From f5e6f5a45e6ff9d78f895557f8fae479d67f9a26 Mon Sep 17 00:00:00 2001 From: Jann Stute Date: Mon, 24 Feb 2025 01:05:05 +0100 Subject: [PATCH 1/9] feat: implement first class for translated widget --- tagstudio/src/qt/translations.py | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/tagstudio/src/qt/translations.py b/tagstudio/src/qt/translations.py index fae788aca..6494f25e1 100644 --- a/tagstudio/src/qt/translations.py +++ b/tagstudio/src/qt/translations.py @@ -1,11 +1,13 @@ +from abc import abstractmethod from pathlib import Path from typing import Callable +from weakref import WeakSet import structlog import ujson from PySide6.QtCore import QObject, Signal from PySide6.QtGui import QAction -from PySide6.QtWidgets import QLabel, QMenu, QMessageBox, QPushButton +from PySide6.QtWidgets import QLabel, QMenu, QMessageBox, QPushButton, QWidget from .helpers.qbutton_wrapper import QPushButtonWrapper @@ -29,13 +31,14 @@ def value(self) -> str: return self.__value or self.__default_value @value.setter - def value(self, value: str): + def value(self, value: str | None): if self.__value != value: self.__value = value self.changed.emit(self.__value) class Translator: + _watchers: WeakSet["TranslationWatcher"] = WeakSet() _strings: dict[str, TranslatedString] = {} _lang: str = DEFAULT_TRANSLATION @@ -50,11 +53,16 @@ def __get_translation_dict(self, lang: str) -> dict[str, str]: ) as f: return ujson.loads(f.read()) + def register_translation_watcher(self, widget: "TranslationWatcher"): + self._watchers.add(widget) + def change_language(self, lang: str): self._lang = lang translated = self.__get_translation_dict(lang) for k in self._strings: self._strings[k].value = translated.get(k, None) + for w in self._watchers: + w.update_text() def translate_qobject(self, widget: QObject, key: str, **kwargs): """Translates the text of the QObject using :func:`translate_with_setter`.""" @@ -95,3 +103,22 @@ def __getitem__(self, key: str) -> str: Translations = Translator() + + +class TranslationWatcher: + def __init__(self): + Translations.register_translation_watcher(self) + + @abstractmethod + def update_text(self): + pass + + +class TQPushButton(QPushButton, TranslationWatcher): + def __init__(self, key: str, parent: QWidget | None = None): + super().__init__(parent) + self.key: str = key + self.update_text() + + def update_text(self): + self.setText(Translations.translate_formatted(self.key)) From b52899dc3e14bd6330e03d338439c4042a6be69e Mon Sep 17 00:00:00 2001 From: Jann Stute Date: Mon, 24 Feb 2025 01:17:20 +0100 Subject: [PATCH 2/9] feat: add further translated widget types --- tagstudio/src/qt/helpers/qbutton_wrapper.py | 13 +++++ tagstudio/src/qt/translations.py | 55 +++++++++++++++++++-- 2 files changed, 65 insertions(+), 3 deletions(-) diff --git a/tagstudio/src/qt/helpers/qbutton_wrapper.py b/tagstudio/src/qt/helpers/qbutton_wrapper.py index 31d2ad812..56354be29 100644 --- a/tagstudio/src/qt/helpers/qbutton_wrapper.py +++ b/tagstudio/src/qt/helpers/qbutton_wrapper.py @@ -3,6 +3,7 @@ # Created for TagStudio: https://github.com/CyanVoxel/TagStudio from PySide6.QtWidgets import QPushButton +from src.qt.translations import TQPushButton class QPushButtonWrapper(QPushButton): @@ -15,3 +16,15 @@ class QPushButtonWrapper(QPushButton): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.is_connected = False + + +class TQPushButtonWrapper(TQPushButton): + """Custom QPushButton wrapper. + + This is a customized implementation of the PySide6 QPushButton that allows to suppress + the warning that is triggered by disconnecting a signal that is not currently connected. + """ + + def __init__(self, text_key: str, *args, **kwargs): + super().__init__(text_key, *args, **kwargs) + self.is_connected = False diff --git a/tagstudio/src/qt/translations.py b/tagstudio/src/qt/translations.py index 6494f25e1..0ad39a2e5 100644 --- a/tagstudio/src/qt/translations.py +++ b/tagstudio/src/qt/translations.py @@ -114,11 +114,60 @@ def update_text(self): pass +# TODO: there is a LOT of duplicated code in these following classes - +# maybe generate them from a template (if that is even possible)? + + class TQPushButton(QPushButton, TranslationWatcher): - def __init__(self, key: str, parent: QWidget | None = None): + def __init__(self, text_key: str, parent: QWidget | None = None, **kwargs): + super().__init__(parent) + self.text_key: str = text_key + self.format_args = kwargs + self.update_text() + + def update_text(self): + self.setText(Translations.translate_formatted(self.text_key, **self.format_args)) + + +class TQLabel(QLabel, TranslationWatcher): + def __init__(self, text_key: str, parent: QWidget | None = None, **kwargs): + super().__init__(parent) + self.text_key: str = text_key + self.format_args = kwargs + self.update_text() + + def update_text(self): + self.setText(Translations.translate_formatted(self.text_key, **self.format_args)) + + +class TQAction(QAction, TranslationWatcher): + def __init__(self, text_key: str, parent: QObject | None = None, **kwargs): + super().__init__(parent) + self.text_key: str = text_key + self.format_args = kwargs + self.update_text() + + def update_text(self): + self.setText(Translations.translate_formatted(self.text_key, **self.format_args)) + + +class TQMessageBox(QMessageBox, TranslationWatcher): + def __init__(self, text_key: str, parent: QWidget | None = None, **kwargs): + super().__init__(parent) + self.text_key: str = text_key + self.format_args = kwargs + self.update_text() + + def update_text(self): + self.setText(Translations.translate_formatted(self.text_key, **self.format_args)) + + +class TQMenu(QMenu, TranslationWatcher): + def __init__(self, title_key: str, parent: QWidget | None = None, **kwargs): super().__init__(parent) - self.key: str = key + self.title_key: str = title_key + self.format_args = kwargs self.update_text() def update_text(self): - self.setText(Translations.translate_formatted(self.key)) + self.setTitle(Translations.translate_formatted(self.title_key, **self.format_args)) From b354385ed5312308d309cb28db4ff8cd86bdd23c Mon Sep 17 00:00:00 2001 From: Jann Stute Date: Mon, 24 Feb 2025 02:03:04 +0100 Subject: [PATCH 3/9] refactor: replace usages of translate_qobject with appropriate classes --- tagstudio/src/qt/helpers/file_opener.py | 9 +- tagstudio/src/qt/main_window.py | 5 +- tagstudio/src/qt/modals/about.py | 16 +-- tagstudio/src/qt/modals/add_field.py | 13 +-- tagstudio/src/qt/modals/build_color.py | 21 ++-- tagstudio/src/qt/modals/build_namespace.py | 17 +-- tagstudio/src/qt/modals/build_tag.py | 20 ++-- tagstudio/src/qt/modals/delete_unlinked.py | 18 +-- tagstudio/src/qt/modals/drop_import.py | 15 +-- tagstudio/src/qt/modals/file_extension.py | 10 +- tagstudio/src/qt/modals/fix_dupes.py | 24 ++-- tagstudio/src/qt/modals/fix_unlinked.py | 22 ++-- tagstudio/src/qt/modals/folders_to_tags.py | 14 +-- tagstudio/src/qt/modals/mirror_entities.py | 15 +-- tagstudio/src/qt/modals/settings_panel.py | 10 +- tagstudio/src/qt/modals/tag_color_manager.py | 12 +- tagstudio/src/qt/modals/tag_database.py | 11 +- tagstudio/src/qt/modals/tag_search.py | 13 +-- tagstudio/src/qt/translations.py | 11 -- tagstudio/src/qt/ts_qt.py | 110 ++++++------------ tagstudio/src/qt/widgets/color_box.py | 7 +- tagstudio/src/qt/widgets/item_thumb.py | 13 +-- tagstudio/src/qt/widgets/landing.py | 9 +- tagstudio/src/qt/widgets/migration_modal.py | 33 ++---- .../widgets/paged_panel/paged_panel_state.py | 9 +- tagstudio/src/qt/widgets/panel.py | 11 +- .../src/qt/widgets/preview/file_attributes.py | 4 +- .../src/qt/widgets/preview/preview_thumb.py | 10 +- tagstudio/src/qt/widgets/preview_panel.py | 8 +- tagstudio/src/qt/widgets/tag_color_preview.py | 2 +- tagstudio/src/qt/widgets/video_player.py | 8 +- 31 files changed, 169 insertions(+), 331 deletions(-) diff --git a/tagstudio/src/qt/helpers/file_opener.py b/tagstudio/src/qt/helpers/file_opener.py index 8650be0be..1b850d713 100644 --- a/tagstudio/src/qt/helpers/file_opener.py +++ b/tagstudio/src/qt/helpers/file_opener.py @@ -12,6 +12,7 @@ from PySide6.QtCore import Qt from PySide6.QtWidgets import QLabel from src.qt.helpers.silent_popen import silent_Popen +from src.qt.translations import TQLabel logger = structlog.get_logger(__name__) @@ -113,14 +114,16 @@ def open_explorer(self): open_file(self.filepath, file_manager=True) -class FileOpenerLabel(QLabel): - def __init__(self, parent=None): +class FileOpenerLabel(TQLabel): + def __init__(self, text_key: str, parent=None, **kwargs): """Initialize the FileOpenerLabel. Args: + text_key (str): The translation key that is passed to the super class. parent (QWidget, optional): The parent widget. Defaults to None. + kwargs: Further keyword arguments that are passed to the super class. """ - super().__init__(parent) + super().__init__(text_key, parent, **kwargs) def set_file_path(self, filepath): """Set the filepath to open. diff --git a/tagstudio/src/qt/main_window.py b/tagstudio/src/qt/main_window.py index c76fa7e93..68df206b1 100644 --- a/tagstudio/src/qt/main_window.py +++ b/tagstudio/src/qt/main_window.py @@ -15,7 +15,7 @@ from src.qt.pagination import Pagination from src.qt.widgets.landing import LandingWidget -from src.qt.translations import Translations +from src.qt.translations import Translations, TQPushButton # Only import for type checking/autocompletion, will not be imported at runtime. if typing.TYPE_CHECKING: @@ -152,8 +152,7 @@ def setupUi(self, MainWindow): self.searchField.setCompleter(self.searchFieldCompleter) self.horizontalLayout_2.addWidget(self.searchField) - self.searchButton = QPushButton(self.centralwidget) - Translations.translate_qobject(self.searchButton, "home.search") + self.searchButton = TQPushButton("home.search", self.centralwidget) self.searchButton.setObjectName(u"searchButton") self.searchButton.setMinimumSize(QSize(0, 32)) diff --git a/tagstudio/src/qt/modals/about.py b/tagstudio/src/qt/modals/about.py index 7e04e3383..d17cdbd65 100644 --- a/tagstudio/src/qt/modals/about.py +++ b/tagstudio/src/qt/modals/about.py @@ -9,14 +9,13 @@ from PySide6.QtWidgets import ( QHBoxLayout, QLabel, - QPushButton, QVBoxLayout, QWidget, ) from src.core.constants import VERSION, VERSION_BRANCH from src.qt.modals.ffmpeg_checker import FfmpegChecker from src.qt.resource_manager import ResourceManager -from src.qt.translations import Translations +from src.qt.translations import TQLabel, TQPushButton, Translations class AboutModal(QWidget): @@ -42,10 +41,6 @@ def __init__(self, config_path): self.logo_widget.setAlignment(Qt.AlignmentFlag.AlignHCenter) self.logo_widget.setContentsMargins(0, 0, 0, 20) - self.content_widget = QLabel() - self.content_widget.setObjectName("contentLabel") - self.content_widget.setWordWrap(True) - self.content_widget.setOpenExternalLinks(True) ff_version = self.fc.version() ffmpeg = 'Missing' if ff_version["ffmpeg"] is not None: @@ -53,8 +48,7 @@ def __init__(self, config_path): ffprobe = 'Missing' if ff_version["ffprobe"] is not None: ffprobe = 'Found (' + ff_version["ffprobe"] + ")" - Translations.translate_qobject( - self.content_widget, + self.content_widget = TQLabel( "about.content", version=VERSION, branch=VERSION_BRANCH, @@ -62,14 +56,16 @@ def __init__(self, config_path): ffmpeg=ffmpeg, ffprobe=ffprobe, ) + self.content_widget.setObjectName("contentLabel") + self.content_widget.setWordWrap(True) + self.content_widget.setOpenExternalLinks(True) self.content_widget.setAlignment(Qt.AlignmentFlag.AlignHCenter) self.button_widget = QWidget() self.button_layout = QHBoxLayout(self.button_widget) self.button_layout.addStretch(1) - self.close_button = QPushButton() - Translations.translate_qobject(self.close_button, "generic.close") + self.close_button = TQPushButton("generic.close") self.close_button.clicked.connect(lambda: self.close()) self.close_button.setMaximumWidth(80) diff --git a/tagstudio/src/qt/modals/add_field.py b/tagstudio/src/qt/modals/add_field.py index 34e4021be..6041005ba 100644 --- a/tagstudio/src/qt/modals/add_field.py +++ b/tagstudio/src/qt/modals/add_field.py @@ -8,15 +8,13 @@ from PySide6.QtCore import Qt, Signal from PySide6.QtWidgets import ( QHBoxLayout, - QLabel, QListWidget, QListWidgetItem, - QPushButton, QVBoxLayout, QWidget, ) from src.core.library import Library -from src.qt.translations import Translations +from src.qt.translations import TQLabel, TQPushButton, Translations logger = structlog.get_logger(__name__) @@ -37,11 +35,10 @@ def __init__(self, library: Library): self.root_layout = QVBoxLayout(self) self.root_layout.setContentsMargins(6, 6, 6, 6) - self.title_widget = QLabel() + self.title_widget = TQLabel("library.field.add") self.title_widget.setObjectName("fieldTitle") self.title_widget.setWordWrap(True) self.title_widget.setStyleSheet("font-weight:bold;" "font-size:14px;" "padding-top: 6px;") - Translations.translate_qobject(self.title_widget, "library.field.add") self.title_widget.setAlignment(Qt.AlignmentFlag.AlignCenter) self.list_widget = QListWidget() @@ -51,13 +48,11 @@ def __init__(self, library: Library): self.button_layout.setContentsMargins(6, 6, 6, 6) self.button_layout.addStretch(1) - self.cancel_button = QPushButton() - Translations.translate_qobject(self.cancel_button, "generic.cancel") + self.cancel_button = TQPushButton("generic.cancel") self.cancel_button.clicked.connect(self.hide) self.button_layout.addWidget(self.cancel_button) - self.save_button = QPushButton() - Translations.translate_qobject(self.save_button, "generic.add") + self.save_button = TQPushButton("generic.add") self.save_button.setDefault(True) self.save_button.clicked.connect(self.hide) self.save_button.clicked.connect( diff --git a/tagstudio/src/qt/modals/build_color.py b/tagstudio/src/qt/modals/build_color.py index 6914a0beb..339aa65d9 100644 --- a/tagstudio/src/qt/modals/build_color.py +++ b/tagstudio/src/qt/modals/build_color.py @@ -13,7 +13,6 @@ QColorDialog, QFormLayout, QHBoxLayout, - QLabel, QLineEdit, QPushButton, QVBoxLayout, @@ -25,7 +24,7 @@ from src.core.library.alchemy.library import slugify from src.core.library.alchemy.models import TagColorGroup from src.core.palette import ColorType, UiColor, get_tag_color, get_ui_color -from src.qt.translations import Translations +from src.qt.translations import TQLabel, TQPushButton, Translations from src.qt.widgets.panel import PanelWidget from src.qt.widgets.tag import ( get_border_color, @@ -72,8 +71,7 @@ def __init__(self, library: Library, color_group: TagColorGroup): self.preview_layout.addWidget(self.preview_button) # Name ----------------------------------------------------------------- - self.name_title = QLabel() - Translations.translate_qobject(self.name_title, "library_object.name") + self.name_title = TQLabel("library_object.name") self.name_field = QLineEdit() self.name_field.setFixedHeight(24) self.name_field.textChanged.connect(self.on_text_changed) @@ -83,8 +81,7 @@ def __init__(self, library: Library, color_group: TagColorGroup): self.form_layout.addRow(self.name_title, self.name_field) # Slug ----------------------------------------------------------------- - self.slug_title = QLabel() - Translations.translate_qobject(self.slug_title, "library_object.slug") + self.slug_title = TQLabel("library_object.slug") self.slug_field = QLineEdit() self.slug_field.setEnabled(False) self.slug_field.setFixedHeight(24) @@ -94,8 +91,7 @@ def __init__(self, library: Library, color_group: TagColorGroup): self.form_layout.addRow(self.slug_title, self.slug_field) # Primary -------------------------------------------------------------- - self.primary_title = QLabel() - Translations.translate_qobject(self.primary_title, "color.primary") + self.primary_title = TQLabel("color.primary") self.primary_button = QPushButton() self.primary_button.setMinimumSize(44, 22) self.primary_button.setMaximumHeight(22) @@ -108,8 +104,7 @@ def __init__(self, library: Library, color_group: TagColorGroup): self.secondary_layout = QHBoxLayout(self.secondary_widget) self.secondary_layout.setContentsMargins(0, 0, 0, 0) self.secondary_layout.setSpacing(6) - self.secondary_title = QLabel() - Translations.translate_qobject(self.secondary_title, "color.secondary") + self.secondary_title = TQLabel("color.secondary") self.secondary_button = QPushButton() self.secondary_button.setMinimumSize(44, 22) self.secondary_button.setMaximumHeight(22) @@ -117,8 +112,7 @@ def __init__(self, library: Library, color_group: TagColorGroup): self.secondary_button.clicked.connect(self.secondary_color_callback) self.secondary_layout.addWidget(self.secondary_button) - self.secondary_reset_button = QPushButton() - Translations.translate_qobject(self.secondary_reset_button, "generic.reset") + self.secondary_reset_button = TQPushButton("generic.reset") self.secondary_reset_button.clicked.connect(self.update_secondary) self.secondary_layout.addWidget(self.secondary_reset_button) self.secondary_layout.setStretch(0, 3) @@ -143,8 +137,7 @@ def __init__(self, library: Library, color_group: TagColorGroup): ) ) self.border_layout.addWidget(self.border_checkbox) - self.border_label = QLabel() - Translations.translate_qobject(self.border_label, "color.color_border") + self.border_label = TQLabel("color.color_border") self.border_layout.addWidget(self.border_label) primary_color = QColor(get_tag_color(ColorType.PRIMARY, TagColorEnum.DEFAULT)) diff --git a/tagstudio/src/qt/modals/build_namespace.py b/tagstudio/src/qt/modals/build_namespace.py index 5b34c2edd..c01f0ac7d 100644 --- a/tagstudio/src/qt/modals/build_namespace.py +++ b/tagstudio/src/qt/modals/build_namespace.py @@ -9,7 +9,6 @@ import structlog from PySide6.QtCore import Qt, Signal from PySide6.QtWidgets import ( - QLabel, QLineEdit, QVBoxLayout, QWidget, @@ -19,7 +18,7 @@ from src.core.library.alchemy.library import ReservedNamespaceError, slugify from src.core.library.alchemy.models import Namespace from src.core.palette import ColorType, UiColor, get_ui_color -from src.qt.translations import Translations +from src.qt.translations import TQLabel, Translations from src.qt.widgets.panel import PanelWidget logger = structlog.get_logger(__name__) @@ -48,8 +47,7 @@ def __init__(self, library: Library, namespace: Namespace | None = None): self.name_layout.setContentsMargins(0, 0, 0, 0) self.name_layout.setSpacing(0) self.name_layout.setAlignment(Qt.AlignmentFlag.AlignLeft) - self.name_title = QLabel() - Translations.translate_qobject(self.name_title, "library_object.name") + self.name_title = TQLabel("library_object.name") self.name_layout.addWidget(self.name_title) self.name_field = QLineEdit() self.name_field.setFixedHeight(24) @@ -66,8 +64,7 @@ def __init__(self, library: Library, namespace: Namespace | None = None): self.slug_layout.setContentsMargins(0, 0, 0, 0) self.slug_layout.setSpacing(0) self.slug_layout.setAlignment(Qt.AlignmentFlag.AlignLeft) - self.slug_title = QLabel() - Translations.translate_qobject(self.slug_title, "library_object.slug") + self.slug_title = TQLabel("library_object.slug") self.slug_layout.addWidget(self.slug_title) self.slug_field = QLineEdit() self.slug_field.setFixedHeight(24) @@ -78,14 +75,10 @@ def __init__(self, library: Library, namespace: Namespace | None = None): self.slug_layout.addWidget(self.slug_field) # Description ---------------------------------------------------------- - self.desc_label = QLabel() + self.desc_label = TQLabel("namespace.create.description") self.desc_label.setWordWrap(True) - Translations.translate_with_setter(self.desc_label.setText, "namespace.create.description") - self.desc_color_label = QLabel() + self.desc_color_label = TQLabel("namespace.create.description_color") self.desc_color_label.setWordWrap(True) - Translations.translate_with_setter( - self.desc_color_label.setText, "namespace.create.description_color" - ) # Add Widgets to Layout ================================================ self.root_layout.addWidget(self.name_widget) diff --git a/tagstudio/src/qt/modals/build_tag.py b/tagstudio/src/qt/modals/build_tag.py index 2732a43a8..f56f76bc9 100644 --- a/tagstudio/src/qt/modals/build_tag.py +++ b/tagstudio/src/qt/modals/build_tag.py @@ -30,7 +30,7 @@ from src.core.palette import ColorType, UiColor, get_tag_color, get_ui_color from src.qt.modals.tag_color_selection import TagColorSelection from src.qt.modals.tag_search import TagSearchPanel -from src.qt.translations import Translations +from src.qt.translations import TQLabel, Translations from src.qt.widgets.panel import PanelModal, PanelWidget from src.qt.widgets.tag import ( TagWidget, @@ -86,8 +86,7 @@ def __init__(self, library: Library, tag: Tag | None = None): self.name_layout.setContentsMargins(0, 0, 0, 0) self.name_layout.setSpacing(0) self.name_layout.setAlignment(Qt.AlignmentFlag.AlignLeft) - self.name_title = QLabel() - Translations.translate_qobject(self.name_title, "tag.name") + self.name_title = TQLabel("tag.name") self.name_layout.addWidget(self.name_title) self.name_field = QLineEdit() self.name_field.setFixedHeight(24) @@ -104,8 +103,7 @@ def __init__(self, library: Library, tag: Tag | None = None): self.shorthand_layout.setContentsMargins(0, 0, 0, 0) self.shorthand_layout.setSpacing(0) self.shorthand_layout.setAlignment(Qt.AlignmentFlag.AlignLeft) - self.shorthand_title = QLabel() - Translations.translate_qobject(self.shorthand_title, "tag.shorthand") + self.shorthand_title = TQLabel("tag.shorthand") self.shorthand_layout.addWidget(self.shorthand_title) self.shorthand_field = QLineEdit() self.shorthand_layout.addWidget(self.shorthand_field) @@ -117,8 +115,7 @@ def __init__(self, library: Library, tag: Tag | None = None): self.aliases_layout.setContentsMargins(0, 0, 0, 0) self.aliases_layout.setSpacing(0) self.aliases_layout.setAlignment(Qt.AlignmentFlag.AlignLeft) - self.aliases_title = QLabel() - Translations.translate_qobject(self.aliases_title, "tag.aliases") + self.aliases_title = TQLabel("tag.aliases") self.aliases_layout.addWidget(self.aliases_title) self.aliases_table = QTableWidget(0, 2) @@ -144,8 +141,7 @@ def __init__(self, library: Library, tag: Tag | None = None): self.disam_button_group = QButtonGroup(self) self.disam_button_group.setExclusive(False) - self.parent_tags_title = QLabel() - Translations.translate_qobject(self.parent_tags_title, "tag.parent_tags") + self.parent_tags_title = TQLabel("tag.parent_tags") self.parent_tags_layout.addWidget(self.parent_tags_title) self.scroll_contents = QWidget() @@ -184,8 +180,7 @@ def __init__(self, library: Library, tag: Tag | None = None): self.color_layout.setContentsMargins(0, 0, 0, 6) self.color_layout.setSpacing(6) self.color_layout.setAlignment(Qt.AlignmentFlag.AlignLeft) - self.color_title = QLabel() - Translations.translate_qobject(self.color_title, "tag.color") + self.color_title = TQLabel("tag.color") self.color_layout.addWidget(self.color_title) self.color_button: TagColorPreview try: @@ -214,8 +209,7 @@ def __init__(self, library: Library, tag: Tag | None = None): self.cat_layout.setContentsMargins(0, 0, 0, 0) self.cat_layout.setSpacing(6) self.cat_layout.setAlignment(Qt.AlignmentFlag.AlignLeft) - self.cat_title = QLabel() - Translations.translate_qobject(self.cat_title, "tag.is_category") + self.cat_title = TQLabel("tag.is_category") self.cat_checkbox = QCheckBox() self.cat_checkbox.setFixedSize(22, 22) diff --git a/tagstudio/src/qt/modals/delete_unlinked.py b/tagstudio/src/qt/modals/delete_unlinked.py index e427f30b4..689f79576 100644 --- a/tagstudio/src/qt/modals/delete_unlinked.py +++ b/tagstudio/src/qt/modals/delete_unlinked.py @@ -9,15 +9,13 @@ from PySide6.QtGui import QStandardItem, QStandardItemModel from PySide6.QtWidgets import ( QHBoxLayout, - QLabel, QListView, - QPushButton, QVBoxLayout, QWidget, ) from src.core.utils.missing_files import MissingRegistry from src.qt.helpers.custom_runnable import CustomRunnable -from src.qt.translations import Translations +from src.qt.translations import TQLabel, TQPushButton, Translations from src.qt.widgets.progress import ProgressWidget # Only import for type checking/autocompletion, will not be imported at runtime. @@ -38,14 +36,12 @@ def __init__(self, driver: "QtDriver", tracker: MissingRegistry): self.root_layout = QVBoxLayout(self) self.root_layout.setContentsMargins(6, 6, 6, 6) - self.desc_widget = QLabel() - self.desc_widget.setObjectName("descriptionLabel") - self.desc_widget.setWordWrap(True) - Translations.translate_qobject( - self.desc_widget, + self.desc_widget = TQLabel( "entries.unlinked.delete.confirm", count=self.tracker.missing_file_entries_count, ) + self.desc_widget.setObjectName("descriptionLabel") + self.desc_widget.setWordWrap(True) self.desc_widget.setAlignment(Qt.AlignmentFlag.AlignCenter) self.list_view = QListView() @@ -57,14 +53,12 @@ def __init__(self, driver: "QtDriver", tracker: MissingRegistry): self.button_layout.setContentsMargins(6, 6, 6, 6) self.button_layout.addStretch(1) - self.cancel_button = QPushButton() - Translations.translate_qobject(self.cancel_button, "generic.cancel_alt") + self.cancel_button = TQPushButton("generic.cancel_alt") self.cancel_button.setDefault(True) self.cancel_button.clicked.connect(self.hide) self.button_layout.addWidget(self.cancel_button) - self.delete_button = QPushButton() - Translations.translate_qobject(self.delete_button, "generic.delete_alt") + self.delete_button = TQPushButton("generic.delete_alt") self.delete_button.clicked.connect(self.hide) self.delete_button.clicked.connect(lambda: self.delete_entries()) self.button_layout.addWidget(self.delete_button) diff --git a/tagstudio/src/qt/modals/drop_import.py b/tagstudio/src/qt/modals/drop_import.py index 4354403f6..29bfaca6a 100644 --- a/tagstudio/src/qt/modals/drop_import.py +++ b/tagstudio/src/qt/modals/drop_import.py @@ -15,11 +15,10 @@ QHBoxLayout, QLabel, QListView, - QPushButton, QVBoxLayout, QWidget, ) -from src.qt.translations import Translations +from src.qt.translations import TQPushButton, Translations from src.qt.widgets.progress import ProgressWidget if TYPE_CHECKING: @@ -67,26 +66,22 @@ def __init__(self, driver: "QtDriver"): self.button_layout.setContentsMargins(6, 6, 6, 6) self.button_layout.addStretch(1) - self.skip_button = QPushButton() - Translations.translate_qobject(self.skip_button, "generic.skip_alt") + self.skip_button = TQPushButton("generic.skip_alt") self.skip_button.setDefault(True) self.skip_button.clicked.connect(lambda: self.begin_transfer(DuplicateChoice.SKIP)) self.button_layout.addWidget(self.skip_button) - self.overwrite_button = QPushButton() - Translations.translate_qobject(self.overwrite_button, "generic.overwrite_alt") + self.overwrite_button = TQPushButton("generic.overwrite_alt") self.overwrite_button.clicked.connect( lambda: self.begin_transfer(DuplicateChoice.OVERWRITE) ) self.button_layout.addWidget(self.overwrite_button) - self.rename_button = QPushButton() - Translations.translate_qobject(self.rename_button, "generic.rename_alt") + self.rename_button = TQPushButton("generic.rename_alt") self.rename_button.clicked.connect(lambda: self.begin_transfer(DuplicateChoice.RENAME)) self.button_layout.addWidget(self.rename_button) - self.cancel_button = QPushButton() - Translations.translate_qobject(self.cancel_button, "generic.cancel_alt") + self.cancel_button = TQPushButton("generic.cancel_alt") self.cancel_button.clicked.connect(lambda: self.begin_transfer(DuplicateChoice.CANCEL)) self.button_layout.addWidget(self.cancel_button) diff --git a/tagstudio/src/qt/modals/file_extension.py b/tagstudio/src/qt/modals/file_extension.py index 49b5b1478..d020c0b36 100644 --- a/tagstudio/src/qt/modals/file_extension.py +++ b/tagstudio/src/qt/modals/file_extension.py @@ -7,9 +7,7 @@ from PySide6.QtWidgets import ( QComboBox, QHBoxLayout, - QLabel, QLineEdit, - QPushButton, QStyledItemDelegate, QTableWidget, QTableWidgetItem, @@ -18,7 +16,7 @@ ) from src.core.enums import LibraryPrefs from src.core.library import Library -from src.qt.translations import Translations +from src.qt.translations import TQLabel, TQPushButton, Translations from src.qt.widgets.panel import PanelWidget @@ -50,8 +48,7 @@ def __init__(self, library: "Library"): self.table.setItemDelegate(FileExtensionItemDelegate()) # Create "Add Button" Widget ------------------------------------------- - self.add_button = QPushButton() - Translations.translate_qobject(self.add_button, "ignore_list.add_extension") + self.add_button = TQPushButton("ignore_list.add_extension") self.add_button.clicked.connect(self.add_item) self.add_button.setDefault(True) self.add_button.setMinimumWidth(100) @@ -61,8 +58,7 @@ def __init__(self, library: "Library"): self.mode_layout = QHBoxLayout(self.mode_widget) self.mode_layout.setContentsMargins(0, 0, 0, 0) self.mode_layout.setSpacing(12) - self.mode_label = QLabel() - Translations.translate_qobject(self.mode_label, "ignore_list.mode.label") + self.mode_label = TQLabel("ignore_list.mode.label") self.mode_combobox = QComboBox() self.mode_combobox.setEditable(False) self.mode_combobox.addItem("") diff --git a/tagstudio/src/qt/modals/fix_dupes.py b/tagstudio/src/qt/modals/fix_dupes.py index da504b6b6..143dfa609 100644 --- a/tagstudio/src/qt/modals/fix_dupes.py +++ b/tagstudio/src/qt/modals/fix_dupes.py @@ -11,14 +11,13 @@ QFileDialog, QHBoxLayout, QLabel, - QPushButton, QVBoxLayout, QWidget, ) from src.core.library import Library from src.core.utils.dupe_files import DupeRegistry from src.qt.modals.mirror_entities import MirrorEntriesModal -from src.qt.translations import Translations +from src.qt.translations import TQLabel, TQPushButton, Translations # Only import for type checking/autocompletion, will not be imported at runtime. if TYPE_CHECKING: @@ -40,11 +39,10 @@ def __init__(self, library: "Library", driver: "QtDriver"): self.tracker = DupeRegistry(library=self.lib) - self.desc_widget = QLabel() + self.desc_widget = TQLabel("file.duplicates.description") self.desc_widget.setObjectName("descriptionLabel") self.desc_widget.setWordWrap(True) self.desc_widget.setStyleSheet("text-align:left;") - Translations.translate_qobject(self.desc_widget, "file.duplicates.description") self.desc_widget.setAlignment(Qt.AlignmentFlag.AlignCenter) self.dupe_count = QLabel() @@ -52,35 +50,29 @@ def __init__(self, library: "Library", driver: "QtDriver"): self.dupe_count.setStyleSheet("font-weight:bold;" "font-size:14px;" "") self.dupe_count.setAlignment(Qt.AlignmentFlag.AlignCenter) - self.file_label = QLabel() + self.file_label = TQLabel("file.duplicates.dupeguru.no_file") self.file_label.setObjectName("fileLabel") - Translations.translate_qobject(self.file_label, "file.duplicates.dupeguru.no_file") - self.open_button = QPushButton() - Translations.translate_qobject(self.open_button, "file.duplicates.dupeguru.load_file") + self.open_button = TQPushButton("file.duplicates.dupeguru.load_file") self.open_button.clicked.connect(self.select_file) self.mirror_modal = MirrorEntriesModal(self.driver, self.tracker) self.mirror_modal.done.connect(self.refresh_dupes) - self.mirror_button = QPushButton() - Translations.translate_qobject(self.mirror_button, "file.duplicates.mirror_entries") + self.mirror_button = TQPushButton("file.duplicates.mirror_entries") self.mirror_button.clicked.connect(self.mirror_modal.show) - self.mirror_desc = QLabel() + self.mirror_desc = TQLabel("file.duplicates.mirror.description") self.mirror_desc.setWordWrap(True) - Translations.translate_qobject(self.mirror_desc, "file.duplicates.mirror.description") - self.advice_label = QLabel() + self.advice_label = TQLabel("file.duplicates.dupeguru.advice") self.advice_label.setWordWrap(True) - Translations.translate_qobject(self.advice_label, "file.duplicates.dupeguru.advice") self.button_container = QWidget() self.button_layout = QHBoxLayout(self.button_container) self.button_layout.setContentsMargins(6, 6, 6, 6) self.button_layout.addStretch(1) - self.done_button = QPushButton() - Translations.translate_qobject(self.done_button, "generic.done_alt") + self.done_button = TQPushButton("generic.done_alt") self.done_button.setDefault(True) self.done_button.clicked.connect(self.hide) self.button_layout.addWidget(self.done_button) diff --git a/tagstudio/src/qt/modals/fix_unlinked.py b/tagstudio/src/qt/modals/fix_unlinked.py index e4eb5ed44..b232bf4ef 100644 --- a/tagstudio/src/qt/modals/fix_unlinked.py +++ b/tagstudio/src/qt/modals/fix_unlinked.py @@ -7,13 +7,13 @@ from PySide6 import QtCore, QtGui from PySide6.QtCore import Qt -from PySide6.QtWidgets import QHBoxLayout, QLabel, QPushButton, QVBoxLayout, QWidget +from PySide6.QtWidgets import QHBoxLayout, QLabel, QVBoxLayout, QWidget from src.core.library import Library from src.core.utils.missing_files import MissingRegistry from src.qt.modals.delete_unlinked import DeleteUnlinkedEntriesModal from src.qt.modals.merge_dupe_entries import MergeDuplicateEntries from src.qt.modals.relink_unlinked import RelinkUnlinkedEntries -from src.qt.translations import Translations +from src.qt.translations import TQLabel, TQPushButton, Translations from src.qt.widgets.progress import ProgressWidget # Only import for type checking/autocompletion, will not be imported at runtime. @@ -37,11 +37,10 @@ def __init__(self, library: "Library", driver: "QtDriver"): self.root_layout = QVBoxLayout(self) self.root_layout.setContentsMargins(6, 6, 6, 6) - self.unlinked_desc_widget = QLabel() + self.unlinked_desc_widget = TQLabel("entries.unlinked.description") self.unlinked_desc_widget.setObjectName("unlinkedDescriptionLabel") self.unlinked_desc_widget.setWordWrap(True) self.unlinked_desc_widget.setStyleSheet("text-align:left;") - Translations.translate_qobject(self.unlinked_desc_widget, "entries.unlinked.description") self.missing_count_label = QLabel() self.missing_count_label.setObjectName("missingCountLabel") @@ -53,15 +52,13 @@ def __init__(self, library: "Library", driver: "QtDriver"): self.dupe_count_label.setStyleSheet("font-weight:bold;" "font-size:14px;") self.dupe_count_label.setAlignment(Qt.AlignmentFlag.AlignCenter) - self.refresh_unlinked_button = QPushButton() - Translations.translate_qobject(self.refresh_unlinked_button, "entries.unlinked.refresh_all") + self.refresh_unlinked_button = TQPushButton("entries.unlinked.refresh_all") self.refresh_unlinked_button.clicked.connect(self.refresh_missing_files) self.merge_class = MergeDuplicateEntries(self.lib, self.driver) self.relink_class = RelinkUnlinkedEntries(self.tracker) - self.search_button = QPushButton() - Translations.translate_qobject(self.search_button, "entries.unlinked.search_and_relink") + self.search_button = TQPushButton("entries.unlinked.search_and_relink") self.relink_class.done.connect( # refresh the grid lambda: ( @@ -71,11 +68,10 @@ def __init__(self, library: "Library", driver: "QtDriver"): ) self.search_button.clicked.connect(self.relink_class.repair_entries) - self.manual_button = QPushButton() - Translations.translate_qobject(self.manual_button, "entries.unlinked.relink.manual") + self.manual_button = TQPushButton("entries.unlinked.relink.manual") self.manual_button.setHidden(True) - self.delete_button = QPushButton() + self.delete_button = TQPushButton("entries.unlinked.delete_alt") self.delete_modal = DeleteUnlinkedEntriesModal(self.driver, self.tracker) self.delete_modal.done.connect( lambda: ( @@ -84,7 +80,6 @@ def __init__(self, library: "Library", driver: "QtDriver"): self.driver.filter_items(), ) ) - Translations.translate_qobject(self.delete_button, "entries.unlinked.delete_alt") self.delete_button.clicked.connect(self.delete_modal.show) self.button_container = QWidget() @@ -92,8 +87,7 @@ def __init__(self, library: "Library", driver: "QtDriver"): self.button_layout.setContentsMargins(6, 6, 6, 6) self.button_layout.addStretch(1) - self.done_button = QPushButton() - Translations.translate_qobject(self.done_button, "generic.done_alt") + self.done_button = TQPushButton("generic.done_alt") self.done_button.setDefault(True) self.done_button.clicked.connect(self.hide) self.button_layout.addWidget(self.done_button) diff --git a/tagstudio/src/qt/modals/folders_to_tags.py b/tagstudio/src/qt/modals/folders_to_tags.py index 0b50fa460..07b5b8e13 100644 --- a/tagstudio/src/qt/modals/folders_to_tags.py +++ b/tagstudio/src/qt/modals/folders_to_tags.py @@ -25,7 +25,7 @@ from src.core.library.alchemy.enums import TagColorEnum from src.core.palette import ColorType, get_tag_color from src.qt.flowlayout import FlowLayout -from src.qt.translations import Translations +from src.qt.translations import TQLabel, TQPushButton, Translations if TYPE_CHECKING: from src.qt.ts_qt import QtDriver @@ -172,11 +172,10 @@ def __init__(self, library: "Library", driver: "QtDriver"): self.root_layout = QVBoxLayout(self) self.root_layout.setContentsMargins(6, 6, 6, 6) - self.title_widget = QLabel() + self.title_widget = TQLabel("folders_to_tags.title") self.title_widget.setObjectName("title") self.title_widget.setWordWrap(True) self.title_widget.setStyleSheet("font-weight:bold;" "font-size:14px;" "padding-top: 6px") - Translations.translate_qobject(self.title_widget, "folders_to_tags.title") self.title_widget.setAlignment(Qt.AlignmentFlag.AlignCenter) self.desc_widget = QLabel() @@ -191,11 +190,9 @@ def __init__(self, library: "Library", driver: "QtDriver"): self.open_close_button_w = QWidget() self.open_close_button_layout = QHBoxLayout(self.open_close_button_w) - self.open_all_button = QPushButton() - Translations.translate_qobject(self.open_all_button, "folders_to_tags.open_all") + self.open_all_button = TQPushButton("folders_to_tags.open_all") self.open_all_button.clicked.connect(lambda: self.set_all_branches(False)) - self.close_all_button = QPushButton() - Translations.translate_qobject(self.close_all_button, "folders_to_tags.close_all") + self.close_all_button = TQPushButton("folders_to_tags.close_all") self.close_all_button.clicked.connect(lambda: self.set_all_branches(True)) self.open_close_button_layout.addWidget(self.open_all_button) @@ -213,8 +210,7 @@ def __init__(self, library: "Library", driver: "QtDriver"): self.scroll_area.setFrameShape(QFrame.Shape.NoFrame) self.scroll_area.setWidget(self.scroll_contents) - self.apply_button = QPushButton() - Translations.translate_qobject(self.apply_button, "generic.apply_alt") + self.apply_button = TQPushButton("generic.apply_alt") self.apply_button.setMinimumWidth(100) self.apply_button.clicked.connect(self.on_apply) diff --git a/tagstudio/src/qt/modals/mirror_entities.py b/tagstudio/src/qt/modals/mirror_entities.py index 4cb37a1cf..77d3971b3 100644 --- a/tagstudio/src/qt/modals/mirror_entities.py +++ b/tagstudio/src/qt/modals/mirror_entities.py @@ -10,14 +10,12 @@ from PySide6.QtGui import QStandardItem, QStandardItemModel from PySide6.QtWidgets import ( QHBoxLayout, - QLabel, QListView, - QPushButton, QVBoxLayout, QWidget, ) from src.core.utils.dupe_files import DupeRegistry -from src.qt.translations import Translations +from src.qt.translations import TQLabel, TQPushButton, Translations from src.qt.widgets.progress import ProgressWidget # Only import for type checking/autocompletion, will not be imported at runtime. @@ -38,12 +36,9 @@ def __init__(self, driver: "QtDriver", tracker: DupeRegistry): self.root_layout.setContentsMargins(6, 6, 6, 6) self.tracker = tracker - self.desc_widget = QLabel() + self.desc_widget = TQLabel("entries.mirror.confirmation", count=self.tracker.groups_count) self.desc_widget.setObjectName("descriptionLabel") self.desc_widget.setWordWrap(True) - Translations.translate_qobject( - self.desc_widget, "entries.mirror.confirmation", count=self.tracker.groups_count - ) self.desc_widget.setAlignment(Qt.AlignmentFlag.AlignCenter) self.list_view = QListView() @@ -55,14 +50,12 @@ def __init__(self, driver: "QtDriver", tracker: DupeRegistry): self.button_layout.setContentsMargins(6, 6, 6, 6) self.button_layout.addStretch(1) - self.cancel_button = QPushButton() - Translations.translate_qobject(self.cancel_button, "generic.cancel_alt") + self.cancel_button = TQPushButton("generic.cancel_alt") self.cancel_button.setDefault(True) self.cancel_button.clicked.connect(self.hide) self.button_layout.addWidget(self.cancel_button) - self.mirror_button = QPushButton() - Translations.translate_qobject(self.mirror_button, "entries.mirror") + self.mirror_button = TQPushButton("entries.mirror") self.mirror_button.clicked.connect(self.hide) self.mirror_button.clicked.connect(self.mirror_entries) self.button_layout.addWidget(self.mirror_button) diff --git a/tagstudio/src/qt/modals/settings_panel.py b/tagstudio/src/qt/modals/settings_panel.py index a499f6ddb..eaf87a064 100644 --- a/tagstudio/src/qt/modals/settings_panel.py +++ b/tagstudio/src/qt/modals/settings_panel.py @@ -4,9 +4,9 @@ from PySide6.QtCore import Qt -from PySide6.QtWidgets import QComboBox, QFormLayout, QLabel, QVBoxLayout, QWidget +from PySide6.QtWidgets import QComboBox, QFormLayout, QVBoxLayout, QWidget from src.core.enums import SettingItems -from src.qt.translations import Translations +from src.qt.translations import TQLabel from src.qt.widgets.panel import PanelWidget @@ -22,13 +22,11 @@ def __init__(self, driver): self.form_layout = QFormLayout(self.form_container) self.form_layout.setContentsMargins(0, 0, 0, 0) - self.restart_label = QLabel() + self.restart_label = TQLabel("settings.restart_required") self.restart_label.setHidden(True) - Translations.translate_qobject(self.restart_label, "settings.restart_required") self.restart_label.setAlignment(Qt.AlignmentFlag.AlignCenter) - language_label = QLabel() - Translations.translate_qobject(language_label, "settings.language") + language_label = TQLabel("settings.language") self.languages = { # "Cantonese (Traditional)": "yue_Hant", # Empty "Chinese (Traditional)": "zh_Hant", diff --git a/tagstudio/src/qt/modals/tag_color_manager.py b/tagstudio/src/qt/modals/tag_color_manager.py index 9b5f6b94e..f1504bab3 100644 --- a/tagstudio/src/qt/modals/tag_color_manager.py +++ b/tagstudio/src/qt/modals/tag_color_manager.py @@ -13,7 +13,6 @@ QHBoxLayout, QLabel, QMessageBox, - QPushButton, QScrollArea, QSizePolicy, QVBoxLayout, @@ -22,7 +21,7 @@ from src.core.constants import RESERVED_NAMESPACE_PREFIX from src.core.enums import Theme from src.qt.modals.build_namespace import BuildNamespacePanel -from src.qt.translations import Translations +from src.qt.translations import TQPushButton, Translations from src.qt.widgets.color_box import ColorBoxWidget from src.qt.widgets.fields import FieldContainer from src.qt.widgets.panel import PanelModal @@ -91,8 +90,7 @@ def __init__( self.button_layout = QHBoxLayout(self.button_container) self.button_layout.setContentsMargins(6, 6, 6, 6) - self.new_namespace_button = QPushButton() - Translations.translate_qobject(self.new_namespace_button, "namespace.new.button") + self.new_namespace_button = TQPushButton("namespace.new.button") self.new_namespace_button.clicked.connect(self.create_namespace) self.button_layout.addWidget(self.new_namespace_button) @@ -102,8 +100,7 @@ def __init__( self.button_layout.addStretch(1) - self.done_button = QPushButton() - Translations.translate_qobject(self.done_button, "generic.done_alt") + self.done_button = TQPushButton("generic.done_alt") self.done_button.clicked.connect(self.hide) self.button_layout.addWidget(self.done_button) @@ -156,8 +153,7 @@ def setup_color_groups(self): ns_layout = QHBoxLayout(ns_container) ns_layout.setAlignment(Qt.AlignmentFlag.AlignCenter) ns_layout.setContentsMargins(0, 18, 0, 18) - namespace_prompt = QPushButton() - Translations.translate_qobject(namespace_prompt, "namespace.new.prompt") + namespace_prompt = TQPushButton("namespace.new.prompt") namespace_prompt.setFixedSize(namespace_prompt.sizeHint().width() + 8, 24) namespace_prompt.clicked.connect(self.create_namespace) ns_layout.addWidget(namespace_prompt) diff --git a/tagstudio/src/qt/modals/tag_database.py b/tagstudio/src/qt/modals/tag_database.py index b552d8d61..57b3f5057 100644 --- a/tagstudio/src/qt/modals/tag_database.py +++ b/tagstudio/src/qt/modals/tag_database.py @@ -5,13 +5,12 @@ import structlog from PySide6.QtWidgets import ( QMessageBox, - QPushButton, ) from src.core.constants import RESERVED_TAG_END, RESERVED_TAG_START from src.core.library import Library, Tag from src.qt.modals.build_tag import BuildTagPanel from src.qt.modals.tag_search import TagSearchPanel -from src.qt.translations import Translations +from src.qt.translations import TQMessageBox, TQPushButton, Translations from src.qt.widgets.panel import PanelModal logger = structlog.get_logger(__name__) @@ -26,8 +25,7 @@ def __init__(self, driver, library: Library): super().__init__(library, is_tag_chooser=False) self.driver = driver - self.create_tag_button = QPushButton() - Translations.translate_qobject(self.create_tag_button, "tag.create") + self.create_tag_button = TQPushButton("tag.create") self.create_tag_button.clicked.connect(lambda: self.build_tag(self.search_field.text())) self.root_layout.addWidget(self.create_tag_button) @@ -61,11 +59,8 @@ def delete_tag(self, tag: Tag): if tag.id in range(RESERVED_TAG_START, RESERVED_TAG_END): return - message_box = QMessageBox() + message_box = TQMessageBox("tag.confirm_delete", tag_name=self.lib.tag_display_name(tag.id)) Translations.translate_with_setter(message_box.setWindowTitle, "tag.remove") - Translations.translate_qobject( - message_box, "tag.confirm_delete", tag_name=self.lib.tag_display_name(tag.id) - ) message_box.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel) # type: ignore message_box.setIcon(QMessageBox.Question) # type: ignore diff --git a/tagstudio/src/qt/modals/tag_search.py b/tagstudio/src/qt/modals/tag_search.py index c86f55007..0c6f53384 100644 --- a/tagstudio/src/qt/modals/tag_search.py +++ b/tagstudio/src/qt/modals/tag_search.py @@ -16,7 +16,6 @@ QComboBox, QFrame, QHBoxLayout, - QLabel, QLineEdit, QPushButton, QScrollArea, @@ -27,7 +26,7 @@ from src.core.library import Library, Tag from src.core.library.alchemy.enums import FilterState, TagColorEnum from src.core.palette import ColorType, get_tag_color -from src.qt.translations import Translations +from src.qt.translations import TQLabel, TQPushButton, Translations from src.qt.widgets.panel import PanelModal, PanelWidget from src.qt.widgets.tag import ( TagWidget, @@ -77,8 +76,7 @@ def __init__( self.limit_layout.setSpacing(12) self.limit_layout.addStretch(1) - self.limit_title = QLabel() - Translations.translate_qobject(self.limit_title, "tag.view_limit") + self.limit_title = TQLabel("tag.view_limit") self.limit_layout.addWidget(self.limit_title) self.limit_combobox = QComboBox() @@ -119,9 +117,9 @@ def set_driver(self, driver): """Set the QtDriver for this search panel. Used for main window operations.""" self.driver = driver - def build_create_button(self, query: str | None): + def build_create_button(self, query: str | None, key: str, format_args: dict): """Constructs a "Create & Add Tag" QPushButton.""" - create_button = QPushButton(self) + create_button = TQPushButton(key, self, **format_args) create_button.setFlat(True) create_button.setMinimumSize(22, 22) @@ -245,11 +243,10 @@ def update_tags(self, query: str | None = None): # Add back the "Create & Add" button if query and query.strip(): - cb: QPushButton = self.build_create_button(query) + cb: QPushButton = self.build_create_button(query, "tag.create_add", {"query": query}) with catch_warnings(record=True): cb.clicked.disconnect() cb.clicked.connect(lambda: self.create_and_add_tag(query or "")) - Translations.translate_qobject(cb, "tag.create_add", query=query) self.scroll_layout.addWidget(cb) self.create_button_in_layout = True diff --git a/tagstudio/src/qt/translations.py b/tagstudio/src/qt/translations.py index 0ad39a2e5..e8c78a939 100644 --- a/tagstudio/src/qt/translations.py +++ b/tagstudio/src/qt/translations.py @@ -9,8 +9,6 @@ from PySide6.QtGui import QAction from PySide6.QtWidgets import QLabel, QMenu, QMessageBox, QPushButton, QWidget -from .helpers.qbutton_wrapper import QPushButtonWrapper - logger = structlog.get_logger(__name__) DEFAULT_TRANSLATION = "en" @@ -64,15 +62,6 @@ def change_language(self, lang: str): for w in self._watchers: w.update_text() - def translate_qobject(self, widget: QObject, key: str, **kwargs): - """Translates the text of the QObject using :func:`translate_with_setter`.""" - if isinstance(widget, (QLabel, QAction, QPushButton, QMessageBox, QPushButtonWrapper)): - self.translate_with_setter(widget.setText, key, **kwargs) - elif isinstance(widget, (QMenu)): - self.translate_with_setter(widget.setTitle, key, **kwargs) - else: - raise RuntimeError - def translate_with_setter(self, setter: Callable[[str], None], key: str, **kwargs): """Calls `setter` everytime the language changes and passes the translated string for `key`. diff --git a/tagstudio/src/qt/ts_qt.py b/tagstudio/src/qt/ts_qt.py index f02cf8ed3..817a07a96 100644 --- a/tagstudio/src/qt/ts_qt.py +++ b/tagstudio/src/qt/ts_qt.py @@ -43,7 +43,6 @@ QComboBox, QFileDialog, QLineEdit, - QMenu, QMenuBar, QMessageBox, QPushButton, @@ -94,7 +93,7 @@ from src.qt.platform_strings import trash_term from src.qt.resource_manager import ResourceManager from src.qt.splash import Splash -from src.qt.translations import Translations +from src.qt.translations import TQAction, TQMenu, Translations from src.qt.widgets.item_thumb import BadgeType, ItemThumb from src.qt.widgets.migration_modal import JsonMigrationModal from src.qt.widgets.panel import PanelModal @@ -338,22 +337,15 @@ def start(self) -> None: self.main_window.setMenuBar(menu_bar) menu_bar.setNativeMenuBar(True) - file_menu = QMenu(menu_bar) - Translations.translate_qobject(file_menu, "menu.file") - edit_menu = QMenu(menu_bar) - Translations.translate_qobject(edit_menu, "generic.edit_alt") - view_menu = QMenu(menu_bar) - Translations.translate_qobject(view_menu, "menu.view") - tools_menu = QMenu(menu_bar) - Translations.translate_qobject(tools_menu, "menu.tools") - macros_menu = QMenu(menu_bar) - Translations.translate_qobject(macros_menu, "menu.macros") - help_menu = QMenu(menu_bar) - Translations.translate_qobject(help_menu, "menu.help") + file_menu = TQMenu("menu.file", menu_bar) + edit_menu = TQMenu("generic.edit_alt", menu_bar) + view_menu = TQMenu("menu.view", menu_bar) + tools_menu = TQMenu("menu.tools", menu_bar) + macros_menu = TQMenu("menu.macros", menu_bar) + help_menu = TQMenu("menu.help", menu_bar) # File Menu ============================================================ - open_library_action = QAction(menu_bar) - Translations.translate_qobject(open_library_action, "menu.file.open_create_library") + open_library_action = TQAction("menu.file.open_create_library", menu_bar) open_library_action.triggered.connect(lambda: self.open_library_from_dialog()) open_library_action.setShortcut( QtCore.QKeyCombination( @@ -364,15 +356,11 @@ def start(self) -> None: open_library_action.setToolTip("Ctrl+O") file_menu.addAction(open_library_action) - self.open_recent_library_menu = QMenu(menu_bar) - Translations.translate_qobject( - self.open_recent_library_menu, "menu.file.open_recent_library" - ) + self.open_recent_library_menu = TQMenu("menu.file.open_recent_library", menu_bar) file_menu.addMenu(self.open_recent_library_menu) self.update_recent_lib_menu() - self.save_library_backup_action = QAction(menu_bar) - Translations.translate_qobject(self.save_library_backup_action, "menu.file.save_backup") + self.save_library_backup_action = TQAction("menu.file.save_backup", menu_bar) self.save_library_backup_action.triggered.connect( lambda: self.callback_library_needed_check(self.backup_library) ) @@ -390,13 +378,11 @@ def start(self) -> None: file_menu.addAction(self.save_library_backup_action) file_menu.addSeparator() - settings_action = QAction(self) - Translations.translate_qobject(settings_action, "menu.settings") + settings_action = TQAction("menu.settings", self) settings_action.triggered.connect(self.open_settings_modal) file_menu.addAction(settings_action) - open_on_start_action = QAction(self) - Translations.translate_qobject(open_on_start_action, "settings.open_library_on_start") + open_on_start_action = TQAction("settings.open_library_on_start", self) open_on_start_action.setCheckable(True) open_on_start_action.setChecked( bool(self.settings.value(SettingItems.START_LOAD_LAST, defaultValue=True, type=bool)) @@ -408,8 +394,7 @@ def start(self) -> None: file_menu.addSeparator() - self.refresh_dir_action = QAction(menu_bar) - Translations.translate_qobject(self.refresh_dir_action, "menu.file.refresh_directories") + self.refresh_dir_action = TQAction("menu.file.refresh_directories", menu_bar) self.refresh_dir_action.triggered.connect( lambda: self.callback_library_needed_check(self.add_new_files_callback) ) @@ -424,16 +409,14 @@ def start(self) -> None: file_menu.addAction(self.refresh_dir_action) file_menu.addSeparator() - self.close_library_action = QAction(menu_bar) - Translations.translate_qobject(self.close_library_action, "menu.file.close_library") + self.close_library_action = TQAction("menu.file.close_library", menu_bar) self.close_library_action.triggered.connect(self.close_library) self.close_library_action.setEnabled(False) file_menu.addAction(self.close_library_action) file_menu.addSeparator() # Edit Menu ============================================================ - self.new_tag_action = QAction(menu_bar) - Translations.translate_qobject(self.new_tag_action, "menu.edit.new_tag") + self.new_tag_action = TQAction("menu.edit.new_tag", menu_bar) self.new_tag_action.triggered.connect(lambda: self.add_tag_action_callback()) self.new_tag_action.setShortcut( QtCore.QKeyCombination( @@ -447,8 +430,7 @@ def start(self) -> None: edit_menu.addSeparator() - self.select_all_action = QAction(menu_bar) - Translations.translate_qobject(self.select_all_action, "select.all") + self.select_all_action = TQAction("select.all", menu_bar) self.select_all_action.triggered.connect(self.select_all_action_callback) self.select_all_action.setShortcut( QtCore.QKeyCombination( @@ -460,8 +442,7 @@ def start(self) -> None: self.select_all_action.setEnabled(False) edit_menu.addAction(self.select_all_action) - self.clear_select_action = QAction(menu_bar) - Translations.translate_qobject(self.clear_select_action, "select.clear") + self.clear_select_action = TQAction("select.clear", menu_bar) self.clear_select_action.triggered.connect(self.clear_select_action_callback) self.clear_select_action.setShortcut(QtCore.Qt.Key.Key_Escape) self.clear_select_action.setToolTip("Esc") @@ -470,8 +451,7 @@ def start(self) -> None: self.copy_buffer: dict = {"fields": [], "tags": []} - self.copy_fields_action = QAction(menu_bar) - Translations.translate_qobject(self.copy_fields_action, "edit.copy_fields") + self.copy_fields_action = QAction("edit.copy_fields", menu_bar) self.copy_fields_action.triggered.connect(self.copy_fields_action_callback) self.copy_fields_action.setShortcut( QtCore.QKeyCombination( @@ -483,8 +463,7 @@ def start(self) -> None: self.copy_fields_action.setEnabled(False) edit_menu.addAction(self.copy_fields_action) - self.paste_fields_action = QAction(menu_bar) - Translations.translate_qobject(self.paste_fields_action, "edit.paste_fields") + self.paste_fields_action = TQAction("edit.paste_fields", menu_bar) self.paste_fields_action.triggered.connect(self.paste_fields_action_callback) self.paste_fields_action.setShortcut( QtCore.QKeyCombination( @@ -496,10 +475,7 @@ def start(self) -> None: self.paste_fields_action.setEnabled(False) edit_menu.addAction(self.paste_fields_action) - self.add_tag_to_selected_action = QAction(menu_bar) - Translations.translate_qobject( - self.add_tag_to_selected_action, "select.add_tag_to_selected" - ) + self.add_tag_to_selected_action = TQAction("select.add_tag_to_selected", menu_bar) self.add_tag_to_selected_action.triggered.connect(self.add_tag_modal.show) self.add_tag_to_selected_action.setShortcut( QtCore.QKeyCombination( @@ -516,9 +492,8 @@ def start(self) -> None: edit_menu.addSeparator() - self.delete_file_action = QAction(menu_bar) - Translations.translate_qobject( - self.delete_file_action, "menu.delete_selected_files_ambiguous", trash_term=trash_term() + self.delete_file_action = TQAction( + "menu.delete_selected_files_ambiguous", menu_bar, trash_term=trash_term() ) self.delete_file_action.triggered.connect(lambda f="": self.delete_files_callback(f)) self.delete_file_action.setShortcut(QtCore.Qt.Key.Key_Delete) @@ -527,15 +502,11 @@ def start(self) -> None: edit_menu.addSeparator() - self.manage_file_ext_action = QAction(menu_bar) - Translations.translate_qobject( - self.manage_file_ext_action, "menu.edit.manage_file_extensions" - ) + self.manage_file_ext_action = TQAction("menu.edit.manage_file_extensions", menu_bar) edit_menu.addAction(self.manage_file_ext_action) self.manage_file_ext_action.setEnabled(False) - self.tag_manager_action = QAction(menu_bar) - Translations.translate_qobject(self.tag_manager_action, "menu.edit.manage_tags") + self.tag_manager_action = TQAction("menu.edit.manage_tags", menu_bar) self.tag_manager_action.triggered.connect(self.tag_manager_panel.show) self.tag_manager_action.setShortcut( QtCore.QKeyCombination( @@ -547,22 +518,19 @@ def start(self) -> None: self.tag_manager_action.setToolTip("Ctrl+M") edit_menu.addAction(self.tag_manager_action) - self.color_manager_action = QAction(menu_bar) - Translations.translate_qobject(self.color_manager_action, "edit.color_manager") + self.color_manager_action = TQAction("edit.color_manager", menu_bar) self.color_manager_action.triggered.connect(self.color_manager_panel.show) self.color_manager_action.setEnabled(False) edit_menu.addAction(self.color_manager_action) # View Menu ============================================================ - show_libs_list_action = QAction(menu_bar) - Translations.translate_qobject(show_libs_list_action, "settings.show_recent_libraries") + show_libs_list_action = TQAction("settings.show_recent_libraries", menu_bar) show_libs_list_action.setCheckable(True) show_libs_list_action.setChecked( bool(self.settings.value(SettingItems.WINDOW_SHOW_LIBS, defaultValue=True, type=bool)) ) - show_filenames_action = QAction(menu_bar) - Translations.translate_qobject(show_filenames_action, "settings.show_filenames_in_grid") + show_filenames_action = TQAction("settings.show_filenames_in_grid", menu_bar) show_filenames_action.setCheckable(True) show_filenames_action.setChecked( bool(self.settings.value(SettingItems.SHOW_FILENAMES, defaultValue=True, type=bool)) @@ -581,10 +549,7 @@ def create_fix_unlinked_entries_modal(): self.unlinked_modal = FixUnlinkedEntriesModal(self.lib, self) self.unlinked_modal.show() - self.fix_unlinked_entries_action = QAction(menu_bar) - Translations.translate_qobject( - self.fix_unlinked_entries_action, "menu.tools.fix_unlinked_entries" - ) + self.fix_unlinked_entries_action = TQAction("menu.tools.fix_unlinked_entries", menu_bar) self.fix_unlinked_entries_action.triggered.connect(create_fix_unlinked_entries_modal) self.fix_unlinked_entries_action.setEnabled(False) tools_menu.addAction(self.fix_unlinked_entries_action) @@ -594,8 +559,7 @@ def create_dupe_files_modal(): self.dupe_modal = FixDupeFilesModal(self.lib, self) self.dupe_modal.show() - self.fix_dupe_files_action = QAction(menu_bar) - Translations.translate_qobject(self.fix_dupe_files_action, "menu.tools.fix_duplicate_files") + self.fix_dupe_files_action = TQAction("menu.tools.fix_duplicate_files", menu_bar) self.fix_dupe_files_action.triggered.connect(create_dupe_files_modal) self.fix_dupe_files_action.setEnabled(False) tools_menu.addAction(self.fix_dupe_files_action) @@ -603,10 +567,7 @@ def create_dupe_files_modal(): tools_menu.addSeparator() # TODO: Move this to a settings screen. - self.clear_thumb_cache_action = QAction(menu_bar) - Translations.translate_qobject( - self.clear_thumb_cache_action, "settings.clear_thumb_cache.title" - ) + self.clear_thumb_cache_action = TQAction("settings.clear_thumb_cache.title", menu_bar) self.clear_thumb_cache_action.triggered.connect( lambda: CacheManager.clear_cache(self.lib.library_dir) ) @@ -632,8 +593,7 @@ def create_folders_tags_modal(): self.folders_modal = FoldersToTagsModal(self.lib, self) self.folders_modal.show() - self.folders_to_tags_action = QAction(menu_bar) - Translations.translate_qobject(self.folders_to_tags_action, "menu.macros.folders_to_tags") + self.folders_to_tags_action = TQAction("menu.macros.folders_to_tags", menu_bar) self.folders_to_tags_action.triggered.connect(create_folders_tags_modal) self.folders_to_tags_action.setEnabled(False) macros_menu.addAction(self.folders_to_tags_action) @@ -644,8 +604,7 @@ def create_about_modal(): self.about_modal = AboutModal(self.config_path) self.about_modal.show() - self.about_action = QAction(menu_bar) - Translations.translate_qobject(self.about_action, "menu.help.about") + self.about_action = TQAction("menu.help.about", menu_bar) self.about_action.triggered.connect(create_about_modal) help_menu.addAction(self.about_action) self.set_macro_menu_viability() @@ -1809,8 +1768,9 @@ def update_recent_lib_menu(self): action.triggered.connect(lambda checked=False, p=path: self.open_library(p)) actions.append(action) - clear_recent_action = QAction(self.open_recent_library_menu) - Translations.translate_qobject(clear_recent_action, "menu.file.clear_recent_libraries") + clear_recent_action = TQAction( + "menu.file.clear_recent_libraries", self.open_recent_library_menu + ) clear_recent_action.triggered.connect(self.clear_recent_libs) actions.append(clear_recent_action) diff --git a/tagstudio/src/qt/widgets/color_box.py b/tagstudio/src/qt/widgets/color_box.py index ac80b1b80..e4b244423 100644 --- a/tagstudio/src/qt/widgets/color_box.py +++ b/tagstudio/src/qt/widgets/color_box.py @@ -15,7 +15,7 @@ from src.core.palette import ColorType, get_tag_color from src.qt.flowlayout import FlowLayout from src.qt.modals.build_color import BuildColorPanel -from src.qt.translations import Translations +from src.qt.translations import TQMessageBox, Translations from src.qt.widgets.fields import FieldWidget from src.qt.widgets.panel import PanelModal from src.qt.widgets.tag_color_label import TagColorLabel @@ -143,11 +143,8 @@ def edit_color(self, color_group: TagColorGroup): self.edit_modal.show() def delete_color(self, color_group: TagColorGroup): - message_box = QMessageBox() + message_box = TQMessageBox("color.confirm_delete", color_name=color_group.name) Translations.translate_with_setter(message_box.setWindowTitle, "color.delete") - Translations.translate_qobject( - message_box, "color.confirm_delete", color_name=color_group.name - ) message_box.setIcon(QMessageBox.Icon.Warning) cancel_button = message_box.addButton( Translations["generic.cancel_alt"], QMessageBox.ButtonRole.RejectRole diff --git a/tagstudio/src/qt/widgets/item_thumb.py b/tagstudio/src/qt/widgets/item_thumb.py index a55660a57..d6a62bb9b 100644 --- a/tagstudio/src/qt/widgets/item_thumb.py +++ b/tagstudio/src/qt/widgets/item_thumb.py @@ -30,7 +30,7 @@ from src.qt.flowlayout import FlowWidget from src.qt.helpers.file_opener import FileOpenerHelper from src.qt.platform_strings import open_file_str, trash_term -from src.qt.translations import Translations +from src.qt.translations import TQAction, TQLabel from src.qt.widgets.thumb_button import ThumbButton from src.qt.widgets.thumb_renderer import ThumbRenderer @@ -216,16 +216,12 @@ def __init__( self.thumb_button.setContextMenuPolicy(Qt.ContextMenuPolicy.ActionsContextMenu) self.opener = FileOpenerHelper("") - open_file_action = QAction(self) - Translations.translate_qobject(open_file_action, "file.open_file") + open_file_action = TQAction("file.open_file", self) open_file_action.triggered.connect(self.opener.open_file) open_explorer_action = QAction(open_file_str(), self) open_explorer_action.triggered.connect(self.opener.open_explorer) - self.delete_action = QAction(self) - Translations.translate_qobject( - self.delete_action, "trash.context.ambiguous", trash_term=trash_term() - ) + self.delete_action = TQAction("trash.context.ambiguous", self, trash_term=trash_term()) self.thumb_button.addAction(open_file_action) self.thumb_button.addAction(open_explorer_action) @@ -313,8 +309,7 @@ def __init__( self.cb_layout.addWidget(badge) # Filename Label ======================================================= - self.file_label = QLabel() - Translations.translate_qobject(self.file_label, "generic.filename") + self.file_label = TQLabel("generic.filename") self.file_label.setStyleSheet(ItemThumb.filename_style) self.file_label.setMaximumHeight(self.label_height) if not show_filename_label: diff --git a/tagstudio/src/qt/widgets/landing.py b/tagstudio/src/qt/widgets/landing.py index 3f6b15942..db25137d9 100644 --- a/tagstudio/src/qt/widgets/landing.py +++ b/tagstudio/src/qt/widgets/landing.py @@ -13,7 +13,7 @@ from PySide6.QtGui import QPixmap from PySide6.QtWidgets import QLabel, QPushButton, QVBoxLayout, QWidget from src.qt.helpers.color_overlay import gradient_overlay, theme_fg_overlay -from src.qt.translations import Translations +from src.qt.translations import TQPushButton from src.qt.widgets.clickable_label import ClickableLabel # Only import for type checking/autocompletion, will not be imported at runtime. @@ -61,11 +61,10 @@ def __init__(self, driver: "QtDriver", pixel_ratio: float): open_shortcut_text = "(⌘+O)" else: open_shortcut_text = "(Ctrl+O)" - self.open_button: QPushButton = QPushButton() - self.open_button.setMinimumWidth(200) - Translations.translate_qobject( - self.open_button, "landing.open_create_library", shortcut=open_shortcut_text + self.open_button: QPushButton = TQPushButton( + "landing.open_create_library", shortcut=open_shortcut_text ) + self.open_button.setMinimumWidth(200) self.open_button.clicked.connect(self.driver.open_library_from_dialog) # Create status label -------------------------------------------------- diff --git a/tagstudio/src/qt/widgets/migration_modal.py b/tagstudio/src/qt/widgets/migration_modal.py index 11acd721b..8cc3de2c8 100644 --- a/tagstudio/src/qt/widgets/migration_modal.py +++ b/tagstudio/src/qt/widgets/migration_modal.py @@ -31,8 +31,8 @@ from src.core.library.json.library import Tag as JsonTag # type: ignore from src.qt.helpers.custom_runnable import CustomRunnable from src.qt.helpers.function_iterator import FunctionIterator -from src.qt.helpers.qbutton_wrapper import QPushButtonWrapper -from src.qt.translations import Translations +from src.qt.helpers.qbutton_wrapper import TQPushButtonWrapper +from src.qt.translations import TQLabel, TQMessageBox, Translations from src.qt.widgets.paged_panel.paged_body_wrapper import PagedBodyWrapper from src.qt.widgets.paged_panel.paged_panel import PagedPanel from src.qt.widgets.paged_panel.paged_panel_state import PagedPanelState @@ -81,17 +81,14 @@ def __init__(self, path: Path): def init_page_info(self) -> None: """Initialize the migration info page.""" body_wrapper: PagedBodyWrapper = PagedBodyWrapper() - body_label = QLabel() - Translations.translate_qobject(body_label, "json_migration.info.description") + body_label = TQLabel("json_migration.info.description") body_label.setWordWrap(True) body_label.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding) body_wrapper.layout().addWidget(body_label) body_wrapper.layout().setContentsMargins(0, 36, 0, 0) - cancel_button = QPushButtonWrapper() - Translations.translate_qobject(cancel_button, "generic.cancel") - next_button = QPushButtonWrapper() - Translations.translate_qobject(next_button, "generic.continue") + cancel_button = TQPushButtonWrapper("generic.cancel") + next_button = TQPushButtonWrapper("generic.continue") cancel_button.clicked.connect(self.migration_cancelled.emit) self.stack.append( @@ -142,8 +139,7 @@ def init_page_convert(self) -> None: old_lib_container: QWidget = QWidget() old_lib_layout: QVBoxLayout = QVBoxLayout(old_lib_container) - old_lib_title = QLabel() - Translations.translate_qobject(old_lib_title, "json_migration.title.old_lib") + old_lib_title = TQLabel("json_migration.title.old_lib") old_lib_title.setAlignment(Qt.AlignmentFlag.AlignCenter) old_lib_layout.addWidget(old_lib_title) @@ -210,8 +206,7 @@ def init_page_convert(self) -> None: new_lib_container: QWidget = QWidget() new_lib_layout: QVBoxLayout = QVBoxLayout(new_lib_container) - new_lib_title = QLabel() - Translations.translate_qobject(new_lib_title, "json_migration.title.new_lib") + new_lib_title = TQLabel("json_migration.title.new_lib") new_lib_title.setAlignment(Qt.AlignmentFlag.AlignCenter) new_lib_layout.addWidget(new_lib_title) @@ -292,15 +287,12 @@ def init_page_convert(self) -> None: self.body_wrapper_01.layout().addWidget(desc_label) self.body_wrapper_01.layout().setSpacing(12) - back_button = QPushButtonWrapper() - Translations.translate_qobject(back_button, "generic.navigation.back") - start_button = QPushButtonWrapper() - Translations.translate_qobject(start_button, "json_migration.start_and_preview") + back_button = TQPushButtonWrapper("generic.navigation.back") + start_button = TQPushButtonWrapper("json_migration.start_and_preview") start_button.setMinimumWidth(120) start_button.clicked.connect(self.migrate) start_button.clicked.connect(lambda: start_button.setDisabled(True)) - finish_button: QPushButtonWrapper = QPushButtonWrapper() - Translations.translate_qobject(finish_button, "json_migration.finish_migration") + finish_button: TQPushButtonWrapper = TQPushButtonWrapper("json_migration.finish_migration") finish_button.setMinimumWidth(120) finish_button.setDisabled(True) finish_button.clicked.connect(self.finish_migration) @@ -481,13 +473,10 @@ def update_sql_value_ui(self, show_msg_box: bool = True): QApplication.alert(self.paged_panel) if not show_msg_box: return - msg_box = QMessageBox() + msg_box = TQMessageBox("json_migration.discrepancies_found.description") Translations.translate_with_setter( msg_box.setWindowTitle, "json_migration.discrepancies_found" ) - Translations.translate_qobject( - msg_box, "json_migration.discrepancies_found.description" - ) msg_box.setDetailedText("\n".join(self.discrepancies)) msg_box.setIcon(QMessageBox.Icon.Warning) msg_box.exec() diff --git a/tagstudio/src/qt/widgets/paged_panel/paged_panel_state.py b/tagstudio/src/qt/widgets/paged_panel/paged_panel_state.py index 849dcbc77..10ae7bead 100644 --- a/tagstudio/src/qt/widgets/paged_panel/paged_panel_state.py +++ b/tagstudio/src/qt/widgets/paged_panel/paged_panel_state.py @@ -4,6 +4,7 @@ from PySide6.QtWidgets import QPushButton +from src.qt.translations import TQPushButton from src.qt.widgets.paged_panel.paged_body_wrapper import PagedBodyWrapper @@ -15,11 +16,11 @@ def __init__( title: str, body_wrapper: PagedBodyWrapper, buttons: list[QPushButton | int], - connect_to_back=list[QPushButton], - connect_to_next=list[QPushButton], + connect_to_back: list[TQPushButton], + connect_to_next: list[TQPushButton], ): self.title: str = title self.body_wrapper: PagedBodyWrapper = body_wrapper self.buttons: list[QPushButton | int] = buttons - self.connect_to_back: list[QPushButton] = connect_to_back - self.connect_to_next: list[QPushButton] = connect_to_next + self.connect_to_back: list[TQPushButton] = connect_to_back + self.connect_to_next: list[TQPushButton] = connect_to_next diff --git a/tagstudio/src/qt/widgets/panel.py b/tagstudio/src/qt/widgets/panel.py index 226ab3f8f..8046fc5f6 100755 --- a/tagstudio/src/qt/widgets/panel.py +++ b/tagstudio/src/qt/widgets/panel.py @@ -7,7 +7,7 @@ from PySide6 import QtCore, QtGui from PySide6.QtCore import Qt, Signal from PySide6.QtWidgets import QHBoxLayout, QLabel, QPushButton, QVBoxLayout, QWidget -from src.qt.translations import Translations +from src.qt.translations import TQPushButton logger = structlog.get_logger(__name__) @@ -52,8 +52,7 @@ def __init__( # self.cancel_button.setText('Cancel') if not (save_callback or has_save): - self.done_button = QPushButton() - Translations.translate_qobject(self.done_button, "generic.done") + self.done_button = TQPushButton("generic.done") self.done_button.setAutoDefault(True) self.done_button.clicked.connect(self.hide) if done_callback: @@ -62,16 +61,14 @@ def __init__( self.button_layout.addWidget(self.done_button) if save_callback or has_save: - self.cancel_button = QPushButton() - Translations.translate_qobject(self.cancel_button, "generic.cancel") + self.cancel_button = TQPushButton("generic.cancel") self.cancel_button.clicked.connect(self.hide) self.cancel_button.clicked.connect(widget.reset) # self.cancel_button.clicked.connect(cancel_callback) self.widget.panel_cancel_button = self.cancel_button self.button_layout.addWidget(self.cancel_button) - self.save_button = QPushButton() - Translations.translate_qobject(self.save_button, "generic.save") + self.save_button = TQPushButton("generic.save") self.save_button.setAutoDefault(True) self.save_button.clicked.connect(self.hide) self.save_button.clicked.connect(self.saved.emit) diff --git a/tagstudio/src/qt/widgets/preview/file_attributes.py b/tagstudio/src/qt/widgets/preview/file_attributes.py index 50f3205fd..a0fb29a1c 100644 --- a/tagstudio/src/qt/widgets/preview/file_attributes.py +++ b/tagstudio/src/qt/widgets/preview/file_attributes.py @@ -61,7 +61,7 @@ def __init__(self, library: Library, driver: "QtDriver"): "padding-left: 1px;" ) - self.file_label = FileOpenerLabel() + self.file_label = FileOpenerLabel("preview.multiple_selection", count=0) self.file_label.setObjectName("filenameLabel") self.file_label.setTextFormat(Qt.TextFormat.RichText) self.file_label.setWordWrap(True) @@ -228,7 +228,7 @@ def update_multi_selection(self, count: int): """Format attributes for multiple selected items.""" self.layout().setSpacing(0) self.file_label.setAlignment(Qt.AlignmentFlag.AlignCenter) - Translations.translate_qobject(self.file_label, "preview.multiple_selection", count=count) + self.file_label.format_args = {"count": count} self.file_label.setCursor(Qt.CursorShape.ArrowCursor) self.file_label.set_file_path("") self.dimensions_label.setText("") diff --git a/tagstudio/src/qt/widgets/preview/preview_thumb.py b/tagstudio/src/qt/widgets/preview/preview_thumb.py index 137b2dea7..d79f6bae8 100644 --- a/tagstudio/src/qt/widgets/preview/preview_thumb.py +++ b/tagstudio/src/qt/widgets/preview/preview_thumb.py @@ -27,7 +27,7 @@ from src.qt.helpers.rounded_pixmap_style import RoundedPixmapStyle from src.qt.platform_strings import open_file_str, trash_term from src.qt.resource_manager import ResourceManager -from src.qt.translations import Translations +from src.qt.translations import TQAction, Translations from src.qt.widgets.media_player import MediaPlayer from src.qt.widgets.thumb_renderer import ThumbRenderer from src.qt.widgets.video_player import VideoPlayer @@ -54,13 +54,9 @@ def __init__(self, library: Library, driver: "QtDriver"): image_layout = QHBoxLayout(self) image_layout.setContentsMargins(0, 0, 0, 0) - self.open_file_action = QAction(self) - Translations.translate_qobject(self.open_file_action, "file.open_file") + self.open_file_action = TQAction("file.open_file", self) self.open_explorer_action = QAction(open_file_str(), self) - self.delete_action = QAction(self) - Translations.translate_qobject( - self.delete_action, "trash.context.ambiguous", trash_term=trash_term() - ) + self.delete_action = TQAction("trash.context.ambiguous", self, trash_term=trash_term()) self.preview_img = QPushButtonWrapper() self.preview_img.setMinimumSize(*self.img_button_size) diff --git a/tagstudio/src/qt/widgets/preview_panel.py b/tagstudio/src/qt/widgets/preview_panel.py index 9df1222d9..169155b5b 100644 --- a/tagstudio/src/qt/widgets/preview_panel.py +++ b/tagstudio/src/qt/widgets/preview_panel.py @@ -22,7 +22,7 @@ from src.core.palette import ColorType, UiColor, get_ui_color from src.qt.modals.add_field import AddFieldModal from src.qt.modals.tag_search import TagSearchPanel -from src.qt.translations import Translations +from src.qt.translations import TQPushButton, Translations from src.qt.widgets.panel import PanelModal from src.qt.widgets.preview.field_containers import FieldContainers from src.qt.widgets.preview.file_attributes import FileAttributes @@ -100,19 +100,17 @@ def __init__(self, library: Library, driver: "QtDriver"): add_buttons_layout.setContentsMargins(0, 0, 0, 0) add_buttons_layout.setSpacing(6) - self.add_tag_button = QPushButton() + self.add_tag_button = TQPushButton("tag.add") self.add_tag_button.setEnabled(False) self.add_tag_button.setCursor(Qt.CursorShape.PointingHandCursor) self.add_tag_button.setMinimumHeight(28) self.add_tag_button.setStyleSheet(PreviewPanel.button_style) - Translations.translate_qobject(self.add_tag_button, "tag.add") - self.add_field_button = QPushButton() + self.add_field_button = TQPushButton("library.field.add") self.add_field_button.setEnabled(False) self.add_field_button.setCursor(Qt.CursorShape.PointingHandCursor) self.add_field_button.setMinimumHeight(28) self.add_field_button.setStyleSheet(PreviewPanel.button_style) - Translations.translate_qobject(self.add_field_button, "library.field.add") add_buttons_layout.addWidget(self.add_tag_button) add_buttons_layout.addWidget(self.add_field_button) diff --git a/tagstudio/src/qt/widgets/tag_color_preview.py b/tagstudio/src/qt/widgets/tag_color_preview.py index 595c98594..1f2683476 100644 --- a/tagstudio/src/qt/widgets/tag_color_preview.py +++ b/tagstudio/src/qt/widgets/tag_color_preview.py @@ -70,7 +70,7 @@ def set_tag_color_group(self, color_group: TagColorGroup | None): f"{color_group.name} ({self.lib.get_namespace_name(color_group.namespace)})" ) else: - Translations.translate_qobject(self.button, "color.title.no_color") + self.button.setText(Translations.translate_formatted("color.title.no_color")) primary_color = self._get_primary_color(color_group) border_color = ( diff --git a/tagstudio/src/qt/widgets/video_player.py b/tagstudio/src/qt/widgets/video_player.py index d02a06e49..60c11c349 100644 --- a/tagstudio/src/qt/widgets/video_player.py +++ b/tagstudio/src/qt/widgets/video_player.py @@ -31,7 +31,7 @@ from src.core.enums import SettingItems from src.qt.helpers.file_opener import FileOpenerHelper from src.qt.platform_strings import open_file_str -from src.qt.translations import Translations +from src.qt.translations import TQAction if typing.TYPE_CHECKING: from src.qt.ts_qt import QtDriver @@ -116,8 +116,7 @@ def __init__(self, driver: "QtDriver") -> None: self.setContextMenuPolicy(Qt.ContextMenuPolicy.ActionsContextMenu) self.opener = FileOpenerHelper(filepath=self.filepath) - autoplay_action = QAction(self) - Translations.translate_qobject(autoplay_action, "media_player.autoplay") + autoplay_action = TQAction("media_player.autoplay", self) autoplay_action.setCheckable(True) self.addAction(autoplay_action) autoplay_action.setChecked( @@ -126,8 +125,7 @@ def __init__(self, driver: "QtDriver") -> None: autoplay_action.triggered.connect(lambda: self.toggle_autoplay()) self.autoplay = autoplay_action - open_file_action = QAction(self) - Translations.translate_qobject(open_file_action, "file.open_file") + open_file_action = TQAction("file.open_file", self) open_file_action.triggered.connect(self.opener.open_file) open_explorer_action = QAction(open_file_str(), self) From 0a7a60a39df77ccfdf5d5daaa20f81287c942b63 Mon Sep 17 00:00:00 2001 From: Jann Stute Date: Tue, 25 Feb 2025 21:00:27 +0100 Subject: [PATCH 4/9] refactor: remove wrapper classes --- tagstudio/src/core/library/alchemy/library.py | 10 +- tagstudio/src/qt/helpers/file_opener.py | 9 +- tagstudio/src/qt/helpers/qbutton_wrapper.py | 13 -- tagstudio/src/qt/main_window.py | 4 +- tagstudio/src/qt/modals/about.py | 27 ++--- tagstudio/src/qt/modals/add_field.py | 10 +- tagstudio/src/qt/modals/build_color.py | 15 +-- tagstudio/src/qt/modals/build_namespace.py | 11 +- tagstudio/src/qt/modals/build_tag.py | 18 +-- tagstudio/src/qt/modals/delete_unlinked.py | 25 ++-- tagstudio/src/qt/modals/drop_import.py | 22 ++-- tagstudio/src/qt/modals/file_extension.py | 8 +- tagstudio/src/qt/modals/fix_dupes.py | 32 ++--- tagstudio/src/qt/modals/fix_unlinked.py | 18 +-- tagstudio/src/qt/modals/folders_to_tags.py | 10 +- tagstudio/src/qt/modals/mirror_entities.py | 23 ++-- tagstudio/src/qt/modals/relink_unlinked.py | 2 +- tagstudio/src/qt/modals/settings_panel.py | 8 +- tagstudio/src/qt/modals/tag_color_manager.py | 9 +- .../src/qt/modals/tag_color_selection.py | 2 +- tagstudio/src/qt/modals/tag_database.py | 21 ++-- tagstudio/src/qt/modals/tag_search.py | 7 +- tagstudio/src/qt/translations.py | 82 +------------ tagstudio/src/qt/ts_qt.py | 114 ++++++++++-------- tagstudio/src/qt/widgets/color_box.py | 10 +- tagstudio/src/qt/widgets/item_thumb.py | 10 +- tagstudio/src/qt/widgets/landing.py | 6 +- tagstudio/src/qt/widgets/migration_modal.py | 34 +++--- .../widgets/paged_panel/paged_panel_state.py | 9 +- tagstudio/src/qt/widgets/panel.py | 8 +- .../qt/widgets/preview/field_containers.py | 2 +- .../src/qt/widgets/preview/preview_thumb.py | 10 +- tagstudio/src/qt/widgets/preview_panel.py | 8 +- tagstudio/src/qt/widgets/tag.py | 4 +- tagstudio/src/qt/widgets/tag_color_label.py | 2 +- tagstudio/src/qt/widgets/tag_color_preview.py | 2 +- tagstudio/src/qt/widgets/video_player.py | 6 +- 37 files changed, 257 insertions(+), 354 deletions(-) diff --git a/tagstudio/src/core/library/alchemy/library.py b/tagstudio/src/core/library/alchemy/library.py index 703a9fb45..e35720aec 100644 --- a/tagstudio/src/core/library/alchemy/library.py +++ b/tagstudio/src/core/library/alchemy/library.py @@ -367,13 +367,9 @@ def open_sqlite_library(self, library_dir: Path, is_new: bool) -> LibraryStatus: db_version = db_result.value # type: ignore if db_version < 6: # NOTE: DB_VERSION 6 is the first supported SQL DB version. - mismatch_text = Translations.translate_formatted( - "status.library_version_mismatch" - ) - found_text = Translations.translate_formatted("status.library_version_found") - expected_text = Translations.translate_formatted( - "status.library_version_expected" - ) + mismatch_text = Translations.formatted("status.library_version_mismatch") + found_text = Translations.formatted("status.library_version_found") + expected_text = Translations.formatted("status.library_version_expected") return LibraryStatus( success=False, message=( diff --git a/tagstudio/src/qt/helpers/file_opener.py b/tagstudio/src/qt/helpers/file_opener.py index 1b850d713..8650be0be 100644 --- a/tagstudio/src/qt/helpers/file_opener.py +++ b/tagstudio/src/qt/helpers/file_opener.py @@ -12,7 +12,6 @@ from PySide6.QtCore import Qt from PySide6.QtWidgets import QLabel from src.qt.helpers.silent_popen import silent_Popen -from src.qt.translations import TQLabel logger = structlog.get_logger(__name__) @@ -114,16 +113,14 @@ def open_explorer(self): open_file(self.filepath, file_manager=True) -class FileOpenerLabel(TQLabel): - def __init__(self, text_key: str, parent=None, **kwargs): +class FileOpenerLabel(QLabel): + def __init__(self, parent=None): """Initialize the FileOpenerLabel. Args: - text_key (str): The translation key that is passed to the super class. parent (QWidget, optional): The parent widget. Defaults to None. - kwargs: Further keyword arguments that are passed to the super class. """ - super().__init__(text_key, parent, **kwargs) + super().__init__(parent) def set_file_path(self, filepath): """Set the filepath to open. diff --git a/tagstudio/src/qt/helpers/qbutton_wrapper.py b/tagstudio/src/qt/helpers/qbutton_wrapper.py index 56354be29..31d2ad812 100644 --- a/tagstudio/src/qt/helpers/qbutton_wrapper.py +++ b/tagstudio/src/qt/helpers/qbutton_wrapper.py @@ -3,7 +3,6 @@ # Created for TagStudio: https://github.com/CyanVoxel/TagStudio from PySide6.QtWidgets import QPushButton -from src.qt.translations import TQPushButton class QPushButtonWrapper(QPushButton): @@ -16,15 +15,3 @@ class QPushButtonWrapper(QPushButton): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.is_connected = False - - -class TQPushButtonWrapper(TQPushButton): - """Custom QPushButton wrapper. - - This is a customized implementation of the PySide6 QPushButton that allows to suppress - the warning that is triggered by disconnecting a signal that is not currently connected. - """ - - def __init__(self, text_key: str, *args, **kwargs): - super().__init__(text_key, *args, **kwargs) - self.is_connected = False diff --git a/tagstudio/src/qt/main_window.py b/tagstudio/src/qt/main_window.py index 68df206b1..ebf36a0fd 100644 --- a/tagstudio/src/qt/main_window.py +++ b/tagstudio/src/qt/main_window.py @@ -15,7 +15,7 @@ from src.qt.pagination import Pagination from src.qt.widgets.landing import LandingWidget -from src.qt.translations import Translations, TQPushButton +from src.qt.translations import Translations # Only import for type checking/autocompletion, will not be imported at runtime. if typing.TYPE_CHECKING: @@ -152,7 +152,7 @@ def setupUi(self, MainWindow): self.searchField.setCompleter(self.searchFieldCompleter) self.horizontalLayout_2.addWidget(self.searchField) - self.searchButton = TQPushButton("home.search", self.centralwidget) + self.searchButton = QPushButton(Translations["home.search"], self.centralwidget) self.searchButton.setObjectName(u"searchButton") self.searchButton.setMinimumSize(QSize(0, 32)) diff --git a/tagstudio/src/qt/modals/about.py b/tagstudio/src/qt/modals/about.py index d17cdbd65..d49168d80 100644 --- a/tagstudio/src/qt/modals/about.py +++ b/tagstudio/src/qt/modals/about.py @@ -6,16 +6,11 @@ from PIL import ImageQt from PySide6.QtCore import Qt from PySide6.QtGui import QPixmap -from PySide6.QtWidgets import ( - QHBoxLayout, - QLabel, - QVBoxLayout, - QWidget, -) +from PySide6.QtWidgets import QHBoxLayout, QLabel, QPushButton, QVBoxLayout, QWidget from src.core.constants import VERSION, VERSION_BRANCH from src.qt.modals.ffmpeg_checker import FfmpegChecker from src.qt.resource_manager import ResourceManager -from src.qt.translations import TQLabel, TQPushButton, Translations +from src.qt.translations import Translations class AboutModal(QWidget): @@ -48,13 +43,15 @@ def __init__(self, config_path): ffprobe = 'Missing' if ff_version["ffprobe"] is not None: ffprobe = 'Found (' + ff_version["ffprobe"] + ")" - self.content_widget = TQLabel( - "about.content", - version=VERSION, - branch=VERSION_BRANCH, - config_path=config_path, - ffmpeg=ffmpeg, - ffprobe=ffprobe, + self.content_widget = QLabel( + Translations.formatted( + "about.content", + version=VERSION, + branch=VERSION_BRANCH, + config_path=config_path, + ffmpeg=ffmpeg, + ffprobe=ffprobe, + ) ) self.content_widget.setObjectName("contentLabel") self.content_widget.setWordWrap(True) @@ -65,7 +62,7 @@ def __init__(self, config_path): self.button_layout = QHBoxLayout(self.button_widget) self.button_layout.addStretch(1) - self.close_button = TQPushButton("generic.close") + self.close_button = QPushButton(Translations["generic.close"]) self.close_button.clicked.connect(lambda: self.close()) self.close_button.setMaximumWidth(80) diff --git a/tagstudio/src/qt/modals/add_field.py b/tagstudio/src/qt/modals/add_field.py index 6041005ba..6d34b6f65 100644 --- a/tagstudio/src/qt/modals/add_field.py +++ b/tagstudio/src/qt/modals/add_field.py @@ -8,13 +8,15 @@ from PySide6.QtCore import Qt, Signal from PySide6.QtWidgets import ( QHBoxLayout, + QLabel, QListWidget, QListWidgetItem, + QPushButton, QVBoxLayout, QWidget, ) from src.core.library import Library -from src.qt.translations import TQLabel, TQPushButton, Translations +from src.qt.translations import Translations logger = structlog.get_logger(__name__) @@ -35,7 +37,7 @@ def __init__(self, library: Library): self.root_layout = QVBoxLayout(self) self.root_layout.setContentsMargins(6, 6, 6, 6) - self.title_widget = TQLabel("library.field.add") + self.title_widget = QLabel(Translations["library.field.add"]) self.title_widget.setObjectName("fieldTitle") self.title_widget.setWordWrap(True) self.title_widget.setStyleSheet("font-weight:bold;" "font-size:14px;" "padding-top: 6px;") @@ -48,11 +50,11 @@ def __init__(self, library: Library): self.button_layout.setContentsMargins(6, 6, 6, 6) self.button_layout.addStretch(1) - self.cancel_button = TQPushButton("generic.cancel") + self.cancel_button = QPushButton(Translations["generic.cancel"]) self.cancel_button.clicked.connect(self.hide) self.button_layout.addWidget(self.cancel_button) - self.save_button = TQPushButton("generic.add") + self.save_button = QPushButton(Translations["generic.add"]) self.save_button.setDefault(True) self.save_button.clicked.connect(self.hide) self.save_button.clicked.connect( diff --git a/tagstudio/src/qt/modals/build_color.py b/tagstudio/src/qt/modals/build_color.py index 339aa65d9..0e55f89b7 100644 --- a/tagstudio/src/qt/modals/build_color.py +++ b/tagstudio/src/qt/modals/build_color.py @@ -13,6 +13,7 @@ QColorDialog, QFormLayout, QHBoxLayout, + QLabel, QLineEdit, QPushButton, QVBoxLayout, @@ -24,7 +25,7 @@ from src.core.library.alchemy.library import slugify from src.core.library.alchemy.models import TagColorGroup from src.core.palette import ColorType, UiColor, get_tag_color, get_ui_color -from src.qt.translations import TQLabel, TQPushButton, Translations +from src.qt.translations import Translations from src.qt.widgets.panel import PanelWidget from src.qt.widgets.tag import ( get_border_color, @@ -71,7 +72,7 @@ def __init__(self, library: Library, color_group: TagColorGroup): self.preview_layout.addWidget(self.preview_button) # Name ----------------------------------------------------------------- - self.name_title = TQLabel("library_object.name") + self.name_title = QLabel(Translations["library_object.name"]) self.name_field = QLineEdit() self.name_field.setFixedHeight(24) self.name_field.textChanged.connect(self.on_text_changed) @@ -81,7 +82,7 @@ def __init__(self, library: Library, color_group: TagColorGroup): self.form_layout.addRow(self.name_title, self.name_field) # Slug ----------------------------------------------------------------- - self.slug_title = TQLabel("library_object.slug") + self.slug_title = QLabel(Translations["library_object.slug"]) self.slug_field = QLineEdit() self.slug_field.setEnabled(False) self.slug_field.setFixedHeight(24) @@ -91,7 +92,7 @@ def __init__(self, library: Library, color_group: TagColorGroup): self.form_layout.addRow(self.slug_title, self.slug_field) # Primary -------------------------------------------------------------- - self.primary_title = TQLabel("color.primary") + self.primary_title = QLabel(Translations["color.primary"]) self.primary_button = QPushButton() self.primary_button.setMinimumSize(44, 22) self.primary_button.setMaximumHeight(22) @@ -104,7 +105,7 @@ def __init__(self, library: Library, color_group: TagColorGroup): self.secondary_layout = QHBoxLayout(self.secondary_widget) self.secondary_layout.setContentsMargins(0, 0, 0, 0) self.secondary_layout.setSpacing(6) - self.secondary_title = TQLabel("color.secondary") + self.secondary_title = QLabel(Translations["color.secondary"]) self.secondary_button = QPushButton() self.secondary_button.setMinimumSize(44, 22) self.secondary_button.setMaximumHeight(22) @@ -112,7 +113,7 @@ def __init__(self, library: Library, color_group: TagColorGroup): self.secondary_button.clicked.connect(self.secondary_color_callback) self.secondary_layout.addWidget(self.secondary_button) - self.secondary_reset_button = TQPushButton("generic.reset") + self.secondary_reset_button = QPushButton(Translations["generic.reset"]) self.secondary_reset_button.clicked.connect(self.update_secondary) self.secondary_layout.addWidget(self.secondary_reset_button) self.secondary_layout.setStretch(0, 3) @@ -137,7 +138,7 @@ def __init__(self, library: Library, color_group: TagColorGroup): ) ) self.border_layout.addWidget(self.border_checkbox) - self.border_label = TQLabel("color.color_border") + self.border_label = QLabel(Translations["color.color_border"]) self.border_layout.addWidget(self.border_label) primary_color = QColor(get_tag_color(ColorType.PRIMARY, TagColorEnum.DEFAULT)) diff --git a/tagstudio/src/qt/modals/build_namespace.py b/tagstudio/src/qt/modals/build_namespace.py index c01f0ac7d..1f62967ec 100644 --- a/tagstudio/src/qt/modals/build_namespace.py +++ b/tagstudio/src/qt/modals/build_namespace.py @@ -9,6 +9,7 @@ import structlog from PySide6.QtCore import Qt, Signal from PySide6.QtWidgets import ( + QLabel, QLineEdit, QVBoxLayout, QWidget, @@ -18,7 +19,7 @@ from src.core.library.alchemy.library import ReservedNamespaceError, slugify from src.core.library.alchemy.models import Namespace from src.core.palette import ColorType, UiColor, get_ui_color -from src.qt.translations import TQLabel, Translations +from src.qt.translations import Translations from src.qt.widgets.panel import PanelWidget logger = structlog.get_logger(__name__) @@ -47,7 +48,7 @@ def __init__(self, library: Library, namespace: Namespace | None = None): self.name_layout.setContentsMargins(0, 0, 0, 0) self.name_layout.setSpacing(0) self.name_layout.setAlignment(Qt.AlignmentFlag.AlignLeft) - self.name_title = TQLabel("library_object.name") + self.name_title = QLabel(Translations["library_object.name"]) self.name_layout.addWidget(self.name_title) self.name_field = QLineEdit() self.name_field.setFixedHeight(24) @@ -64,7 +65,7 @@ def __init__(self, library: Library, namespace: Namespace | None = None): self.slug_layout.setContentsMargins(0, 0, 0, 0) self.slug_layout.setSpacing(0) self.slug_layout.setAlignment(Qt.AlignmentFlag.AlignLeft) - self.slug_title = TQLabel("library_object.slug") + self.slug_title = QLabel(Translations["library_object.slug"]) self.slug_layout.addWidget(self.slug_title) self.slug_field = QLineEdit() self.slug_field.setFixedHeight(24) @@ -75,9 +76,9 @@ def __init__(self, library: Library, namespace: Namespace | None = None): self.slug_layout.addWidget(self.slug_field) # Description ---------------------------------------------------------- - self.desc_label = TQLabel("namespace.create.description") + self.desc_label = QLabel(Translations["namespace.create.description"]) self.desc_label.setWordWrap(True) - self.desc_color_label = TQLabel("namespace.create.description_color") + self.desc_color_label = QLabel(Translations["namespace.create.description_color"]) self.desc_color_label.setWordWrap(True) # Add Widgets to Layout ================================================ diff --git a/tagstudio/src/qt/modals/build_tag.py b/tagstudio/src/qt/modals/build_tag.py index f56f76bc9..d94c85388 100644 --- a/tagstudio/src/qt/modals/build_tag.py +++ b/tagstudio/src/qt/modals/build_tag.py @@ -30,7 +30,7 @@ from src.core.palette import ColorType, UiColor, get_tag_color, get_ui_color from src.qt.modals.tag_color_selection import TagColorSelection from src.qt.modals.tag_search import TagSearchPanel -from src.qt.translations import TQLabel, Translations +from src.qt.translations import Translations from src.qt.widgets.panel import PanelModal, PanelWidget from src.qt.widgets.tag import ( TagWidget, @@ -86,7 +86,7 @@ def __init__(self, library: Library, tag: Tag | None = None): self.name_layout.setContentsMargins(0, 0, 0, 0) self.name_layout.setSpacing(0) self.name_layout.setAlignment(Qt.AlignmentFlag.AlignLeft) - self.name_title = TQLabel("tag.name") + self.name_title = QLabel(Translations["tag.name"]) self.name_layout.addWidget(self.name_title) self.name_field = QLineEdit() self.name_field.setFixedHeight(24) @@ -103,7 +103,7 @@ def __init__(self, library: Library, tag: Tag | None = None): self.shorthand_layout.setContentsMargins(0, 0, 0, 0) self.shorthand_layout.setSpacing(0) self.shorthand_layout.setAlignment(Qt.AlignmentFlag.AlignLeft) - self.shorthand_title = TQLabel("tag.shorthand") + self.shorthand_title = QLabel(Translations["tag.shorthand"]) self.shorthand_layout.addWidget(self.shorthand_title) self.shorthand_field = QLineEdit() self.shorthand_layout.addWidget(self.shorthand_field) @@ -115,7 +115,7 @@ def __init__(self, library: Library, tag: Tag | None = None): self.aliases_layout.setContentsMargins(0, 0, 0, 0) self.aliases_layout.setSpacing(0) self.aliases_layout.setAlignment(Qt.AlignmentFlag.AlignLeft) - self.aliases_title = TQLabel("tag.aliases") + self.aliases_title = QLabel(Translations["tag.aliases"]) self.aliases_layout.addWidget(self.aliases_title) self.aliases_table = QTableWidget(0, 2) @@ -141,7 +141,7 @@ def __init__(self, library: Library, tag: Tag | None = None): self.disam_button_group = QButtonGroup(self) self.disam_button_group.setExclusive(False) - self.parent_tags_title = TQLabel("tag.parent_tags") + self.parent_tags_title = QLabel(Translations["tag.parent_tags"]) self.parent_tags_layout.addWidget(self.parent_tags_title) self.scroll_contents = QWidget() @@ -180,7 +180,7 @@ def __init__(self, library: Library, tag: Tag | None = None): self.color_layout.setContentsMargins(0, 0, 0, 6) self.color_layout.setSpacing(6) self.color_layout.setAlignment(Qt.AlignmentFlag.AlignLeft) - self.color_title = TQLabel("tag.color") + self.color_title = QLabel(Translations["tag.color"]) self.color_layout.addWidget(self.color_title) self.color_button: TagColorPreview try: @@ -190,7 +190,7 @@ def __init__(self, library: Library, tag: Tag | None = None): logger.error("[BuildTag] Could not access Tag member attributes", error=e) self.color_button = TagColorPreview(self.lib, None) self.tag_color_selection = TagColorSelection(self.lib) - chose_tag_color_title = Translations.translate_formatted("tag.choose_color") + chose_tag_color_title = Translations.formatted("tag.choose_color") self.choose_color_modal = PanelModal( self.tag_color_selection, chose_tag_color_title, @@ -209,7 +209,7 @@ def __init__(self, library: Library, tag: Tag | None = None): self.cat_layout.setContentsMargins(0, 0, 0, 0) self.cat_layout.setSpacing(6) self.cat_layout.setAlignment(Qt.AlignmentFlag.AlignLeft) - self.cat_title = TQLabel("tag.is_category") + self.cat_title = QLabel(Translations["tag.is_category"]) self.cat_checkbox = QCheckBox() self.cat_checkbox.setFixedSize(22, 22) @@ -398,7 +398,7 @@ def __build_row_item_widget(self, tag: Tag, parent_id: int, is_disambiguation: b disam_button = QRadioButton() disam_button.setObjectName(f"disambiguationButton.{parent_id}") disam_button.setFixedSize(22, 22) - disam_button.setToolTip(Translations.translate_formatted("tag.disambiguation.tooltip")) + disam_button.setToolTip(Translations.formatted("tag.disambiguation.tooltip")) disam_button.setStyleSheet( f"QRadioButton{{" f"background: rgba{primary_color.toTuple()};" diff --git a/tagstudio/src/qt/modals/delete_unlinked.py b/tagstudio/src/qt/modals/delete_unlinked.py index 689f79576..8828c7ed9 100644 --- a/tagstudio/src/qt/modals/delete_unlinked.py +++ b/tagstudio/src/qt/modals/delete_unlinked.py @@ -7,15 +7,10 @@ from PySide6 import QtCore, QtGui from PySide6.QtCore import Qt, QThreadPool, Signal from PySide6.QtGui import QStandardItem, QStandardItemModel -from PySide6.QtWidgets import ( - QHBoxLayout, - QListView, - QVBoxLayout, - QWidget, -) +from PySide6.QtWidgets import QHBoxLayout, QLabel, QListView, QPushButton, QVBoxLayout, QWidget from src.core.utils.missing_files import MissingRegistry from src.qt.helpers.custom_runnable import CustomRunnable -from src.qt.translations import TQLabel, TQPushButton, Translations +from src.qt.translations import Translations from src.qt.widgets.progress import ProgressWidget # Only import for type checking/autocompletion, will not be imported at runtime. @@ -36,9 +31,11 @@ def __init__(self, driver: "QtDriver", tracker: MissingRegistry): self.root_layout = QVBoxLayout(self) self.root_layout.setContentsMargins(6, 6, 6, 6) - self.desc_widget = TQLabel( - "entries.unlinked.delete.confirm", - count=self.tracker.missing_file_entries_count, + self.desc_widget = QLabel( + Translations.formatted( + "entries.unlinked.delete.confirm", + count=self.tracker.missing_file_entries_count, + ) ) self.desc_widget.setObjectName("descriptionLabel") self.desc_widget.setWordWrap(True) @@ -53,12 +50,12 @@ def __init__(self, driver: "QtDriver", tracker: MissingRegistry): self.button_layout.setContentsMargins(6, 6, 6, 6) self.button_layout.addStretch(1) - self.cancel_button = TQPushButton("generic.cancel_alt") + self.cancel_button = QPushButton(Translations["generic.cancel_alt"]) self.cancel_button.setDefault(True) self.cancel_button.clicked.connect(self.hide) self.button_layout.addWidget(self.cancel_button) - self.delete_button = TQPushButton("generic.delete_alt") + self.delete_button = QPushButton(Translations["generic.delete_alt"]) self.delete_button.clicked.connect(self.hide) self.delete_button.clicked.connect(lambda: self.delete_entries()) self.button_layout.addWidget(self.delete_button) @@ -69,7 +66,7 @@ def __init__(self, driver: "QtDriver", tracker: MissingRegistry): def refresh_list(self): self.desc_widget.setText( - Translations.translate_formatted( + Translations.formatted( "entries.unlinked.delete.confirm", count=self.tracker.missing_file_entries_count ) ) @@ -82,7 +79,7 @@ def refresh_list(self): def delete_entries(self): def displayed_text(x): - return Translations.translate_formatted( + return Translations.formatted( "entries.unlinked.delete.deleting_count", idx=x, count=self.tracker.missing_file_entries_count, diff --git a/tagstudio/src/qt/modals/drop_import.py b/tagstudio/src/qt/modals/drop_import.py index 29bfaca6a..b88c3ded9 100644 --- a/tagstudio/src/qt/modals/drop_import.py +++ b/tagstudio/src/qt/modals/drop_import.py @@ -11,14 +11,8 @@ from PySide6 import QtCore, QtGui from PySide6.QtCore import Qt, QUrl from PySide6.QtGui import QStandardItem, QStandardItemModel -from PySide6.QtWidgets import ( - QHBoxLayout, - QLabel, - QListView, - QVBoxLayout, - QWidget, -) -from src.qt.translations import TQPushButton, Translations +from PySide6.QtWidgets import QHBoxLayout, QLabel, QListView, QPushButton, QVBoxLayout, QWidget +from src.qt.translations import Translations from src.qt.widgets.progress import ProgressWidget if TYPE_CHECKING: @@ -66,22 +60,22 @@ def __init__(self, driver: "QtDriver"): self.button_layout.setContentsMargins(6, 6, 6, 6) self.button_layout.addStretch(1) - self.skip_button = TQPushButton("generic.skip_alt") + self.skip_button = QPushButton(Translations["generic.skip_alt"]) self.skip_button.setDefault(True) self.skip_button.clicked.connect(lambda: self.begin_transfer(DuplicateChoice.SKIP)) self.button_layout.addWidget(self.skip_button) - self.overwrite_button = TQPushButton("generic.overwrite_alt") + self.overwrite_button = QPushButton(Translations["generic.overwrite_alt"]) self.overwrite_button.clicked.connect( lambda: self.begin_transfer(DuplicateChoice.OVERWRITE) ) self.button_layout.addWidget(self.overwrite_button) - self.rename_button = TQPushButton("generic.rename_alt") + self.rename_button = QPushButton(Translations["generic.rename_alt"]) self.rename_button.clicked.connect(lambda: self.begin_transfer(DuplicateChoice.RENAME)) self.button_layout.addWidget(self.rename_button) - self.cancel_button = TQPushButton("generic.cancel_alt") + self.cancel_button = QPushButton(Translations["generic.cancel_alt"]) self.cancel_button.clicked.connect(lambda: self.begin_transfer(DuplicateChoice.CANCEL)) self.button_layout.addWidget(self.cancel_button) @@ -137,7 +131,7 @@ def ask_duplicates_choice(self): self.desc_widget.setText( Translations["drop_import.duplicates_choice.singular"] if len(self.duplicate_files) == 1 - else Translations.translate_formatted( + else Translations.formatted( "drop_import.duplicates_choice.plural", count=len(self.duplicate_files) ) ) @@ -160,7 +154,7 @@ def begin_transfer(self, choice: DuplicateChoice | None = None): return def displayed_text(x): - return Translations.translate_formatted( + return Translations.formatted( "drop_import.progress.label.singular" if x[0] + 1 == 1 else "drop_import.progress.label.plural", diff --git a/tagstudio/src/qt/modals/file_extension.py b/tagstudio/src/qt/modals/file_extension.py index d020c0b36..1a566d3ab 100644 --- a/tagstudio/src/qt/modals/file_extension.py +++ b/tagstudio/src/qt/modals/file_extension.py @@ -7,7 +7,9 @@ from PySide6.QtWidgets import ( QComboBox, QHBoxLayout, + QLabel, QLineEdit, + QPushButton, QStyledItemDelegate, QTableWidget, QTableWidgetItem, @@ -16,7 +18,7 @@ ) from src.core.enums import LibraryPrefs from src.core.library import Library -from src.qt.translations import TQLabel, TQPushButton, Translations +from src.qt.translations import Translations from src.qt.widgets.panel import PanelWidget @@ -48,7 +50,7 @@ def __init__(self, library: "Library"): self.table.setItemDelegate(FileExtensionItemDelegate()) # Create "Add Button" Widget ------------------------------------------- - self.add_button = TQPushButton("ignore_list.add_extension") + self.add_button = QPushButton(Translations["ignore_list.add_extension"]) self.add_button.clicked.connect(self.add_item) self.add_button.setDefault(True) self.add_button.setMinimumWidth(100) @@ -58,7 +60,7 @@ def __init__(self, library: "Library"): self.mode_layout = QHBoxLayout(self.mode_widget) self.mode_layout.setContentsMargins(0, 0, 0, 0) self.mode_layout.setSpacing(12) - self.mode_label = TQLabel("ignore_list.mode.label") + self.mode_label = QLabel(Translations["ignore_list.mode.label"]) self.mode_combobox = QComboBox() self.mode_combobox.setEditable(False) self.mode_combobox.addItem("") diff --git a/tagstudio/src/qt/modals/fix_dupes.py b/tagstudio/src/qt/modals/fix_dupes.py index 143dfa609..e3e29acb4 100644 --- a/tagstudio/src/qt/modals/fix_dupes.py +++ b/tagstudio/src/qt/modals/fix_dupes.py @@ -7,17 +7,11 @@ from PySide6 import QtCore, QtGui from PySide6.QtCore import Qt -from PySide6.QtWidgets import ( - QFileDialog, - QHBoxLayout, - QLabel, - QVBoxLayout, - QWidget, -) +from PySide6.QtWidgets import QFileDialog, QHBoxLayout, QLabel, QPushButton, QVBoxLayout, QWidget from src.core.library import Library from src.core.utils.dupe_files import DupeRegistry from src.qt.modals.mirror_entities import MirrorEntriesModal -from src.qt.translations import TQLabel, TQPushButton, Translations +from src.qt.translations import Translations # Only import for type checking/autocompletion, will not be imported at runtime. if TYPE_CHECKING: @@ -39,7 +33,7 @@ def __init__(self, library: "Library", driver: "QtDriver"): self.tracker = DupeRegistry(library=self.lib) - self.desc_widget = TQLabel("file.duplicates.description") + self.desc_widget = QLabel(Translations["file.duplicates.description"]) self.desc_widget.setObjectName("descriptionLabel") self.desc_widget.setWordWrap(True) self.desc_widget.setStyleSheet("text-align:left;") @@ -50,21 +44,21 @@ def __init__(self, library: "Library", driver: "QtDriver"): self.dupe_count.setStyleSheet("font-weight:bold;" "font-size:14px;" "") self.dupe_count.setAlignment(Qt.AlignmentFlag.AlignCenter) - self.file_label = TQLabel("file.duplicates.dupeguru.no_file") + self.file_label = QLabel(Translations["file.duplicates.dupeguru.no_file"]) self.file_label.setObjectName("fileLabel") - self.open_button = TQPushButton("file.duplicates.dupeguru.load_file") + self.open_button = QPushButton(Translations["file.duplicates.dupeguru.load_file"]) self.open_button.clicked.connect(self.select_file) self.mirror_modal = MirrorEntriesModal(self.driver, self.tracker) self.mirror_modal.done.connect(self.refresh_dupes) - self.mirror_button = TQPushButton("file.duplicates.mirror_entries") + self.mirror_button = QPushButton(Translations["file.duplicates.mirror_entries"]) self.mirror_button.clicked.connect(self.mirror_modal.show) - self.mirror_desc = TQLabel("file.duplicates.mirror.description") + self.mirror_desc = QLabel(Translations["file.duplicates.mirror.description"]) self.mirror_desc.setWordWrap(True) - self.advice_label = TQLabel("file.duplicates.dupeguru.advice") + self.advice_label = QLabel(Translations["file.duplicates.dupeguru.advice"]) self.advice_label.setWordWrap(True) self.button_container = QWidget() @@ -72,7 +66,7 @@ def __init__(self, library: "Library", driver: "QtDriver"): self.button_layout.setContentsMargins(6, 6, 6, 6) self.button_layout.addStretch(1) - self.done_button = TQPushButton("generic.done_alt") + self.done_button = QPushButton(Translations["generic.done_alt"]) self.done_button.setDefault(True) self.done_button.clicked.connect(self.hide) self.button_layout.addWidget(self.done_button) @@ -120,14 +114,10 @@ def set_dupe_count(self, count: int): self.dupe_count.setText(Translations["file.duplicates.matches_uninitialized"]) elif count == 0: self.mirror_button.setDisabled(True) - self.dupe_count.setText( - Translations.translate_formatted("file.duplicates.matches", count=count) - ) + self.dupe_count.setText(Translations.formatted("file.duplicates.matches", count=count)) else: self.mirror_button.setDisabled(False) - self.dupe_count.setText( - Translations.translate_formatted("file.duplicates.matches", count=count) - ) + self.dupe_count.setText(Translations.formatted("file.duplicates.matches", count=count)) @override def keyPressEvent(self, event: QtGui.QKeyEvent) -> None: # noqa N802 diff --git a/tagstudio/src/qt/modals/fix_unlinked.py b/tagstudio/src/qt/modals/fix_unlinked.py index b232bf4ef..c4ce7298e 100644 --- a/tagstudio/src/qt/modals/fix_unlinked.py +++ b/tagstudio/src/qt/modals/fix_unlinked.py @@ -7,13 +7,13 @@ from PySide6 import QtCore, QtGui from PySide6.QtCore import Qt -from PySide6.QtWidgets import QHBoxLayout, QLabel, QVBoxLayout, QWidget +from PySide6.QtWidgets import QHBoxLayout, QLabel, QPushButton, QVBoxLayout, QWidget from src.core.library import Library from src.core.utils.missing_files import MissingRegistry from src.qt.modals.delete_unlinked import DeleteUnlinkedEntriesModal from src.qt.modals.merge_dupe_entries import MergeDuplicateEntries from src.qt.modals.relink_unlinked import RelinkUnlinkedEntries -from src.qt.translations import TQLabel, TQPushButton, Translations +from src.qt.translations import Translations from src.qt.widgets.progress import ProgressWidget # Only import for type checking/autocompletion, will not be imported at runtime. @@ -37,7 +37,7 @@ def __init__(self, library: "Library", driver: "QtDriver"): self.root_layout = QVBoxLayout(self) self.root_layout.setContentsMargins(6, 6, 6, 6) - self.unlinked_desc_widget = TQLabel("entries.unlinked.description") + self.unlinked_desc_widget = QLabel(Translations["entries.unlinked.description"]) self.unlinked_desc_widget.setObjectName("unlinkedDescriptionLabel") self.unlinked_desc_widget.setWordWrap(True) self.unlinked_desc_widget.setStyleSheet("text-align:left;") @@ -52,13 +52,13 @@ def __init__(self, library: "Library", driver: "QtDriver"): self.dupe_count_label.setStyleSheet("font-weight:bold;" "font-size:14px;") self.dupe_count_label.setAlignment(Qt.AlignmentFlag.AlignCenter) - self.refresh_unlinked_button = TQPushButton("entries.unlinked.refresh_all") + self.refresh_unlinked_button = QPushButton(Translations["entries.unlinked.refresh_all"]) self.refresh_unlinked_button.clicked.connect(self.refresh_missing_files) self.merge_class = MergeDuplicateEntries(self.lib, self.driver) self.relink_class = RelinkUnlinkedEntries(self.tracker) - self.search_button = TQPushButton("entries.unlinked.search_and_relink") + self.search_button = QPushButton(Translations["entries.unlinked.search_and_relink"]) self.relink_class.done.connect( # refresh the grid lambda: ( @@ -68,10 +68,10 @@ def __init__(self, library: "Library", driver: "QtDriver"): ) self.search_button.clicked.connect(self.relink_class.repair_entries) - self.manual_button = TQPushButton("entries.unlinked.relink.manual") + self.manual_button = QPushButton(Translations["entries.unlinked.relink.manual"]) self.manual_button.setHidden(True) - self.delete_button = TQPushButton("entries.unlinked.delete_alt") + self.delete_button = QPushButton(Translations["entries.unlinked.delete_alt"]) self.delete_modal = DeleteUnlinkedEntriesModal(self.driver, self.tracker) self.delete_modal.done.connect( lambda: ( @@ -87,7 +87,7 @@ def __init__(self, library: "Library", driver: "QtDriver"): self.button_layout.setContentsMargins(6, 6, 6, 6) self.button_layout.addStretch(1) - self.done_button = TQPushButton("generic.done_alt") + self.done_button = QPushButton(Translations["generic.done_alt"]) self.done_button.setDefault(True) self.done_button.clicked.connect(self.hide) self.button_layout.addWidget(self.done_button) @@ -135,7 +135,7 @@ def set_missing_count(self, count: int | None = None): self.search_button.setDisabled(self.missing_count == 0) self.delete_button.setDisabled(self.missing_count == 0) self.missing_count_label.setText( - Translations.translate_formatted( + Translations.formatted( "entries.unlinked.missing_count.some", count=self.missing_count ) ) diff --git a/tagstudio/src/qt/modals/folders_to_tags.py b/tagstudio/src/qt/modals/folders_to_tags.py index 07b5b8e13..7c99fcc26 100644 --- a/tagstudio/src/qt/modals/folders_to_tags.py +++ b/tagstudio/src/qt/modals/folders_to_tags.py @@ -25,7 +25,7 @@ from src.core.library.alchemy.enums import TagColorEnum from src.core.palette import ColorType, get_tag_color from src.qt.flowlayout import FlowLayout -from src.qt.translations import TQLabel, TQPushButton, Translations +from src.qt.translations import Translations if TYPE_CHECKING: from src.qt.ts_qt import QtDriver @@ -172,7 +172,7 @@ def __init__(self, library: "Library", driver: "QtDriver"): self.root_layout = QVBoxLayout(self) self.root_layout.setContentsMargins(6, 6, 6, 6) - self.title_widget = TQLabel("folders_to_tags.title") + self.title_widget = QLabel(Translations["folders_to_tags.title"]) self.title_widget.setObjectName("title") self.title_widget.setWordWrap(True) self.title_widget.setStyleSheet("font-weight:bold;" "font-size:14px;" "padding-top: 6px") @@ -190,9 +190,9 @@ def __init__(self, library: "Library", driver: "QtDriver"): self.open_close_button_w = QWidget() self.open_close_button_layout = QHBoxLayout(self.open_close_button_w) - self.open_all_button = TQPushButton("folders_to_tags.open_all") + self.open_all_button = QPushButton(Translations["folders_to_tags.open_all"]) self.open_all_button.clicked.connect(lambda: self.set_all_branches(False)) - self.close_all_button = TQPushButton("folders_to_tags.close_all") + self.close_all_button = QPushButton(Translations["folders_to_tags.close_all"]) self.close_all_button.clicked.connect(lambda: self.set_all_branches(True)) self.open_close_button_layout.addWidget(self.open_all_button) @@ -210,7 +210,7 @@ def __init__(self, library: "Library", driver: "QtDriver"): self.scroll_area.setFrameShape(QFrame.Shape.NoFrame) self.scroll_area.setWidget(self.scroll_contents) - self.apply_button = TQPushButton("generic.apply_alt") + self.apply_button = QPushButton(Translations["generic.apply_alt"]) self.apply_button.setMinimumWidth(100) self.apply_button.clicked.connect(self.on_apply) diff --git a/tagstudio/src/qt/modals/mirror_entities.py b/tagstudio/src/qt/modals/mirror_entities.py index 77d3971b3..c46b958ad 100644 --- a/tagstudio/src/qt/modals/mirror_entities.py +++ b/tagstudio/src/qt/modals/mirror_entities.py @@ -8,14 +8,9 @@ from PySide6.QtCore import Qt, Signal from PySide6.QtGui import QStandardItem, QStandardItemModel -from PySide6.QtWidgets import ( - QHBoxLayout, - QListView, - QVBoxLayout, - QWidget, -) +from PySide6.QtWidgets import QHBoxLayout, QLabel, QListView, QPushButton, QVBoxLayout, QWidget from src.core.utils.dupe_files import DupeRegistry -from src.qt.translations import TQLabel, TQPushButton, Translations +from src.qt.translations import Translations from src.qt.widgets.progress import ProgressWidget # Only import for type checking/autocompletion, will not be imported at runtime. @@ -36,7 +31,9 @@ def __init__(self, driver: "QtDriver", tracker: DupeRegistry): self.root_layout.setContentsMargins(6, 6, 6, 6) self.tracker = tracker - self.desc_widget = TQLabel("entries.mirror.confirmation", count=self.tracker.groups_count) + self.desc_widget = QLabel( + Translations.formatted("entries.mirror.confirmation", count=self.tracker.groups_count) + ) self.desc_widget.setObjectName("descriptionLabel") self.desc_widget.setWordWrap(True) self.desc_widget.setAlignment(Qt.AlignmentFlag.AlignCenter) @@ -50,12 +47,12 @@ def __init__(self, driver: "QtDriver", tracker: DupeRegistry): self.button_layout.setContentsMargins(6, 6, 6, 6) self.button_layout.addStretch(1) - self.cancel_button = TQPushButton("generic.cancel_alt") + self.cancel_button = QPushButton(Translations["generic.cancel_alt"]) self.cancel_button.setDefault(True) self.cancel_button.clicked.connect(self.hide) self.button_layout.addWidget(self.cancel_button) - self.mirror_button = TQPushButton("entries.mirror") + self.mirror_button = QPushButton(Translations["entries.mirror"]) self.mirror_button.clicked.connect(self.hide) self.mirror_button.clicked.connect(self.mirror_entries) self.button_layout.addWidget(self.mirror_button) @@ -66,9 +63,7 @@ def __init__(self, driver: "QtDriver", tracker: DupeRegistry): def refresh_list(self): self.desc_widget.setText( - Translations.translate_formatted( - "entries.mirror.confirmation", count=self.tracker.groups_count - ) + Translations.formatted("entries.mirror.confirmation", count=self.tracker.groups_count) ) self.model.clear() @@ -77,7 +72,7 @@ def refresh_list(self): def mirror_entries(self): def displayed_text(x): - return Translations.translate_formatted( + return Translations.formatted( "entries.mirror.label", idx=x + 1, count=self.tracker.groups_count ) diff --git a/tagstudio/src/qt/modals/relink_unlinked.py b/tagstudio/src/qt/modals/relink_unlinked.py index 6dbd6f4ca..680f40c90 100644 --- a/tagstudio/src/qt/modals/relink_unlinked.py +++ b/tagstudio/src/qt/modals/relink_unlinked.py @@ -18,7 +18,7 @@ def __init__(self, tracker: MissingRegistry): def repair_entries(self): def displayed_text(x): - return Translations.translate_formatted( + return Translations.formatted( "entries.unlinked.relink.attempting", idx=x, missing_count=self.tracker.missing_file_entries_count, diff --git a/tagstudio/src/qt/modals/settings_panel.py b/tagstudio/src/qt/modals/settings_panel.py index eaf87a064..476f3cf4f 100644 --- a/tagstudio/src/qt/modals/settings_panel.py +++ b/tagstudio/src/qt/modals/settings_panel.py @@ -4,9 +4,9 @@ from PySide6.QtCore import Qt -from PySide6.QtWidgets import QComboBox, QFormLayout, QVBoxLayout, QWidget +from PySide6.QtWidgets import QComboBox, QFormLayout, QLabel, QVBoxLayout, QWidget from src.core.enums import SettingItems -from src.qt.translations import TQLabel +from src.qt.translations import Translations from src.qt.widgets.panel import PanelWidget @@ -22,11 +22,11 @@ def __init__(self, driver): self.form_layout = QFormLayout(self.form_container) self.form_layout.setContentsMargins(0, 0, 0, 0) - self.restart_label = TQLabel("settings.restart_required") + self.restart_label = QLabel(Translations["settings.restart_required"]) self.restart_label.setHidden(True) self.restart_label.setAlignment(Qt.AlignmentFlag.AlignCenter) - language_label = TQLabel("settings.language") + language_label = QLabel(Translations["settings.language"]) self.languages = { # "Cantonese (Traditional)": "yue_Hant", # Empty "Chinese (Traditional)": "zh_Hant", diff --git a/tagstudio/src/qt/modals/tag_color_manager.py b/tagstudio/src/qt/modals/tag_color_manager.py index f1504bab3..73a23802e 100644 --- a/tagstudio/src/qt/modals/tag_color_manager.py +++ b/tagstudio/src/qt/modals/tag_color_manager.py @@ -13,6 +13,7 @@ QHBoxLayout, QLabel, QMessageBox, + QPushButton, QScrollArea, QSizePolicy, QVBoxLayout, @@ -21,7 +22,7 @@ from src.core.constants import RESERVED_NAMESPACE_PREFIX from src.core.enums import Theme from src.qt.modals.build_namespace import BuildNamespacePanel -from src.qt.translations import TQPushButton, Translations +from src.qt.translations import Translations from src.qt.widgets.color_box import ColorBoxWidget from src.qt.widgets.fields import FieldContainer from src.qt.widgets.panel import PanelModal @@ -90,7 +91,7 @@ def __init__( self.button_layout = QHBoxLayout(self.button_container) self.button_layout.setContentsMargins(6, 6, 6, 6) - self.new_namespace_button = TQPushButton("namespace.new.button") + self.new_namespace_button = QPushButton(Translations["namespace.new.button"]) self.new_namespace_button.clicked.connect(self.create_namespace) self.button_layout.addWidget(self.new_namespace_button) @@ -100,7 +101,7 @@ def __init__( self.button_layout.addStretch(1) - self.done_button = TQPushButton("generic.done_alt") + self.done_button = QPushButton(Translations["generic.done_alt"]) self.done_button.clicked.connect(self.hide) self.button_layout.addWidget(self.done_button) @@ -153,7 +154,7 @@ def setup_color_groups(self): ns_layout = QHBoxLayout(ns_container) ns_layout.setAlignment(Qt.AlignmentFlag.AlignCenter) ns_layout.setContentsMargins(0, 18, 0, 18) - namespace_prompt = TQPushButton("namespace.new.prompt") + namespace_prompt = QPushButton(Translations["namespace.new.prompt"]) namespace_prompt.setFixedSize(namespace_prompt.sizeHint().width() + 8, 24) namespace_prompt.clicked.connect(self.create_namespace) ns_layout.addWidget(namespace_prompt) diff --git a/tagstudio/src/qt/modals/tag_color_selection.py b/tagstudio/src/qt/modals/tag_color_selection.py index f0f1585b6..6346c3528 100644 --- a/tagstudio/src/qt/modals/tag_color_selection.py +++ b/tagstudio/src/qt/modals/tag_color_selection.py @@ -139,7 +139,7 @@ def __init__(self, library: Library): self.scroll_layout.addSpacerItem(QSpacerItem(1, 6)) def add_no_color_widget(self): - no_color_str: str = Translations.translate_formatted("color.title.no_color") + no_color_str: str = Translations.formatted("color.title.no_color") self.scroll_layout.addWidget(QLabel(f"

{no_color_str}

")) color_box_widget = QWidget() color_group_layout = FlowLayout() diff --git a/tagstudio/src/qt/modals/tag_database.py b/tagstudio/src/qt/modals/tag_database.py index 57b3f5057..06eb697ba 100644 --- a/tagstudio/src/qt/modals/tag_database.py +++ b/tagstudio/src/qt/modals/tag_database.py @@ -3,14 +3,12 @@ # Created for TagStudio: https://github.com/CyanVoxel/TagStudio import structlog -from PySide6.QtWidgets import ( - QMessageBox, -) +from PySide6.QtWidgets import QMessageBox, QPushButton from src.core.constants import RESERVED_TAG_END, RESERVED_TAG_START from src.core.library import Library, Tag from src.qt.modals.build_tag import BuildTagPanel from src.qt.modals.tag_search import TagSearchPanel -from src.qt.translations import TQMessageBox, TQPushButton, Translations +from src.qt.translations import Translations from src.qt.widgets.panel import PanelModal logger = structlog.get_logger(__name__) @@ -25,7 +23,7 @@ def __init__(self, driver, library: Library): super().__init__(library, is_tag_chooser=False) self.driver = driver - self.create_tag_button = TQPushButton("tag.create") + self.create_tag_button = QPushButton(Translations["tag.create"]) self.create_tag_button.clicked.connect(lambda: self.build_tag(self.search_field.text())) self.root_layout.addWidget(self.create_tag_button) @@ -59,10 +57,15 @@ def delete_tag(self, tag: Tag): if tag.id in range(RESERVED_TAG_START, RESERVED_TAG_END): return - message_box = TQMessageBox("tag.confirm_delete", tag_name=self.lib.tag_display_name(tag.id)) - Translations.translate_with_setter(message_box.setWindowTitle, "tag.remove") - message_box.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel) # type: ignore - message_box.setIcon(QMessageBox.Question) # type: ignore + message_box = QMessageBox( + QMessageBox.Question, # type: ignore + Translations["tag.remove"], + Translations.formatted( + "tag.confirm_delete", + tag_name=self.lib.tag_display_name(tag.id), + ), + QMessageBox.Ok | QMessageBox.Cancel, # type: ignore + ) result = message_box.exec() diff --git a/tagstudio/src/qt/modals/tag_search.py b/tagstudio/src/qt/modals/tag_search.py index 0c6f53384..ff8903b99 100644 --- a/tagstudio/src/qt/modals/tag_search.py +++ b/tagstudio/src/qt/modals/tag_search.py @@ -16,6 +16,7 @@ QComboBox, QFrame, QHBoxLayout, + QLabel, QLineEdit, QPushButton, QScrollArea, @@ -26,7 +27,7 @@ from src.core.library import Library, Tag from src.core.library.alchemy.enums import FilterState, TagColorEnum from src.core.palette import ColorType, get_tag_color -from src.qt.translations import TQLabel, TQPushButton, Translations +from src.qt.translations import Translations from src.qt.widgets.panel import PanelModal, PanelWidget from src.qt.widgets.tag import ( TagWidget, @@ -76,7 +77,7 @@ def __init__( self.limit_layout.setSpacing(12) self.limit_layout.addStretch(1) - self.limit_title = TQLabel("tag.view_limit") + self.limit_title = QLabel(Translations["tag.view_limit"]) self.limit_layout.addWidget(self.limit_title) self.limit_combobox = QComboBox() @@ -119,7 +120,7 @@ def set_driver(self, driver): def build_create_button(self, query: str | None, key: str, format_args: dict): """Constructs a "Create & Add Tag" QPushButton.""" - create_button = TQPushButton(key, self, **format_args) + create_button = QPushButton(Translations.formatted(key, **format_args), self) create_button.setFlat(True) create_button.setMinimumSize(22, 22) diff --git a/tagstudio/src/qt/translations.py b/tagstudio/src/qt/translations.py index e8c78a939..c2508f075 100644 --- a/tagstudio/src/qt/translations.py +++ b/tagstudio/src/qt/translations.py @@ -1,13 +1,9 @@ -from abc import abstractmethod from pathlib import Path from typing import Callable -from weakref import WeakSet import structlog import ujson from PySide6.QtCore import QObject, Signal -from PySide6.QtGui import QAction -from PySide6.QtWidgets import QLabel, QMenu, QMessageBox, QPushButton, QWidget logger = structlog.get_logger(__name__) @@ -36,7 +32,6 @@ def value(self, value: str | None): class Translator: - _watchers: WeakSet["TranslationWatcher"] = WeakSet() _strings: dict[str, TranslatedString] = {} _lang: str = DEFAULT_TRANSLATION @@ -51,16 +46,11 @@ def __get_translation_dict(self, lang: str) -> dict[str, str]: ) as f: return ujson.loads(f.read()) - def register_translation_watcher(self, widget: "TranslationWatcher"): - self._watchers.add(widget) - def change_language(self, lang: str): self._lang = lang translated = self.__get_translation_dict(lang) for k in self._strings: self._strings[k].value = translated.get(k, None) - for w in self._watchers: - w.update_text() def translate_with_setter(self, setter: Callable[[str], None], key: str, **kwargs): """Calls `setter` everytime the language changes and passes the translated string for `key`. @@ -70,7 +60,7 @@ def translate_with_setter(self, setter: Callable[[str], None], key: str, **kwarg # TODO: Fix so deleted Qt objects aren't referenced any longer # if key in self._strings: # self._strings[key].changed.connect(lambda text: setter(self.__format(text, **kwargs))) - setter(self.translate_formatted(key, **kwargs)) + setter(self.formatted(key, **kwargs)) def __format(self, text: str, **kwargs) -> str: try: @@ -84,7 +74,7 @@ def __format(self, text: str, **kwargs) -> str: ) return text - def translate_formatted(self, key: str, **kwargs) -> str: + def formatted(self, key: str, **kwargs) -> str: return self.__format(self[key], **kwargs) def __getitem__(self, key: str) -> str: @@ -92,71 +82,3 @@ def __getitem__(self, key: str) -> str: Translations = Translator() - - -class TranslationWatcher: - def __init__(self): - Translations.register_translation_watcher(self) - - @abstractmethod - def update_text(self): - pass - - -# TODO: there is a LOT of duplicated code in these following classes - -# maybe generate them from a template (if that is even possible)? - - -class TQPushButton(QPushButton, TranslationWatcher): - def __init__(self, text_key: str, parent: QWidget | None = None, **kwargs): - super().__init__(parent) - self.text_key: str = text_key - self.format_args = kwargs - self.update_text() - - def update_text(self): - self.setText(Translations.translate_formatted(self.text_key, **self.format_args)) - - -class TQLabel(QLabel, TranslationWatcher): - def __init__(self, text_key: str, parent: QWidget | None = None, **kwargs): - super().__init__(parent) - self.text_key: str = text_key - self.format_args = kwargs - self.update_text() - - def update_text(self): - self.setText(Translations.translate_formatted(self.text_key, **self.format_args)) - - -class TQAction(QAction, TranslationWatcher): - def __init__(self, text_key: str, parent: QObject | None = None, **kwargs): - super().__init__(parent) - self.text_key: str = text_key - self.format_args = kwargs - self.update_text() - - def update_text(self): - self.setText(Translations.translate_formatted(self.text_key, **self.format_args)) - - -class TQMessageBox(QMessageBox, TranslationWatcher): - def __init__(self, text_key: str, parent: QWidget | None = None, **kwargs): - super().__init__(parent) - self.text_key: str = text_key - self.format_args = kwargs - self.update_text() - - def update_text(self): - self.setText(Translations.translate_formatted(self.text_key, **self.format_args)) - - -class TQMenu(QMenu, TranslationWatcher): - def __init__(self, title_key: str, parent: QWidget | None = None, **kwargs): - super().__init__(parent) - self.title_key: str = title_key - self.format_args = kwargs - self.update_text() - - def update_text(self): - self.setTitle(Translations.translate_formatted(self.title_key, **self.format_args)) diff --git a/tagstudio/src/qt/ts_qt.py b/tagstudio/src/qt/ts_qt.py index 817a07a96..34c1e91da 100644 --- a/tagstudio/src/qt/ts_qt.py +++ b/tagstudio/src/qt/ts_qt.py @@ -43,6 +43,7 @@ QComboBox, QFileDialog, QLineEdit, + QMenu, QMenuBar, QMessageBox, QPushButton, @@ -93,7 +94,7 @@ from src.qt.platform_strings import trash_term from src.qt.resource_manager import ResourceManager from src.qt.splash import Splash -from src.qt.translations import TQAction, TQMenu, Translations +from src.qt.translations import Translations from src.qt.widgets.item_thumb import BadgeType, ItemThumb from src.qt.widgets.migration_modal import JsonMigrationModal from src.qt.widgets.panel import PanelModal @@ -323,8 +324,8 @@ def start(self) -> None: self.tag_search_panel.set_driver(self) self.add_tag_modal = PanelModal( widget=self.tag_search_panel, - title=Translations.translate_formatted("tag.add.plural"), - window_title=Translations.translate_formatted("tag.add.plural"), + title=Translations.formatted("tag.add.plural"), + window_title=Translations.formatted("tag.add.plural"), ) self.tag_search_panel.tag_chosen.connect( lambda t: ( @@ -337,15 +338,15 @@ def start(self) -> None: self.main_window.setMenuBar(menu_bar) menu_bar.setNativeMenuBar(True) - file_menu = TQMenu("menu.file", menu_bar) - edit_menu = TQMenu("generic.edit_alt", menu_bar) - view_menu = TQMenu("menu.view", menu_bar) - tools_menu = TQMenu("menu.tools", menu_bar) - macros_menu = TQMenu("menu.macros", menu_bar) - help_menu = TQMenu("menu.help", menu_bar) + file_menu = QMenu(Translations["menu.file"], menu_bar) + edit_menu = QMenu(Translations["generic.edit_alt"], menu_bar) + view_menu = QMenu(Translations["menu.view"], menu_bar) + tools_menu = QMenu(Translations["menu.tools"], menu_bar) + macros_menu = QMenu(Translations["menu.macros"], menu_bar) + help_menu = QMenu(Translations["menu.help"], menu_bar) # File Menu ============================================================ - open_library_action = TQAction("menu.file.open_create_library", menu_bar) + open_library_action = QAction(Translations["menu.file.open_create_library"], menu_bar) open_library_action.triggered.connect(lambda: self.open_library_from_dialog()) open_library_action.setShortcut( QtCore.QKeyCombination( @@ -356,11 +357,13 @@ def start(self) -> None: open_library_action.setToolTip("Ctrl+O") file_menu.addAction(open_library_action) - self.open_recent_library_menu = TQMenu("menu.file.open_recent_library", menu_bar) + self.open_recent_library_menu = QMenu( + Translations["menu.file.open_recent_library"], menu_bar + ) file_menu.addMenu(self.open_recent_library_menu) self.update_recent_lib_menu() - self.save_library_backup_action = TQAction("menu.file.save_backup", menu_bar) + self.save_library_backup_action = QAction(Translations["menu.file.save_backup"], menu_bar) self.save_library_backup_action.triggered.connect( lambda: self.callback_library_needed_check(self.backup_library) ) @@ -378,11 +381,11 @@ def start(self) -> None: file_menu.addAction(self.save_library_backup_action) file_menu.addSeparator() - settings_action = TQAction("menu.settings", self) + settings_action = QAction(Translations["menu.settings"], self) settings_action.triggered.connect(self.open_settings_modal) file_menu.addAction(settings_action) - open_on_start_action = TQAction("settings.open_library_on_start", self) + open_on_start_action = QAction(Translations["settings.open_library_on_start"], self) open_on_start_action.setCheckable(True) open_on_start_action.setChecked( bool(self.settings.value(SettingItems.START_LOAD_LAST, defaultValue=True, type=bool)) @@ -394,7 +397,7 @@ def start(self) -> None: file_menu.addSeparator() - self.refresh_dir_action = TQAction("menu.file.refresh_directories", menu_bar) + self.refresh_dir_action = QAction(Translations["menu.file.refresh_directories"], menu_bar) self.refresh_dir_action.triggered.connect( lambda: self.callback_library_needed_check(self.add_new_files_callback) ) @@ -409,14 +412,14 @@ def start(self) -> None: file_menu.addAction(self.refresh_dir_action) file_menu.addSeparator() - self.close_library_action = TQAction("menu.file.close_library", menu_bar) + self.close_library_action = QAction(Translations["menu.file.close_library"], menu_bar) self.close_library_action.triggered.connect(self.close_library) self.close_library_action.setEnabled(False) file_menu.addAction(self.close_library_action) file_menu.addSeparator() # Edit Menu ============================================================ - self.new_tag_action = TQAction("menu.edit.new_tag", menu_bar) + self.new_tag_action = QAction(Translations["menu.edit.new_tag"], menu_bar) self.new_tag_action.triggered.connect(lambda: self.add_tag_action_callback()) self.new_tag_action.setShortcut( QtCore.QKeyCombination( @@ -430,7 +433,7 @@ def start(self) -> None: edit_menu.addSeparator() - self.select_all_action = TQAction("select.all", menu_bar) + self.select_all_action = QAction(Translations["select.all"], menu_bar) self.select_all_action.triggered.connect(self.select_all_action_callback) self.select_all_action.setShortcut( QtCore.QKeyCombination( @@ -442,7 +445,7 @@ def start(self) -> None: self.select_all_action.setEnabled(False) edit_menu.addAction(self.select_all_action) - self.clear_select_action = TQAction("select.clear", menu_bar) + self.clear_select_action = QAction(Translations["select.clear"], menu_bar) self.clear_select_action.triggered.connect(self.clear_select_action_callback) self.clear_select_action.setShortcut(QtCore.Qt.Key.Key_Escape) self.clear_select_action.setToolTip("Esc") @@ -463,7 +466,7 @@ def start(self) -> None: self.copy_fields_action.setEnabled(False) edit_menu.addAction(self.copy_fields_action) - self.paste_fields_action = TQAction("edit.paste_fields", menu_bar) + self.paste_fields_action = QAction(Translations.formatted("edit.paste_fields"), menu_bar) self.paste_fields_action.triggered.connect(self.paste_fields_action_callback) self.paste_fields_action.setShortcut( QtCore.QKeyCombination( @@ -475,7 +478,9 @@ def start(self) -> None: self.paste_fields_action.setEnabled(False) edit_menu.addAction(self.paste_fields_action) - self.add_tag_to_selected_action = TQAction("select.add_tag_to_selected", menu_bar) + self.add_tag_to_selected_action = QAction( + Translations["select.add_tag_to_selected"], menu_bar + ) self.add_tag_to_selected_action.triggered.connect(self.add_tag_modal.show) self.add_tag_to_selected_action.setShortcut( QtCore.QKeyCombination( @@ -492,8 +497,9 @@ def start(self) -> None: edit_menu.addSeparator() - self.delete_file_action = TQAction( - "menu.delete_selected_files_ambiguous", menu_bar, trash_term=trash_term() + self.delete_file_action = QAction( + Translations.formatted("menu.delete_selected_files_ambiguous", trash_term=trash_term()), + menu_bar, ) self.delete_file_action.triggered.connect(lambda f="": self.delete_files_callback(f)) self.delete_file_action.setShortcut(QtCore.Qt.Key.Key_Delete) @@ -502,11 +508,13 @@ def start(self) -> None: edit_menu.addSeparator() - self.manage_file_ext_action = TQAction("menu.edit.manage_file_extensions", menu_bar) + self.manage_file_ext_action = QAction( + Translations["menu.edit.manage_file_extensions"], menu_bar + ) edit_menu.addAction(self.manage_file_ext_action) self.manage_file_ext_action.setEnabled(False) - self.tag_manager_action = TQAction("menu.edit.manage_tags", menu_bar) + self.tag_manager_action = QAction(Translations["menu.edit.manage_tags"], menu_bar) self.tag_manager_action.triggered.connect(self.tag_manager_panel.show) self.tag_manager_action.setShortcut( QtCore.QKeyCombination( @@ -518,19 +526,19 @@ def start(self) -> None: self.tag_manager_action.setToolTip("Ctrl+M") edit_menu.addAction(self.tag_manager_action) - self.color_manager_action = TQAction("edit.color_manager", menu_bar) + self.color_manager_action = QAction(Translations["edit.color_manager"], menu_bar) self.color_manager_action.triggered.connect(self.color_manager_panel.show) self.color_manager_action.setEnabled(False) edit_menu.addAction(self.color_manager_action) # View Menu ============================================================ - show_libs_list_action = TQAction("settings.show_recent_libraries", menu_bar) + show_libs_list_action = QAction(Translations["settings.show_recent_libraries"], menu_bar) show_libs_list_action.setCheckable(True) show_libs_list_action.setChecked( bool(self.settings.value(SettingItems.WINDOW_SHOW_LIBS, defaultValue=True, type=bool)) ) - show_filenames_action = TQAction("settings.show_filenames_in_grid", menu_bar) + show_filenames_action = QAction(Translations["settings.show_filenames_in_grid"], menu_bar) show_filenames_action.setCheckable(True) show_filenames_action.setChecked( bool(self.settings.value(SettingItems.SHOW_FILENAMES, defaultValue=True, type=bool)) @@ -549,7 +557,9 @@ def create_fix_unlinked_entries_modal(): self.unlinked_modal = FixUnlinkedEntriesModal(self.lib, self) self.unlinked_modal.show() - self.fix_unlinked_entries_action = TQAction("menu.tools.fix_unlinked_entries", menu_bar) + self.fix_unlinked_entries_action = QAction( + Translations["menu.tools.fix_unlinked_entries"], menu_bar + ) self.fix_unlinked_entries_action.triggered.connect(create_fix_unlinked_entries_modal) self.fix_unlinked_entries_action.setEnabled(False) tools_menu.addAction(self.fix_unlinked_entries_action) @@ -559,7 +569,9 @@ def create_dupe_files_modal(): self.dupe_modal = FixDupeFilesModal(self.lib, self) self.dupe_modal.show() - self.fix_dupe_files_action = TQAction("menu.tools.fix_duplicate_files", menu_bar) + self.fix_dupe_files_action = QAction( + Translations["menu.tools.fix_duplicate_files"], menu_bar + ) self.fix_dupe_files_action.triggered.connect(create_dupe_files_modal) self.fix_dupe_files_action.setEnabled(False) tools_menu.addAction(self.fix_dupe_files_action) @@ -567,7 +579,9 @@ def create_dupe_files_modal(): tools_menu.addSeparator() # TODO: Move this to a settings screen. - self.clear_thumb_cache_action = TQAction("settings.clear_thumb_cache.title", menu_bar) + self.clear_thumb_cache_action = QAction( + Translations["settings.clear_thumb_cache.title"], menu_bar + ) self.clear_thumb_cache_action.triggered.connect( lambda: CacheManager.clear_cache(self.lib.library_dir) ) @@ -593,7 +607,7 @@ def create_folders_tags_modal(): self.folders_modal = FoldersToTagsModal(self.lib, self) self.folders_modal.show() - self.folders_to_tags_action = TQAction("menu.macros.folders_to_tags", menu_bar) + self.folders_to_tags_action = QAction(Translations["menu.macros.folders_to_tags"], menu_bar) self.folders_to_tags_action.triggered.connect(create_folders_tags_modal) self.folders_to_tags_action.setEnabled(False) macros_menu.addAction(self.folders_to_tags_action) @@ -604,7 +618,7 @@ def create_about_modal(): self.about_modal = AboutModal(self.config_path) self.about_modal.show() - self.about_action = TQAction("menu.help.about", menu_bar) + self.about_action = QAction(Translations["menu.help.about"], menu_bar) self.about_action.triggered.connect(create_about_modal) help_menu.addAction(self.about_action) self.set_macro_menu_viability() @@ -868,7 +882,7 @@ def close_library(self, is_shutdown: bool = False): end_time = time.time() self.main_window.statusbar.showMessage( - Translations.translate_formatted( + Translations.formatted( "status.library_closed", time_span=format_timespan(end_time - start_time) ) ) @@ -880,7 +894,7 @@ def backup_library(self): target_path = self.lib.save_library_backup_to_disk() end_time = time.time() self.main_window.statusbar.showMessage( - Translations.translate_formatted( + Translations.formatted( "status.library_backup_success", path=target_path, time_span=format_timespan(end_time - start_time), @@ -979,7 +993,7 @@ def delete_files_callback(self, origin_path: str | Path, origin_id: int | None = self.preview_panel.thumb.stop_file_use() if delete_file(self.lib.library_dir / f): self.main_window.statusbar.showMessage( - Translations.translate_formatted( + Translations.formatted( "status.deleting_file", i=i, count=len(pending), path=f ) ) @@ -997,19 +1011,17 @@ def delete_files_callback(self, origin_path: str | Path, origin_id: int | None = self.main_window.statusbar.showMessage(Translations["status.deleted_none"]) elif len(self.selected) <= 1 and deleted_count == 1: self.main_window.statusbar.showMessage( - Translations.translate_formatted("status.deleted_file_plural", count=deleted_count) + Translations.formatted("status.deleted_file_plural", count=deleted_count) ) elif len(self.selected) > 1 and deleted_count == 0: self.main_window.statusbar.showMessage(Translations["status.deleted_none"]) elif len(self.selected) > 1 and deleted_count < len(self.selected): self.main_window.statusbar.showMessage( - Translations.translate_formatted( - "status.deleted_partial_warning", count=deleted_count - ) + Translations.formatted("status.deleted_partial_warning", count=deleted_count) ) elif len(self.selected) > 1 and deleted_count == len(self.selected): self.main_window.statusbar.showMessage( - Translations.translate_formatted("status.deleted_file_plural", count=deleted_count) + Translations.formatted("status.deleted_file_plural", count=deleted_count) ) self.main_window.statusbar.repaint() @@ -1026,7 +1038,7 @@ def delete_file_confirmation(self, count: int, filename: Path | None = None) -> # https://github.com/arsenetar/send2trash/issues/28 # This warning is applied to all platforms until at least macOS and Linux can be verified # to not exhibit this same behavior. - perm_warning_msg = Translations.translate_formatted( + perm_warning_msg = Translations.formatted( "trash.dialog.permanent_delete_warning", trash_term=trash_term() ) perm_warning: str = ( @@ -1044,7 +1056,7 @@ def delete_file_confirmation(self, count: int, filename: Path | None = None) -> ) msg.setIcon(QMessageBox.Icon.Warning) if count <= 1: - msg_text = Translations.translate_formatted( + msg_text = Translations.formatted( "trash.dialog.move.confirmation.singular", trash_term=trash_term() ) msg.setText( @@ -1054,7 +1066,7 @@ def delete_file_confirmation(self, count: int, filename: Path | None = None) -> f"{perm_warning}
" ) elif count > 1: - msg_text = Translations.translate_formatted( + msg_text = Translations.formatted( "trash.dialog.move.confirmation.plural", count=count, trash_term=trash_term(), @@ -1090,7 +1102,7 @@ def add_new_files_callback(self): lambda x: ( pw.update_progress(x + 1), pw.update_label( - Translations.translate_formatted( + Translations.formatted( "library.refresh.scanning.plural" if x + 1 != 1 else "library.refresh.scanning.singular", @@ -1132,7 +1144,7 @@ def add_new_files_runnable(self, tracker: RefreshDirTracker): iterator.value.connect( lambda: ( pw.update_label( - Translations.translate_formatted( + Translations.formatted( "entries.running.dialog.new_entries", total=f"{files_count:n}" ) ), @@ -1692,7 +1704,7 @@ def filter_items(self, filter: FilterState | None = None) -> None: # inform user about completed search self.main_window.statusbar.showMessage( - Translations.translate_formatted( + Translations.formatted( "status.results_found", count=results.total_count, time_span=format_timespan(end_time - start_time), @@ -1768,8 +1780,8 @@ def update_recent_lib_menu(self): action.triggered.connect(lambda checked=False, p=path: self.open_library(p)) actions.append(action) - clear_recent_action = TQAction( - "menu.file.clear_recent_libraries", self.open_recent_library_menu + clear_recent_action = QAction( + Translations["menu.file.clear_recent_libraries"], self.open_recent_library_menu ) clear_recent_action.triggered.connect(self.clear_recent_libs) actions.append(clear_recent_action) @@ -1823,9 +1835,7 @@ def open_library(self, path: Path) -> None: Translations.translate_with_setter( self.main_window.landing_widget.set_status_label, **translation_params ) - self.main_window.statusbar.showMessage( - Translations.translate_formatted(**translation_params), 3 - ) + self.main_window.statusbar.showMessage(Translations.formatted(**translation_params), 3) self.main_window.repaint() if self.lib.library_dir: diff --git a/tagstudio/src/qt/widgets/color_box.py b/tagstudio/src/qt/widgets/color_box.py index e4b244423..ee7b2d99a 100644 --- a/tagstudio/src/qt/widgets/color_box.py +++ b/tagstudio/src/qt/widgets/color_box.py @@ -15,7 +15,7 @@ from src.core.palette import ColorType, get_tag_color from src.qt.flowlayout import FlowLayout from src.qt.modals.build_color import BuildColorPanel -from src.qt.translations import TQMessageBox, Translations +from src.qt.translations import Translations from src.qt.widgets.fields import FieldWidget from src.qt.widgets.panel import PanelModal from src.qt.widgets.tag_color_label import TagColorLabel @@ -143,9 +143,11 @@ def edit_color(self, color_group: TagColorGroup): self.edit_modal.show() def delete_color(self, color_group: TagColorGroup): - message_box = TQMessageBox("color.confirm_delete", color_name=color_group.name) - Translations.translate_with_setter(message_box.setWindowTitle, "color.delete") - message_box.setIcon(QMessageBox.Icon.Warning) + message_box = QMessageBox( + QMessageBox.Icon.Warning, + Translations["color.delete"], + Translations.formatted("color.confirm_delete", color_name=color_group.name), + ) cancel_button = message_box.addButton( Translations["generic.cancel_alt"], QMessageBox.ButtonRole.RejectRole ) diff --git a/tagstudio/src/qt/widgets/item_thumb.py b/tagstudio/src/qt/widgets/item_thumb.py index d6a62bb9b..7618bb2ad 100644 --- a/tagstudio/src/qt/widgets/item_thumb.py +++ b/tagstudio/src/qt/widgets/item_thumb.py @@ -30,7 +30,7 @@ from src.qt.flowlayout import FlowWidget from src.qt.helpers.file_opener import FileOpenerHelper from src.qt.platform_strings import open_file_str, trash_term -from src.qt.translations import TQAction, TQLabel +from src.qt.translations import Translations from src.qt.widgets.thumb_button import ThumbButton from src.qt.widgets.thumb_renderer import ThumbRenderer @@ -216,12 +216,14 @@ def __init__( self.thumb_button.setContextMenuPolicy(Qt.ContextMenuPolicy.ActionsContextMenu) self.opener = FileOpenerHelper("") - open_file_action = TQAction("file.open_file", self) + open_file_action = QAction(Translations["file.open_file"], self) open_file_action.triggered.connect(self.opener.open_file) open_explorer_action = QAction(open_file_str(), self) open_explorer_action.triggered.connect(self.opener.open_explorer) - self.delete_action = TQAction("trash.context.ambiguous", self, trash_term=trash_term()) + self.delete_action = QAction( + Translations.formatted("trash.context.ambiguous", trash_term=trash_term()), self + ) self.thumb_button.addAction(open_file_action) self.thumb_button.addAction(open_explorer_action) @@ -309,7 +311,7 @@ def __init__( self.cb_layout.addWidget(badge) # Filename Label ======================================================= - self.file_label = TQLabel("generic.filename") + self.file_label = QLabel(Translations["generic.filename"]) self.file_label.setStyleSheet(ItemThumb.filename_style) self.file_label.setMaximumHeight(self.label_height) if not show_filename_label: diff --git a/tagstudio/src/qt/widgets/landing.py b/tagstudio/src/qt/widgets/landing.py index db25137d9..e6b1775f2 100644 --- a/tagstudio/src/qt/widgets/landing.py +++ b/tagstudio/src/qt/widgets/landing.py @@ -13,7 +13,7 @@ from PySide6.QtGui import QPixmap from PySide6.QtWidgets import QLabel, QPushButton, QVBoxLayout, QWidget from src.qt.helpers.color_overlay import gradient_overlay, theme_fg_overlay -from src.qt.translations import TQPushButton +from src.qt.translations import Translations from src.qt.widgets.clickable_label import ClickableLabel # Only import for type checking/autocompletion, will not be imported at runtime. @@ -61,8 +61,8 @@ def __init__(self, driver: "QtDriver", pixel_ratio: float): open_shortcut_text = "(⌘+O)" else: open_shortcut_text = "(Ctrl+O)" - self.open_button: QPushButton = TQPushButton( - "landing.open_create_library", shortcut=open_shortcut_text + self.open_button: QPushButton = QPushButton( + Translations.formatted("landing.open_create_library", shortcut=open_shortcut_text) ) self.open_button.setMinimumWidth(200) self.open_button.clicked.connect(self.driver.open_library_from_dialog) diff --git a/tagstudio/src/qt/widgets/migration_modal.py b/tagstudio/src/qt/widgets/migration_modal.py index 8cc3de2c8..f3c69d90d 100644 --- a/tagstudio/src/qt/widgets/migration_modal.py +++ b/tagstudio/src/qt/widgets/migration_modal.py @@ -31,8 +31,8 @@ from src.core.library.json.library import Tag as JsonTag # type: ignore from src.qt.helpers.custom_runnable import CustomRunnable from src.qt.helpers.function_iterator import FunctionIterator -from src.qt.helpers.qbutton_wrapper import TQPushButtonWrapper -from src.qt.translations import TQLabel, TQMessageBox, Translations +from src.qt.helpers.qbutton_wrapper import QPushButtonWrapper +from src.qt.translations import Translations from src.qt.widgets.paged_panel.paged_body_wrapper import PagedBodyWrapper from src.qt.widgets.paged_panel.paged_panel import PagedPanel from src.qt.widgets.paged_panel.paged_panel_state import PagedPanelState @@ -57,7 +57,7 @@ def __init__(self, path: Path): self.is_migration_initialized: bool = False self.discrepancies: list[str] = [] - self.title: str = Translations.translate_formatted("json_migration.title", path=self.path) + self.title: str = Translations.formatted("json_migration.title", path=self.path) self.warning: str = "(!)" self.old_entry_count: int = 0 @@ -81,14 +81,14 @@ def __init__(self, path: Path): def init_page_info(self) -> None: """Initialize the migration info page.""" body_wrapper: PagedBodyWrapper = PagedBodyWrapper() - body_label = TQLabel("json_migration.info.description") + body_label = QLabel(Translations["json_migration.info.description"]) body_label.setWordWrap(True) body_label.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding) body_wrapper.layout().addWidget(body_label) body_wrapper.layout().setContentsMargins(0, 36, 0, 0) - cancel_button = TQPushButtonWrapper("generic.cancel") - next_button = TQPushButtonWrapper("generic.continue") + cancel_button = QPushButtonWrapper(Translations["generic.cancel"]) + next_button = QPushButtonWrapper(Translations["generic.continue"]) cancel_button.clicked.connect(self.migration_cancelled.emit) self.stack.append( @@ -139,7 +139,7 @@ def init_page_convert(self) -> None: old_lib_container: QWidget = QWidget() old_lib_layout: QVBoxLayout = QVBoxLayout(old_lib_container) - old_lib_title = TQLabel("json_migration.title.old_lib") + old_lib_title = QLabel(Translations["json_migration.title.old_lib"]) old_lib_title.setAlignment(Qt.AlignmentFlag.AlignCenter) old_lib_layout.addWidget(old_lib_title) @@ -206,7 +206,7 @@ def init_page_convert(self) -> None: new_lib_container: QWidget = QWidget() new_lib_layout: QVBoxLayout = QVBoxLayout(new_lib_container) - new_lib_title = TQLabel("json_migration.title.new_lib") + new_lib_title = QLabel(Translations["json_migration.title.new_lib"]) new_lib_title.setAlignment(Qt.AlignmentFlag.AlignCenter) new_lib_layout.addWidget(new_lib_title) @@ -287,12 +287,14 @@ def init_page_convert(self) -> None: self.body_wrapper_01.layout().addWidget(desc_label) self.body_wrapper_01.layout().setSpacing(12) - back_button = TQPushButtonWrapper("generic.navigation.back") - start_button = TQPushButtonWrapper("json_migration.start_and_preview") + back_button = QPushButtonWrapper(Translations["generic.navigation.back"]) + start_button = QPushButtonWrapper(Translations["json_migration.start_and_preview"]) start_button.setMinimumWidth(120) start_button.clicked.connect(self.migrate) start_button.clicked.connect(lambda: start_button.setDisabled(True)) - finish_button: TQPushButtonWrapper = TQPushButtonWrapper("json_migration.finish_migration") + finish_button: QPushButtonWrapper = QPushButtonWrapper( + Translations["json_migration.finish_migration"] + ) finish_button.setMinimumWidth(120) finish_button.setDisabled(True) finish_button.clicked.connect(self.finish_migration) @@ -403,7 +405,7 @@ def migration_iterator(self): logger.info('Temporary migration file "temp_path" already exists. Removing...') self.temp_path.unlink() self.sql_lib.open_sqlite_library(self.json_lib.library_dir, is_new=True) - yield Translations.translate_formatted( + yield Translations.formatted( "json_migration.migrating_files_entries", entries=len(self.json_lib.entries) ) self.sql_lib.migrate_json_to_sqlite(self.json_lib) @@ -473,12 +475,12 @@ def update_sql_value_ui(self, show_msg_box: bool = True): QApplication.alert(self.paged_panel) if not show_msg_box: return - msg_box = TQMessageBox("json_migration.discrepancies_found.description") - Translations.translate_with_setter( - msg_box.setWindowTitle, "json_migration.discrepancies_found" + msg_box = QMessageBox( + QMessageBox.Icon.Warning, + Translations["json_migration.discrepancies_found"], + Translations["json_migration.discrepancies_found.description"], ) msg_box.setDetailedText("\n".join(self.discrepancies)) - msg_box.setIcon(QMessageBox.Icon.Warning) msg_box.exec() def finish_migration(self): diff --git a/tagstudio/src/qt/widgets/paged_panel/paged_panel_state.py b/tagstudio/src/qt/widgets/paged_panel/paged_panel_state.py index 10ae7bead..20ecafba1 100644 --- a/tagstudio/src/qt/widgets/paged_panel/paged_panel_state.py +++ b/tagstudio/src/qt/widgets/paged_panel/paged_panel_state.py @@ -4,7 +4,6 @@ from PySide6.QtWidgets import QPushButton -from src.qt.translations import TQPushButton from src.qt.widgets.paged_panel.paged_body_wrapper import PagedBodyWrapper @@ -16,11 +15,11 @@ def __init__( title: str, body_wrapper: PagedBodyWrapper, buttons: list[QPushButton | int], - connect_to_back: list[TQPushButton], - connect_to_next: list[TQPushButton], + connect_to_back: list[QPushButton], + connect_to_next: list[QPushButton], ): self.title: str = title self.body_wrapper: PagedBodyWrapper = body_wrapper self.buttons: list[QPushButton | int] = buttons - self.connect_to_back: list[TQPushButton] = connect_to_back - self.connect_to_next: list[TQPushButton] = connect_to_next + self.connect_to_back: list[QPushButton] = connect_to_back + self.connect_to_next: list[QPushButton] = connect_to_next diff --git a/tagstudio/src/qt/widgets/panel.py b/tagstudio/src/qt/widgets/panel.py index 8046fc5f6..26de75f95 100755 --- a/tagstudio/src/qt/widgets/panel.py +++ b/tagstudio/src/qt/widgets/panel.py @@ -7,7 +7,7 @@ from PySide6 import QtCore, QtGui from PySide6.QtCore import Qt, Signal from PySide6.QtWidgets import QHBoxLayout, QLabel, QPushButton, QVBoxLayout, QWidget -from src.qt.translations import TQPushButton +from src.qt.translations import Translations logger = structlog.get_logger(__name__) @@ -52,7 +52,7 @@ def __init__( # self.cancel_button.setText('Cancel') if not (save_callback or has_save): - self.done_button = TQPushButton("generic.done") + self.done_button = QPushButton(Translations["generic.done"]) self.done_button.setAutoDefault(True) self.done_button.clicked.connect(self.hide) if done_callback: @@ -61,14 +61,14 @@ def __init__( self.button_layout.addWidget(self.done_button) if save_callback or has_save: - self.cancel_button = TQPushButton("generic.cancel") + self.cancel_button = QPushButton(Translations["generic.cancel"]) self.cancel_button.clicked.connect(self.hide) self.cancel_button.clicked.connect(widget.reset) # self.cancel_button.clicked.connect(cancel_callback) self.widget.panel_cancel_button = self.cancel_button self.button_layout.addWidget(self.cancel_button) - self.save_button = TQPushButton("generic.save") + self.save_button = QPushButton(Translations["generic.save"]) self.save_button.setAutoDefault(True) self.save_button.clicked.connect(self.hide) self.save_button.clicked.connect(self.saved.emit) diff --git a/tagstudio/src/qt/widgets/preview/field_containers.py b/tagstudio/src/qt/widgets/preview/field_containers.py index 88ecd7d9b..8c9914048 100644 --- a/tagstudio/src/qt/widgets/preview/field_containers.py +++ b/tagstudio/src/qt/widgets/preview/field_containers.py @@ -246,7 +246,7 @@ def add_to_cluster(tag_id: int, p_ids: list[int] | None = None): return cats def remove_field_prompt(self, name: str) -> str: - return Translations.translate_formatted("library.field.confirm_remove", name=name) + return Translations.formatted("library.field.confirm_remove", name=name) def add_field_to_selected(self, field_list: list): """Add list of entry fields to one or more selected items. diff --git a/tagstudio/src/qt/widgets/preview/preview_thumb.py b/tagstudio/src/qt/widgets/preview/preview_thumb.py index d79f6bae8..65be56301 100644 --- a/tagstudio/src/qt/widgets/preview/preview_thumb.py +++ b/tagstudio/src/qt/widgets/preview/preview_thumb.py @@ -27,7 +27,7 @@ from src.qt.helpers.rounded_pixmap_style import RoundedPixmapStyle from src.qt.platform_strings import open_file_str, trash_term from src.qt.resource_manager import ResourceManager -from src.qt.translations import TQAction, Translations +from src.qt.translations import Translations from src.qt.widgets.media_player import MediaPlayer from src.qt.widgets.thumb_renderer import ThumbRenderer from src.qt.widgets.video_player import VideoPlayer @@ -54,9 +54,11 @@ def __init__(self, library: Library, driver: "QtDriver"): image_layout = QHBoxLayout(self) image_layout.setContentsMargins(0, 0, 0, 0) - self.open_file_action = TQAction("file.open_file", self) + self.open_file_action = QAction(Translations["file.open_file"], self) self.open_explorer_action = QAction(open_file_str(), self) - self.delete_action = TQAction("trash.context.ambiguous", self, trash_term=trash_term()) + self.delete_action = QAction( + Translations.formatted("trash.context.ambiguous", trash_term=trash_term()), self + ) self.preview_img = QPushButtonWrapper() self.preview_img.setMinimumSize(*self.img_button_size) @@ -376,7 +378,7 @@ def update_preview(self, filepath: Path, ext: str) -> dict: self.delete_action.triggered.disconnect() self.delete_action.setText( - Translations.translate_formatted("trash.context.singular", trash_term=trash_term()) + Translations.formatted("trash.context.singular", trash_term=trash_term()) ) self.delete_action.triggered.connect( lambda checked=False, f=filepath: self.driver.delete_files_callback(f) diff --git a/tagstudio/src/qt/widgets/preview_panel.py b/tagstudio/src/qt/widgets/preview_panel.py index 169155b5b..7098fa978 100644 --- a/tagstudio/src/qt/widgets/preview_panel.py +++ b/tagstudio/src/qt/widgets/preview_panel.py @@ -22,7 +22,7 @@ from src.core.palette import ColorType, UiColor, get_ui_color from src.qt.modals.add_field import AddFieldModal from src.qt.modals.tag_search import TagSearchPanel -from src.qt.translations import TQPushButton, Translations +from src.qt.translations import Translations from src.qt.widgets.panel import PanelModal from src.qt.widgets.preview.field_containers import FieldContainers from src.qt.widgets.preview.file_attributes import FileAttributes @@ -75,7 +75,7 @@ def __init__(self, library: Library, driver: "QtDriver"): self.tag_search_panel = TagSearchPanel(self.driver.lib, is_tag_chooser=True) self.add_tag_modal = PanelModal( - self.tag_search_panel, Translations.translate_formatted("tag.add.plural") + self.tag_search_panel, Translations.formatted("tag.add.plural") ) Translations.translate_with_setter(self.add_tag_modal.setWindowTitle, "tag.add.plural") @@ -100,13 +100,13 @@ def __init__(self, library: Library, driver: "QtDriver"): add_buttons_layout.setContentsMargins(0, 0, 0, 0) add_buttons_layout.setSpacing(6) - self.add_tag_button = TQPushButton("tag.add") + self.add_tag_button = QPushButton(Translations["tag.add"]) self.add_tag_button.setEnabled(False) self.add_tag_button.setCursor(Qt.CursorShape.PointingHandCursor) self.add_tag_button.setMinimumHeight(28) self.add_tag_button.setStyleSheet(PreviewPanel.button_style) - self.add_field_button = TQPushButton("library.field.add") + self.add_field_button = QPushButton(Translations["library.field.add"]) self.add_field_button.setEnabled(False) self.add_field_button.setCursor(Qt.CursorShape.PointingHandCursor) self.add_field_button.setMinimumHeight(28) diff --git a/tagstudio/src/qt/widgets/tag.py b/tagstudio/src/qt/widgets/tag.py index 2d399262c..c95ab88c8 100644 --- a/tagstudio/src/qt/widgets/tag.py +++ b/tagstudio/src/qt/widgets/tag.py @@ -130,7 +130,7 @@ def __init__( if has_edit: edit_action = QAction(self) - edit_action.setText(Translations.translate_formatted("generic.edit")) + edit_action.setText(Translations.formatted("generic.edit")) edit_action.triggered.connect(on_edit_callback) edit_action.triggered.connect(self.on_edit.emit) self.bg_button.addAction(edit_action) @@ -140,7 +140,7 @@ def __init__( # TODO: This currently doesn't work in "Add Tag" menus. Either fix this or # disable it in that context. self.search_for_tag_action = QAction(self) - self.search_for_tag_action.setText(Translations.translate_formatted("tag.search_for_tag")) + self.search_for_tag_action.setText(Translations.formatted("tag.search_for_tag")) self.bg_button.addAction(self.search_for_tag_action) # add_to_search_action = QAction(self) # add_to_search_action.setText(Translations.translate_formatted("tag.add_to_search")) diff --git a/tagstudio/src/qt/widgets/tag_color_label.py b/tagstudio/src/qt/widgets/tag_color_label.py index 6fedc4765..31158edf2 100644 --- a/tagstudio/src/qt/widgets/tag_color_label.py +++ b/tagstudio/src/qt/widgets/tag_color_label.py @@ -60,7 +60,7 @@ def __init__( self.bg_button.setFlat(True) edit_action = QAction(self) - edit_action.setText(Translations.translate_formatted("generic.edit")) + edit_action.setText(Translations.formatted("generic.edit")) edit_action.triggered.connect(self.on_click.emit) self.bg_button.addAction(edit_action) self.bg_button.setContextMenuPolicy(Qt.ContextMenuPolicy.ActionsContextMenu) diff --git a/tagstudio/src/qt/widgets/tag_color_preview.py b/tagstudio/src/qt/widgets/tag_color_preview.py index 1f2683476..5d8c79ce8 100644 --- a/tagstudio/src/qt/widgets/tag_color_preview.py +++ b/tagstudio/src/qt/widgets/tag_color_preview.py @@ -70,7 +70,7 @@ def set_tag_color_group(self, color_group: TagColorGroup | None): f"{color_group.name} ({self.lib.get_namespace_name(color_group.namespace)})" ) else: - self.button.setText(Translations.translate_formatted("color.title.no_color")) + self.button.setText(Translations.formatted("color.title.no_color")) primary_color = self._get_primary_color(color_group) border_color = ( diff --git a/tagstudio/src/qt/widgets/video_player.py b/tagstudio/src/qt/widgets/video_player.py index 60c11c349..1260a18a2 100644 --- a/tagstudio/src/qt/widgets/video_player.py +++ b/tagstudio/src/qt/widgets/video_player.py @@ -31,7 +31,7 @@ from src.core.enums import SettingItems from src.qt.helpers.file_opener import FileOpenerHelper from src.qt.platform_strings import open_file_str -from src.qt.translations import TQAction +from src.qt.translations import Translations if typing.TYPE_CHECKING: from src.qt.ts_qt import QtDriver @@ -116,7 +116,7 @@ def __init__(self, driver: "QtDriver") -> None: self.setContextMenuPolicy(Qt.ContextMenuPolicy.ActionsContextMenu) self.opener = FileOpenerHelper(filepath=self.filepath) - autoplay_action = TQAction("media_player.autoplay", self) + autoplay_action = QAction(Translations["media_player.autoplay"], self) autoplay_action.setCheckable(True) self.addAction(autoplay_action) autoplay_action.setChecked( @@ -125,7 +125,7 @@ def __init__(self, driver: "QtDriver") -> None: autoplay_action.triggered.connect(lambda: self.toggle_autoplay()) self.autoplay = autoplay_action - open_file_action = TQAction("file.open_file", self) + open_file_action = QAction(Translations["file.open_file"], self) open_file_action.triggered.connect(self.opener.open_file) open_explorer_action = QAction(open_file_str(), self) From 4de73f4307a65ca17fcff8277c4850582c08ae5f Mon Sep 17 00:00:00 2001 From: Jann Stute Date: Tue, 25 Feb 2025 21:21:28 +0100 Subject: [PATCH 5/9] refactor: remove unnecessary used of Translations.formatted --- tagstudio/src/qt/modals/build_tag.py | 4 ++-- tagstudio/src/qt/modals/tag_color_selection.py | 2 +- tagstudio/src/qt/ts_qt.py | 2 +- tagstudio/src/qt/widgets/preview/file_attributes.py | 4 ++-- tagstudio/src/qt/widgets/preview_panel.py | 4 +--- tagstudio/src/qt/widgets/tag.py | 4 ++-- tagstudio/src/qt/widgets/tag_color_label.py | 2 +- tagstudio/src/qt/widgets/tag_color_preview.py | 2 +- 8 files changed, 11 insertions(+), 13 deletions(-) diff --git a/tagstudio/src/qt/modals/build_tag.py b/tagstudio/src/qt/modals/build_tag.py index d94c85388..0330d09f2 100644 --- a/tagstudio/src/qt/modals/build_tag.py +++ b/tagstudio/src/qt/modals/build_tag.py @@ -190,7 +190,7 @@ def __init__(self, library: Library, tag: Tag | None = None): logger.error("[BuildTag] Could not access Tag member attributes", error=e) self.color_button = TagColorPreview(self.lib, None) self.tag_color_selection = TagColorSelection(self.lib) - chose_tag_color_title = Translations.formatted("tag.choose_color") + chose_tag_color_title = Translations["tag.choose_color"] self.choose_color_modal = PanelModal( self.tag_color_selection, chose_tag_color_title, @@ -398,7 +398,7 @@ def __build_row_item_widget(self, tag: Tag, parent_id: int, is_disambiguation: b disam_button = QRadioButton() disam_button.setObjectName(f"disambiguationButton.{parent_id}") disam_button.setFixedSize(22, 22) - disam_button.setToolTip(Translations.formatted("tag.disambiguation.tooltip")) + disam_button.setToolTip(Translations["tag.disambiguation.tooltip"]) disam_button.setStyleSheet( f"QRadioButton{{" f"background: rgba{primary_color.toTuple()};" diff --git a/tagstudio/src/qt/modals/tag_color_selection.py b/tagstudio/src/qt/modals/tag_color_selection.py index 6346c3528..0d647fa2b 100644 --- a/tagstudio/src/qt/modals/tag_color_selection.py +++ b/tagstudio/src/qt/modals/tag_color_selection.py @@ -139,7 +139,7 @@ def __init__(self, library: Library): self.scroll_layout.addSpacerItem(QSpacerItem(1, 6)) def add_no_color_widget(self): - no_color_str: str = Translations.formatted("color.title.no_color") + no_color_str: str = Translations["color.title.no_color"] self.scroll_layout.addWidget(QLabel(f"

{no_color_str}

")) color_box_widget = QWidget() color_group_layout = FlowLayout() diff --git a/tagstudio/src/qt/ts_qt.py b/tagstudio/src/qt/ts_qt.py index 34c1e91da..6fe3431c5 100644 --- a/tagstudio/src/qt/ts_qt.py +++ b/tagstudio/src/qt/ts_qt.py @@ -466,7 +466,7 @@ def start(self) -> None: self.copy_fields_action.setEnabled(False) edit_menu.addAction(self.copy_fields_action) - self.paste_fields_action = QAction(Translations.formatted("edit.paste_fields"), menu_bar) + self.paste_fields_action = QAction(Translations["edit.paste_fields"], menu_bar) self.paste_fields_action.triggered.connect(self.paste_fields_action_callback) self.paste_fields_action.setShortcut( QtCore.QKeyCombination( diff --git a/tagstudio/src/qt/widgets/preview/file_attributes.py b/tagstudio/src/qt/widgets/preview/file_attributes.py index a0fb29a1c..8fc19f8a4 100644 --- a/tagstudio/src/qt/widgets/preview/file_attributes.py +++ b/tagstudio/src/qt/widgets/preview/file_attributes.py @@ -61,7 +61,7 @@ def __init__(self, library: Library, driver: "QtDriver"): "padding-left: 1px;" ) - self.file_label = FileOpenerLabel("preview.multiple_selection", count=0) + self.file_label = FileOpenerLabel() self.file_label.setObjectName("filenameLabel") self.file_label.setTextFormat(Qt.TextFormat.RichText) self.file_label.setWordWrap(True) @@ -228,7 +228,7 @@ def update_multi_selection(self, count: int): """Format attributes for multiple selected items.""" self.layout().setSpacing(0) self.file_label.setAlignment(Qt.AlignmentFlag.AlignCenter) - self.file_label.format_args = {"count": count} + self.file_label.setText(Translations["preview.multiple_selection"].format(count=count)) self.file_label.setCursor(Qt.CursorShape.ArrowCursor) self.file_label.set_file_path("") self.dimensions_label.setText("") diff --git a/tagstudio/src/qt/widgets/preview_panel.py b/tagstudio/src/qt/widgets/preview_panel.py index 7098fa978..990c57389 100644 --- a/tagstudio/src/qt/widgets/preview_panel.py +++ b/tagstudio/src/qt/widgets/preview_panel.py @@ -74,9 +74,7 @@ def __init__(self, library: Library, driver: "QtDriver"): self.fields = FieldContainers(library, driver) self.tag_search_panel = TagSearchPanel(self.driver.lib, is_tag_chooser=True) - self.add_tag_modal = PanelModal( - self.tag_search_panel, Translations.formatted("tag.add.plural") - ) + self.add_tag_modal = PanelModal(self.tag_search_panel, Translations["tag.add.plural"]) Translations.translate_with_setter(self.add_tag_modal.setWindowTitle, "tag.add.plural") self.add_field_modal = AddFieldModal(self.lib) diff --git a/tagstudio/src/qt/widgets/tag.py b/tagstudio/src/qt/widgets/tag.py index c95ab88c8..8eb5252e3 100644 --- a/tagstudio/src/qt/widgets/tag.py +++ b/tagstudio/src/qt/widgets/tag.py @@ -130,7 +130,7 @@ def __init__( if has_edit: edit_action = QAction(self) - edit_action.setText(Translations.formatted("generic.edit")) + edit_action.setText(Translations["generic.edit"]) edit_action.triggered.connect(on_edit_callback) edit_action.triggered.connect(self.on_edit.emit) self.bg_button.addAction(edit_action) @@ -140,7 +140,7 @@ def __init__( # TODO: This currently doesn't work in "Add Tag" menus. Either fix this or # disable it in that context. self.search_for_tag_action = QAction(self) - self.search_for_tag_action.setText(Translations.formatted("tag.search_for_tag")) + self.search_for_tag_action.setText(Translations["tag.search_for_tag"]) self.bg_button.addAction(self.search_for_tag_action) # add_to_search_action = QAction(self) # add_to_search_action.setText(Translations.translate_formatted("tag.add_to_search")) diff --git a/tagstudio/src/qt/widgets/tag_color_label.py b/tagstudio/src/qt/widgets/tag_color_label.py index 31158edf2..2557eb817 100644 --- a/tagstudio/src/qt/widgets/tag_color_label.py +++ b/tagstudio/src/qt/widgets/tag_color_label.py @@ -60,7 +60,7 @@ def __init__( self.bg_button.setFlat(True) edit_action = QAction(self) - edit_action.setText(Translations.formatted("generic.edit")) + edit_action.setText(Translations["generic.edit"]) edit_action.triggered.connect(self.on_click.emit) self.bg_button.addAction(edit_action) self.bg_button.setContextMenuPolicy(Qt.ContextMenuPolicy.ActionsContextMenu) diff --git a/tagstudio/src/qt/widgets/tag_color_preview.py b/tagstudio/src/qt/widgets/tag_color_preview.py index 5d8c79ce8..be8dba472 100644 --- a/tagstudio/src/qt/widgets/tag_color_preview.py +++ b/tagstudio/src/qt/widgets/tag_color_preview.py @@ -70,7 +70,7 @@ def set_tag_color_group(self, color_group: TagColorGroup | None): f"{color_group.name} ({self.lib.get_namespace_name(color_group.namespace)})" ) else: - self.button.setText(Translations.formatted("color.title.no_color")) + self.button.setText(Translations["color.title.no_color"]) primary_color = self._get_primary_color(color_group) border_color = ( From c7578570ab367a1ef76797ccea9a1aaeedc1ddee Mon Sep 17 00:00:00 2001 From: Jann Stute Date: Tue, 25 Feb 2025 21:25:15 +0100 Subject: [PATCH 6/9] refactor: remove further unnecessary format calls --- tagstudio/src/core/library/alchemy/library.py | 6 +++--- tagstudio/src/qt/ts_qt.py | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tagstudio/src/core/library/alchemy/library.py b/tagstudio/src/core/library/alchemy/library.py index e35720aec..029bb0480 100644 --- a/tagstudio/src/core/library/alchemy/library.py +++ b/tagstudio/src/core/library/alchemy/library.py @@ -367,9 +367,9 @@ def open_sqlite_library(self, library_dir: Path, is_new: bool) -> LibraryStatus: db_version = db_result.value # type: ignore if db_version < 6: # NOTE: DB_VERSION 6 is the first supported SQL DB version. - mismatch_text = Translations.formatted("status.library_version_mismatch") - found_text = Translations.formatted("status.library_version_found") - expected_text = Translations.formatted("status.library_version_expected") + mismatch_text = Translations["status.library_version_mismatch"] + found_text = Translations["status.library_version_found"] + expected_text = Translations["status.library_version_expected"] return LibraryStatus( success=False, message=( diff --git a/tagstudio/src/qt/ts_qt.py b/tagstudio/src/qt/ts_qt.py index 6fe3431c5..5f83445ca 100644 --- a/tagstudio/src/qt/ts_qt.py +++ b/tagstudio/src/qt/ts_qt.py @@ -324,8 +324,8 @@ def start(self) -> None: self.tag_search_panel.set_driver(self) self.add_tag_modal = PanelModal( widget=self.tag_search_panel, - title=Translations.formatted("tag.add.plural"), - window_title=Translations.formatted("tag.add.plural"), + title=Translations["tag.add.plural"], + window_title=Translations["tag.add.plural"], ) self.tag_search_panel.tag_chosen.connect( lambda t: ( From c75ad9cfd330cbe27296204ddee5a4788ffc0884 Mon Sep 17 00:00:00 2001 From: Jann Stute Date: Tue, 25 Feb 2025 21:39:09 +0100 Subject: [PATCH 7/9] refactor: replace calls for Translations.formatted with calls to str.format and remove some unused code --- tagstudio/src/qt/modals/about.py | 3 +- tagstudio/src/qt/modals/delete_unlinked.py | 14 ++---- tagstudio/src/qt/modals/drop_import.py | 9 ++-- tagstudio/src/qt/modals/fix_dupes.py | 4 +- tagstudio/src/qt/modals/fix_unlinked.py | 4 +- tagstudio/src/qt/modals/mirror_entities.py | 8 +-- tagstudio/src/qt/modals/relink_unlinked.py | 3 +- tagstudio/src/qt/modals/tag_database.py | 3 +- tagstudio/src/qt/modals/tag_search.py | 2 +- tagstudio/src/qt/translations.py | 30 ++--------- tagstudio/src/qt/ts_qt.py | 50 +++++++++---------- tagstudio/src/qt/widgets/color_box.py | 2 +- tagstudio/src/qt/widgets/item_thumb.py | 2 +- tagstudio/src/qt/widgets/landing.py | 4 +- tagstudio/src/qt/widgets/migration_modal.py | 6 +-- .../qt/widgets/preview/field_containers.py | 2 +- .../src/qt/widgets/preview/preview_thumb.py | 4 +- 17 files changed, 56 insertions(+), 94 deletions(-) diff --git a/tagstudio/src/qt/modals/about.py b/tagstudio/src/qt/modals/about.py index d49168d80..1a3e4dd55 100644 --- a/tagstudio/src/qt/modals/about.py +++ b/tagstudio/src/qt/modals/about.py @@ -44,8 +44,7 @@ def __init__(self, config_path): if ff_version["ffprobe"] is not None: ffprobe = 'Found (' + ff_version["ffprobe"] + ")" self.content_widget = QLabel( - Translations.formatted( - "about.content", + Translations["about.content"].format( version=VERSION, branch=VERSION_BRANCH, config_path=config_path, diff --git a/tagstudio/src/qt/modals/delete_unlinked.py b/tagstudio/src/qt/modals/delete_unlinked.py index 8828c7ed9..740cafac0 100644 --- a/tagstudio/src/qt/modals/delete_unlinked.py +++ b/tagstudio/src/qt/modals/delete_unlinked.py @@ -32,8 +32,7 @@ def __init__(self, driver: "QtDriver", tracker: MissingRegistry): self.root_layout.setContentsMargins(6, 6, 6, 6) self.desc_widget = QLabel( - Translations.formatted( - "entries.unlinked.delete.confirm", + Translations["entries.unlinked.delete.confirm"].format( count=self.tracker.missing_file_entries_count, ) ) @@ -66,8 +65,8 @@ def __init__(self, driver: "QtDriver", tracker: MissingRegistry): def refresh_list(self): self.desc_widget.setText( - Translations.formatted( - "entries.unlinked.delete.confirm", count=self.tracker.missing_file_entries_count + Translations["entries.unlinked.delete.confirm"].format( + count=self.tracker.missing_file_entries_count ) ) @@ -78,13 +77,6 @@ def refresh_list(self): self.model.appendRow(item) def delete_entries(self): - def displayed_text(x): - return Translations.formatted( - "entries.unlinked.delete.deleting_count", - idx=x, - count=self.tracker.missing_file_entries_count, - ) - pw = ProgressWidget( cancel_button_text=None, minimum=0, diff --git a/tagstudio/src/qt/modals/drop_import.py b/tagstudio/src/qt/modals/drop_import.py index b88c3ded9..25be0723a 100644 --- a/tagstudio/src/qt/modals/drop_import.py +++ b/tagstudio/src/qt/modals/drop_import.py @@ -131,8 +131,8 @@ def ask_duplicates_choice(self): self.desc_widget.setText( Translations["drop_import.duplicates_choice.singular"] if len(self.duplicate_files) == 1 - else Translations.formatted( - "drop_import.duplicates_choice.plural", count=len(self.duplicate_files) + else Translations["drop_import.duplicates_choice.plural"].format( + count=len(self.duplicate_files) ) ) @@ -154,10 +154,11 @@ def begin_transfer(self, choice: DuplicateChoice | None = None): return def displayed_text(x): - return Translations.formatted( + return Translations[ "drop_import.progress.label.singular" if x[0] + 1 == 1 - else "drop_import.progress.label.plural", + else "drop_import.progress.label.plural" + ].format( count=x[0] + 1, suffix=f" {x[1]} {self.choice.value}" if self.choice else "", ) diff --git a/tagstudio/src/qt/modals/fix_dupes.py b/tagstudio/src/qt/modals/fix_dupes.py index e3e29acb4..78570e7c8 100644 --- a/tagstudio/src/qt/modals/fix_dupes.py +++ b/tagstudio/src/qt/modals/fix_dupes.py @@ -114,10 +114,10 @@ def set_dupe_count(self, count: int): self.dupe_count.setText(Translations["file.duplicates.matches_uninitialized"]) elif count == 0: self.mirror_button.setDisabled(True) - self.dupe_count.setText(Translations.formatted("file.duplicates.matches", count=count)) + self.dupe_count.setText(Translations["file.duplicates.matches"].format(count=count)) else: self.mirror_button.setDisabled(False) - self.dupe_count.setText(Translations.formatted("file.duplicates.matches", count=count)) + self.dupe_count.setText(Translations["file.duplicates.matches"].format(count=count)) @override def keyPressEvent(self, event: QtGui.QKeyEvent) -> None: # noqa N802 diff --git a/tagstudio/src/qt/modals/fix_unlinked.py b/tagstudio/src/qt/modals/fix_unlinked.py index c4ce7298e..a8270d45b 100644 --- a/tagstudio/src/qt/modals/fix_unlinked.py +++ b/tagstudio/src/qt/modals/fix_unlinked.py @@ -135,9 +135,7 @@ def set_missing_count(self, count: int | None = None): self.search_button.setDisabled(self.missing_count == 0) self.delete_button.setDisabled(self.missing_count == 0) self.missing_count_label.setText( - Translations.formatted( - "entries.unlinked.missing_count.some", count=self.missing_count - ) + Translations["entries.unlinked.missing_count.some"].format(count=self.missing_count) ) @override diff --git a/tagstudio/src/qt/modals/mirror_entities.py b/tagstudio/src/qt/modals/mirror_entities.py index c46b958ad..2e798a8af 100644 --- a/tagstudio/src/qt/modals/mirror_entities.py +++ b/tagstudio/src/qt/modals/mirror_entities.py @@ -32,7 +32,7 @@ def __init__(self, driver: "QtDriver", tracker: DupeRegistry): self.tracker = tracker self.desc_widget = QLabel( - Translations.formatted("entries.mirror.confirmation", count=self.tracker.groups_count) + Translations["entries.mirror.confirmation"].format(count=self.tracker.groups_count) ) self.desc_widget.setObjectName("descriptionLabel") self.desc_widget.setWordWrap(True) @@ -63,7 +63,7 @@ def __init__(self, driver: "QtDriver", tracker: DupeRegistry): def refresh_list(self): self.desc_widget.setText( - Translations.formatted("entries.mirror.confirmation", count=self.tracker.groups_count) + Translations["entries.mirror.confirmation"].format(count=self.tracker.groups_count) ) self.model.clear() @@ -72,8 +72,8 @@ def refresh_list(self): def mirror_entries(self): def displayed_text(x): - return Translations.formatted( - "entries.mirror.label", idx=x + 1, count=self.tracker.groups_count + return Translations["entries.mirror.label"].format( + idx=x + 1, count=self.tracker.groups_count ) pw = ProgressWidget( diff --git a/tagstudio/src/qt/modals/relink_unlinked.py b/tagstudio/src/qt/modals/relink_unlinked.py index 680f40c90..5dbee80ad 100644 --- a/tagstudio/src/qt/modals/relink_unlinked.py +++ b/tagstudio/src/qt/modals/relink_unlinked.py @@ -18,8 +18,7 @@ def __init__(self, tracker: MissingRegistry): def repair_entries(self): def displayed_text(x): - return Translations.formatted( - "entries.unlinked.relink.attempting", + return Translations["entries.unlinked.relink.attempting"].format( idx=x, missing_count=self.tracker.missing_file_entries_count, fixed_count=self.tracker.files_fixed_count, diff --git a/tagstudio/src/qt/modals/tag_database.py b/tagstudio/src/qt/modals/tag_database.py index 06eb697ba..3e287a8f6 100644 --- a/tagstudio/src/qt/modals/tag_database.py +++ b/tagstudio/src/qt/modals/tag_database.py @@ -60,8 +60,7 @@ def delete_tag(self, tag: Tag): message_box = QMessageBox( QMessageBox.Question, # type: ignore Translations["tag.remove"], - Translations.formatted( - "tag.confirm_delete", + Translations["tag.confirm_delete"].format( tag_name=self.lib.tag_display_name(tag.id), ), QMessageBox.Ok | QMessageBox.Cancel, # type: ignore diff --git a/tagstudio/src/qt/modals/tag_search.py b/tagstudio/src/qt/modals/tag_search.py index ff8903b99..1bfbe28f4 100644 --- a/tagstudio/src/qt/modals/tag_search.py +++ b/tagstudio/src/qt/modals/tag_search.py @@ -120,7 +120,7 @@ def set_driver(self, driver): def build_create_button(self, query: str | None, key: str, format_args: dict): """Constructs a "Create & Add Tag" QPushButton.""" - create_button = QPushButton(Translations.formatted(key, **format_args), self) + create_button = QPushButton(Translations[key].format(**format_args), self) create_button.setFlat(True) create_button.setMinimumSize(22, 22) diff --git a/tagstudio/src/qt/translations.py b/tagstudio/src/qt/translations.py index c2508f075..0d9a63258 100644 --- a/tagstudio/src/qt/translations.py +++ b/tagstudio/src/qt/translations.py @@ -3,16 +3,13 @@ import structlog import ujson -from PySide6.QtCore import QObject, Signal logger = structlog.get_logger(__name__) DEFAULT_TRANSLATION = "en" -class TranslatedString(QObject): - changed = Signal(str) - +class TranslatedString: __default_value: str __value: str | None = None @@ -26,9 +23,7 @@ def value(self) -> str: @value.setter def value(self, value: str | None): - if self.__value != value: - self.__value = value - self.changed.emit(self.__value) + self.__value = value class Translator: @@ -57,25 +52,8 @@ def translate_with_setter(self, setter: Callable[[str], None], key: str, **kwarg Also formats the translation with the given keyword arguments. """ - # TODO: Fix so deleted Qt objects aren't referenced any longer - # if key in self._strings: - # self._strings[key].changed.connect(lambda text: setter(self.__format(text, **kwargs))) - setter(self.formatted(key, **kwargs)) - - def __format(self, text: str, **kwargs) -> str: - try: - return text.format(**kwargs) - except (KeyError, ValueError): - logger.error( - "[Translations] Error while formatting translation.", - text=text, - kwargs=kwargs, - language=self._lang, - ) - return text - - def formatted(self, key: str, **kwargs) -> str: - return self.__format(self[key], **kwargs) + # TODO replace calls to this method with direct calls to setter + setter(Translations[key].format(**kwargs)) def __getitem__(self, key: str) -> str: return self._strings[key].value if key in self._strings else f"[{key}]" diff --git a/tagstudio/src/qt/ts_qt.py b/tagstudio/src/qt/ts_qt.py index 5f83445ca..7e59180c0 100644 --- a/tagstudio/src/qt/ts_qt.py +++ b/tagstudio/src/qt/ts_qt.py @@ -498,7 +498,7 @@ def start(self) -> None: edit_menu.addSeparator() self.delete_file_action = QAction( - Translations.formatted("menu.delete_selected_files_ambiguous", trash_term=trash_term()), + Translations["menu.delete_selected_files_ambiguous"].format(trash_term=trash_term()), menu_bar, ) self.delete_file_action.triggered.connect(lambda f="": self.delete_files_callback(f)) @@ -882,8 +882,8 @@ def close_library(self, is_shutdown: bool = False): end_time = time.time() self.main_window.statusbar.showMessage( - Translations.formatted( - "status.library_closed", time_span=format_timespan(end_time - start_time) + Translations["status.library_closed"].format( + time_span=format_timespan(end_time - start_time) ) ) @@ -894,8 +894,7 @@ def backup_library(self): target_path = self.lib.save_library_backup_to_disk() end_time = time.time() self.main_window.statusbar.showMessage( - Translations.formatted( - "status.library_backup_success", + Translations["status.library_backup_success"].format( path=target_path, time_span=format_timespan(end_time - start_time), ) @@ -993,8 +992,8 @@ def delete_files_callback(self, origin_path: str | Path, origin_id: int | None = self.preview_panel.thumb.stop_file_use() if delete_file(self.lib.library_dir / f): self.main_window.statusbar.showMessage( - Translations.formatted( - "status.deleting_file", i=i, count=len(pending), path=f + Translations["status.deleting_file"].format( + i=i, count=len(pending), path=f ) ) self.main_window.statusbar.repaint() @@ -1011,17 +1010,17 @@ def delete_files_callback(self, origin_path: str | Path, origin_id: int | None = self.main_window.statusbar.showMessage(Translations["status.deleted_none"]) elif len(self.selected) <= 1 and deleted_count == 1: self.main_window.statusbar.showMessage( - Translations.formatted("status.deleted_file_plural", count=deleted_count) + Translations["status.deleted_file_plural"].format(count=deleted_count) ) elif len(self.selected) > 1 and deleted_count == 0: self.main_window.statusbar.showMessage(Translations["status.deleted_none"]) elif len(self.selected) > 1 and deleted_count < len(self.selected): self.main_window.statusbar.showMessage( - Translations.formatted("status.deleted_partial_warning", count=deleted_count) + Translations["status.deleted_partial_warning"].format(count=deleted_count) ) elif len(self.selected) > 1 and deleted_count == len(self.selected): self.main_window.statusbar.showMessage( - Translations.formatted("status.deleted_file_plural", count=deleted_count) + Translations["status.deleted_file_plural"].format(count=deleted_count) ) self.main_window.statusbar.repaint() @@ -1038,8 +1037,8 @@ def delete_file_confirmation(self, count: int, filename: Path | None = None) -> # https://github.com/arsenetar/send2trash/issues/28 # This warning is applied to all platforms until at least macOS and Linux can be verified # to not exhibit this same behavior. - perm_warning_msg = Translations.formatted( - "trash.dialog.permanent_delete_warning", trash_term=trash_term() + perm_warning_msg = Translations["trash.dialog.permanent_delete_warning"].format( + trash_term=trash_term() ) perm_warning: str = ( f"

" @@ -1056,8 +1055,8 @@ def delete_file_confirmation(self, count: int, filename: Path | None = None) -> ) msg.setIcon(QMessageBox.Icon.Warning) if count <= 1: - msg_text = Translations.formatted( - "trash.dialog.move.confirmation.singular", trash_term=trash_term() + msg_text = Translations["trash.dialog.move.confirmation.singular"].format( + trash_term=trash_term() ) msg.setText( f"

{msg_text}

" @@ -1066,8 +1065,7 @@ def delete_file_confirmation(self, count: int, filename: Path | None = None) -> f"{perm_warning}
" ) elif count > 1: - msg_text = Translations.formatted( - "trash.dialog.move.confirmation.plural", + msg_text = Translations["trash.dialog.move.confirmation.plural"].format( count=count, trash_term=trash_term(), ) @@ -1102,10 +1100,11 @@ def add_new_files_callback(self): lambda x: ( pw.update_progress(x + 1), pw.update_label( - Translations.formatted( + Translations[ "library.refresh.scanning.plural" if x + 1 != 1 - else "library.refresh.scanning.singular", + else "library.refresh.scanning.singular" + ].format( searched_count=f"{x+1:n}", found_count=f"{tracker.files_count:n}", ) @@ -1144,8 +1143,8 @@ def add_new_files_runnable(self, tracker: RefreshDirTracker): iterator.value.connect( lambda: ( pw.update_label( - Translations.formatted( - "entries.running.dialog.new_entries", total=f"{files_count:n}" + Translations["entries.running.dialog.new_entries"].format( + total=f"{files_count:n}" ) ), ) @@ -1704,8 +1703,7 @@ def filter_items(self, filter: FilterState | None = None) -> None: # inform user about completed search self.main_window.statusbar.showMessage( - Translations.formatted( - "status.results_found", + Translations["status.results_found"].format( count=results.total_count, time_span=format_timespan(end_time - start_time), ) @@ -1831,11 +1829,9 @@ def update_language_settings(self, language: str): def open_library(self, path: Path) -> None: """Open a TagStudio library.""" - translation_params = {"key": "splash.opening_library", "library_path": str(path)} - Translations.translate_with_setter( - self.main_window.landing_widget.set_status_label, **translation_params - ) - self.main_window.statusbar.showMessage(Translations.formatted(**translation_params), 3) + message = Translations["splash.opening_library"].format(library_path=str(path)) + self.main_window.landing_widget.set_status_label(message) + self.main_window.statusbar.showMessage(message, 3) self.main_window.repaint() if self.lib.library_dir: diff --git a/tagstudio/src/qt/widgets/color_box.py b/tagstudio/src/qt/widgets/color_box.py index ee7b2d99a..fb920c715 100644 --- a/tagstudio/src/qt/widgets/color_box.py +++ b/tagstudio/src/qt/widgets/color_box.py @@ -146,7 +146,7 @@ def delete_color(self, color_group: TagColorGroup): message_box = QMessageBox( QMessageBox.Icon.Warning, Translations["color.delete"], - Translations.formatted("color.confirm_delete", color_name=color_group.name), + Translations["color.confirm_delete"].format(color_name=color_group.name), ) cancel_button = message_box.addButton( Translations["generic.cancel_alt"], QMessageBox.ButtonRole.RejectRole diff --git a/tagstudio/src/qt/widgets/item_thumb.py b/tagstudio/src/qt/widgets/item_thumb.py index 7618bb2ad..dc637073d 100644 --- a/tagstudio/src/qt/widgets/item_thumb.py +++ b/tagstudio/src/qt/widgets/item_thumb.py @@ -222,7 +222,7 @@ def __init__( open_explorer_action.triggered.connect(self.opener.open_explorer) self.delete_action = QAction( - Translations.formatted("trash.context.ambiguous", trash_term=trash_term()), self + Translations["trash.context.ambiguous"].format(trash_term=trash_term()), self ) self.thumb_button.addAction(open_file_action) diff --git a/tagstudio/src/qt/widgets/landing.py b/tagstudio/src/qt/widgets/landing.py index e6b1775f2..f584a3205 100644 --- a/tagstudio/src/qt/widgets/landing.py +++ b/tagstudio/src/qt/widgets/landing.py @@ -62,7 +62,7 @@ def __init__(self, driver: "QtDriver", pixel_ratio: float): else: open_shortcut_text = "(Ctrl+O)" self.open_button: QPushButton = QPushButton( - Translations.formatted("landing.open_create_library", shortcut=open_shortcut_text) + Translations["landing.open_create_library"].format(shortcut=open_shortcut_text) ) self.open_button.setMinimumWidth(200) self.open_button.clicked.connect(self.driver.open_library_from_dialog) @@ -160,7 +160,7 @@ def animate_logo_pop(self): # self.status_pos_anim.setEndValue(self.status_label.pos()) # self.status_pos_anim.start() - def set_status_label(self, text=str): + def set_status_label(self, text: str): """Set the text of the status label. Args: diff --git a/tagstudio/src/qt/widgets/migration_modal.py b/tagstudio/src/qt/widgets/migration_modal.py index f3c69d90d..09fd2845f 100644 --- a/tagstudio/src/qt/widgets/migration_modal.py +++ b/tagstudio/src/qt/widgets/migration_modal.py @@ -57,7 +57,7 @@ def __init__(self, path: Path): self.is_migration_initialized: bool = False self.discrepancies: list[str] = [] - self.title: str = Translations.formatted("json_migration.title", path=self.path) + self.title: str = Translations["json_migration.title"].format(path=self.path) self.warning: str = "(!)" self.old_entry_count: int = 0 @@ -405,8 +405,8 @@ def migration_iterator(self): logger.info('Temporary migration file "temp_path" already exists. Removing...') self.temp_path.unlink() self.sql_lib.open_sqlite_library(self.json_lib.library_dir, is_new=True) - yield Translations.formatted( - "json_migration.migrating_files_entries", entries=len(self.json_lib.entries) + yield Translations["json_migration.migrating_files_entries"].format( + entries=len(self.json_lib.entries) ) self.sql_lib.migrate_json_to_sqlite(self.json_lib) yield Translations["json_migration.checking_for_parity"] diff --git a/tagstudio/src/qt/widgets/preview/field_containers.py b/tagstudio/src/qt/widgets/preview/field_containers.py index 8c9914048..a6d42232d 100644 --- a/tagstudio/src/qt/widgets/preview/field_containers.py +++ b/tagstudio/src/qt/widgets/preview/field_containers.py @@ -246,7 +246,7 @@ def add_to_cluster(tag_id: int, p_ids: list[int] | None = None): return cats def remove_field_prompt(self, name: str) -> str: - return Translations.formatted("library.field.confirm_remove", name=name) + return Translations["library.field.confirm_remove"].format(name=name) def add_field_to_selected(self, field_list: list): """Add list of entry fields to one or more selected items. diff --git a/tagstudio/src/qt/widgets/preview/preview_thumb.py b/tagstudio/src/qt/widgets/preview/preview_thumb.py index 65be56301..38a89ac08 100644 --- a/tagstudio/src/qt/widgets/preview/preview_thumb.py +++ b/tagstudio/src/qt/widgets/preview/preview_thumb.py @@ -57,7 +57,7 @@ def __init__(self, library: Library, driver: "QtDriver"): self.open_file_action = QAction(Translations["file.open_file"], self) self.open_explorer_action = QAction(open_file_str(), self) self.delete_action = QAction( - Translations.formatted("trash.context.ambiguous", trash_term=trash_term()), self + Translations["trash.context.ambiguous"].format(trash_term=trash_term()), self ) self.preview_img = QPushButtonWrapper() @@ -378,7 +378,7 @@ def update_preview(self, filepath: Path, ext: str) -> dict: self.delete_action.triggered.disconnect() self.delete_action.setText( - Translations.formatted("trash.context.singular", trash_term=trash_term()) + Translations["trash.context.singular"].format(trash_term=trash_term()) ) self.delete_action.triggered.connect( lambda checked=False, f=filepath: self.driver.delete_files_callback(f) From 580b6b26a5df110f0d5323294fc50f69b85ad4c8 Mon Sep 17 00:00:00 2001 From: Jann Stute Date: Tue, 25 Feb 2025 21:44:35 +0100 Subject: [PATCH 8/9] refactor: remove TranslatedString class --- tagstudio/src/qt/translations.py | 29 +++++------------------------ 1 file changed, 5 insertions(+), 24 deletions(-) diff --git a/tagstudio/src/qt/translations.py b/tagstudio/src/qt/translations.py index 0d9a63258..1ad4684a5 100644 --- a/tagstudio/src/qt/translations.py +++ b/tagstudio/src/qt/translations.py @@ -9,30 +9,13 @@ DEFAULT_TRANSLATION = "en" -class TranslatedString: - __default_value: str - __value: str | None = None - - def __init__(self, value: str): - super().__init__() - self.__default_value = value - - @property - def value(self) -> str: - return self.__value or self.__default_value - - @value.setter - def value(self, value: str | None): - self.__value = value - - class Translator: - _strings: dict[str, TranslatedString] = {} + _default_strings: dict[str, str] + _strings: dict[str, str] = {} _lang: str = DEFAULT_TRANSLATION def __init__(self): - for k, v in self.__get_translation_dict(DEFAULT_TRANSLATION).items(): - self._strings[k] = TranslatedString(v) + self._default_strings = self.__get_translation_dict(DEFAULT_TRANSLATION) def __get_translation_dict(self, lang: str) -> dict[str, str]: with open( @@ -43,9 +26,7 @@ def __get_translation_dict(self, lang: str) -> dict[str, str]: def change_language(self, lang: str): self._lang = lang - translated = self.__get_translation_dict(lang) - for k in self._strings: - self._strings[k].value = translated.get(k, None) + self._strings = self.__get_translation_dict(lang) def translate_with_setter(self, setter: Callable[[str], None], key: str, **kwargs): """Calls `setter` everytime the language changes and passes the translated string for `key`. @@ -56,7 +37,7 @@ def translate_with_setter(self, setter: Callable[[str], None], key: str, **kwarg setter(Translations[key].format(**kwargs)) def __getitem__(self, key: str) -> str: - return self._strings[key].value if key in self._strings else f"[{key}]" + return self._strings.get(key) or self._default_strings.get(key) or f"[{key}]" Translations = Translator() From ea0d3a86a867d6fed74a24d7827e5ad1f57d928e Mon Sep 17 00:00:00 2001 From: Jann Stute Date: Tue, 25 Feb 2025 21:59:07 +0100 Subject: [PATCH 9/9] refactor: replace translate_with_setter with direct calls to the setter --- tagstudio/src/qt/main_window.py | 4 +- tagstudio/src/qt/modals/about.py | 2 +- tagstudio/src/qt/modals/add_field.py | 2 +- tagstudio/src/qt/modals/build_color.py | 8 +-- tagstudio/src/qt/modals/build_namespace.py | 8 +-- tagstudio/src/qt/modals/build_tag.py | 8 ++- tagstudio/src/qt/modals/delete_unlinked.py | 6 +-- tagstudio/src/qt/modals/drop_import.py | 6 +-- tagstudio/src/qt/modals/file_extension.py | 10 ++-- tagstudio/src/qt/modals/fix_dupes.py | 2 +- tagstudio/src/qt/modals/fix_unlinked.py | 6 +-- tagstudio/src/qt/modals/folders_to_tags.py | 2 +- tagstudio/src/qt/modals/merge_dupe_entries.py | 4 +- tagstudio/src/qt/modals/mirror_entities.py | 4 +- tagstudio/src/qt/modals/relink_unlinked.py | 2 +- tagstudio/src/qt/modals/tag_color_manager.py | 6 +-- tagstudio/src/qt/modals/tag_database.py | 4 +- tagstudio/src/qt/modals/tag_search.py | 8 +-- tagstudio/src/qt/translations.py | 9 ---- tagstudio/src/qt/ts_qt.py | 49 ++++++++----------- tagstudio/src/qt/widgets/preview_panel.py | 2 +- 21 files changed, 59 insertions(+), 93 deletions(-) diff --git a/tagstudio/src/qt/main_window.py b/tagstudio/src/qt/main_window.py index ebf36a0fd..d51a8afd2 100644 --- a/tagstudio/src/qt/main_window.py +++ b/tagstudio/src/qt/main_window.py @@ -74,7 +74,7 @@ def setupUi(self, MainWindow): # Thumbnail Size placeholder self.thumb_size_combobox = QComboBox(self.centralwidget) self.thumb_size_combobox.setObjectName(u"thumbSizeComboBox") - Translations.translate_with_setter(self.thumb_size_combobox.setPlaceholderText, "home.thumbnail_size") + self.thumb_size_combobox.setPlaceholderText(Translations["home.thumbnail_size"]) self.thumb_size_combobox.setCurrentText("") sizePolicy = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) @@ -142,7 +142,7 @@ def setupUi(self, MainWindow): self.horizontalLayout_2.addWidget(self.forwardButton) self.searchField = QLineEdit(self.centralwidget) - Translations.translate_with_setter(self.searchField.setPlaceholderText, "home.search_entries") + self.searchField.setPlaceholderText(Translations["home.search_entries"]) self.searchField.setObjectName(u"searchField") self.searchField.setMinimumSize(QSize(0, 32)) diff --git a/tagstudio/src/qt/modals/about.py b/tagstudio/src/qt/modals/about.py index 1a3e4dd55..8d921ad59 100644 --- a/tagstudio/src/qt/modals/about.py +++ b/tagstudio/src/qt/modals/about.py @@ -16,7 +16,7 @@ class AboutModal(QWidget): def __init__(self, config_path): super().__init__() - Translations.translate_with_setter(self.setWindowTitle, "about.title") + self.setWindowTitle(Translations["about.title"]) self.fc: FfmpegChecker = FfmpegChecker() self.rm: ResourceManager = ResourceManager() diff --git a/tagstudio/src/qt/modals/add_field.py b/tagstudio/src/qt/modals/add_field.py index 6d34b6f65..ee5d3c253 100644 --- a/tagstudio/src/qt/modals/add_field.py +++ b/tagstudio/src/qt/modals/add_field.py @@ -31,7 +31,7 @@ def __init__(self, library: Library): # [Cancel] [Save] super().__init__() self.lib = library - Translations.translate_with_setter(self.setWindowTitle, "library.field.add") + self.setWindowTitle(Translations["library.field.add"]) self.setWindowModality(Qt.WindowModality.ApplicationModal) self.setMinimumSize(400, 300) self.root_layout = QVBoxLayout(self) diff --git a/tagstudio/src/qt/modals/build_color.py b/tagstudio/src/qt/modals/build_color.py index 0e55f89b7..e9abcbf88 100644 --- a/tagstudio/src/qt/modals/build_color.py +++ b/tagstudio/src/qt/modals/build_color.py @@ -76,9 +76,7 @@ def __init__(self, library: Library, color_group: TagColorGroup): self.name_field = QLineEdit() self.name_field.setFixedHeight(24) self.name_field.textChanged.connect(self.on_text_changed) - Translations.translate_with_setter( - self.name_field.setPlaceholderText, "library_object.name_required" - ) + self.name_field.setPlaceholderText(Translations["library_object.name_required"]) self.form_layout.addRow(self.name_title, self.name_field) # Slug ----------------------------------------------------------------- @@ -86,9 +84,7 @@ def __init__(self, library: Library, color_group: TagColorGroup): self.slug_field = QLineEdit() self.slug_field.setEnabled(False) self.slug_field.setFixedHeight(24) - Translations.translate_with_setter( - self.slug_field.setPlaceholderText, "library_object.slug_required" - ) + self.slug_field.setPlaceholderText(Translations["library_object.slug_required"]) self.form_layout.addRow(self.slug_title, self.slug_field) # Primary -------------------------------------------------------------- diff --git a/tagstudio/src/qt/modals/build_namespace.py b/tagstudio/src/qt/modals/build_namespace.py index 1f62967ec..6566d0e43 100644 --- a/tagstudio/src/qt/modals/build_namespace.py +++ b/tagstudio/src/qt/modals/build_namespace.py @@ -53,9 +53,7 @@ def __init__(self, library: Library, namespace: Namespace | None = None): self.name_field = QLineEdit() self.name_field.setFixedHeight(24) self.name_field.textChanged.connect(self.on_text_changed) - Translations.translate_with_setter( - self.name_field.setPlaceholderText, "library_object.name_required" - ) + self.name_field.setPlaceholderText(Translations["library_object.name_required"]) self.name_layout.addWidget(self.name_field) # Slug ----------------------------------------------------------------- @@ -70,9 +68,7 @@ def __init__(self, library: Library, namespace: Namespace | None = None): self.slug_field = QLineEdit() self.slug_field.setFixedHeight(24) self.slug_field.setEnabled(False) - Translations.translate_with_setter( - self.slug_field.setPlaceholderText, "library_object.slug_required" - ) + self.slug_field.setPlaceholderText(Translations["library_object.slug_required"]) self.slug_layout.addWidget(self.slug_field) # Description ---------------------------------------------------------- diff --git a/tagstudio/src/qt/modals/build_tag.py b/tagstudio/src/qt/modals/build_tag.py index 0330d09f2..c9657b8f4 100644 --- a/tagstudio/src/qt/modals/build_tag.py +++ b/tagstudio/src/qt/modals/build_tag.py @@ -91,9 +91,7 @@ def __init__(self, library: Library, tag: Tag | None = None): self.name_field = QLineEdit() self.name_field.setFixedHeight(24) self.name_field.textChanged.connect(self.on_name_changed) - Translations.translate_with_setter( - self.name_field.setPlaceholderText, "tag.tag_name_required" - ) + self.name_field.setPlaceholderText(Translations["tag.tag_name_required"]) self.name_layout.addWidget(self.name_field) # Shorthand ------------------------------------------------------------ @@ -169,8 +167,8 @@ def __init__(self, library: Library, tag: Tag | None = None): tsp = TagSearchPanel(self.lib, exclude_ids) tsp.tag_chosen.connect(lambda x: self.add_parent_tag_callback(x)) self.add_tag_modal = PanelModal(tsp) - Translations.translate_with_setter(self.add_tag_modal.setTitle, "tag.parent_tags.add") - Translations.translate_with_setter(self.add_tag_modal.setWindowTitle, "tag.parent_tags.add") + self.add_tag_modal.setTitle(Translations["tag.parent_tags.add"]) + self.add_tag_modal.setWindowTitle(Translations["tag.parent_tags.add"]) self.parent_tags_add_button.clicked.connect(self.add_tag_modal.show) # Color ---------------------------------------------------------------- diff --git a/tagstudio/src/qt/modals/delete_unlinked.py b/tagstudio/src/qt/modals/delete_unlinked.py index 740cafac0..c038b7b48 100644 --- a/tagstudio/src/qt/modals/delete_unlinked.py +++ b/tagstudio/src/qt/modals/delete_unlinked.py @@ -25,7 +25,7 @@ def __init__(self, driver: "QtDriver", tracker: MissingRegistry): super().__init__() self.driver = driver self.tracker = tracker - Translations.translate_with_setter(self.setWindowTitle, "entries.unlinked.delete") + self.setWindowTitle(Translations["entries.unlinked.delete"]) self.setWindowModality(Qt.WindowModality.ApplicationModal) self.setMinimumSize(500, 400) self.root_layout = QVBoxLayout(self) @@ -82,8 +82,8 @@ def delete_entries(self): minimum=0, maximum=0, ) - Translations.translate_with_setter(pw.setWindowTitle, "entries.unlinked.delete.deleting") - Translations.translate_with_setter(pw.update_label, "entries.unlinked.delete.deleting") + pw.setWindowTitle(Translations["entries.unlinked.delete.deleting"]) + pw.update_label(Translations["entries.unlinked.delete.deleting"]) pw.show() r = CustomRunnable(self.tracker.execute_deletion) diff --git a/tagstudio/src/qt/modals/drop_import.py b/tagstudio/src/qt/modals/drop_import.py index 25be0723a..d0d1daffe 100644 --- a/tagstudio/src/qt/modals/drop_import.py +++ b/tagstudio/src/qt/modals/drop_import.py @@ -37,7 +37,7 @@ def __init__(self, driver: "QtDriver"): self.driver: QtDriver = driver # Widget ====================== - Translations.translate_with_setter(self.setWindowTitle, "drop_import.title") + self.setWindowTitle(Translations["drop_import.title"]) self.setWindowModality(Qt.WindowModality.ApplicationModal) self.setMinimumSize(500, 400) self.root_layout = QVBoxLayout(self) @@ -168,8 +168,8 @@ def displayed_text(x): minimum=0, maximum=len(self.files), ) - Translations.translate_with_setter(pw.setWindowTitle, "drop_import.progress.window_title") - Translations.translate_with_setter(pw.update_label, "drop_import.progress.label.initial") + pw.setWindowTitle(Translations["drop_import.progress.window_title"]) + pw.update_label(Translations["drop_import.progress.label.initial"]) pw.from_iterable_function( self.copy_files, diff --git a/tagstudio/src/qt/modals/file_extension.py b/tagstudio/src/qt/modals/file_extension.py index 1a566d3ab..8e9c25295 100644 --- a/tagstudio/src/qt/modals/file_extension.py +++ b/tagstudio/src/qt/modals/file_extension.py @@ -36,7 +36,7 @@ def __init__(self, library: "Library"): super().__init__() # Initialize Modal ===================================================== self.lib = library - Translations.translate_with_setter(self.setWindowTitle, "ignore_list.title") + self.setWindowTitle(Translations["ignore_list.title"]) self.setWindowModality(Qt.WindowModality.ApplicationModal) self.setMinimumSize(240, 400) self.root_layout = QVBoxLayout(self) @@ -65,12 +65,8 @@ def __init__(self, library: "Library"): self.mode_combobox.setEditable(False) self.mode_combobox.addItem("") self.mode_combobox.addItem("") - Translations.translate_with_setter( - lambda text: self.mode_combobox.setItemText(0, text), "ignore_list.mode.include" - ) - Translations.translate_with_setter( - lambda text: self.mode_combobox.setItemText(1, text), "ignore_list.mode.exclude" - ) + self.mode_combobox.setItemText(0, Translations["ignore_list.mode.include"]) + self.mode_combobox.setItemText(1, Translations["ignore_list.mode.exclude"]) is_exclude_list = int(bool(self.lib.prefs(LibraryPrefs.IS_EXCLUDE_LIST))) diff --git a/tagstudio/src/qt/modals/fix_dupes.py b/tagstudio/src/qt/modals/fix_dupes.py index 78570e7c8..db997e313 100644 --- a/tagstudio/src/qt/modals/fix_dupes.py +++ b/tagstudio/src/qt/modals/fix_dupes.py @@ -25,7 +25,7 @@ def __init__(self, library: "Library", driver: "QtDriver"): self.driver = driver self.count = -1 self.filename = "" - Translations.translate_with_setter(self.setWindowTitle, "file.duplicates.fix") + self.setWindowTitle(Translations["file.duplicates.fix"]) self.setWindowModality(Qt.WindowModality.ApplicationModal) self.setMinimumSize(400, 300) self.root_layout = QVBoxLayout(self) diff --git a/tagstudio/src/qt/modals/fix_unlinked.py b/tagstudio/src/qt/modals/fix_unlinked.py index a8270d45b..4b3dd9d29 100644 --- a/tagstudio/src/qt/modals/fix_unlinked.py +++ b/tagstudio/src/qt/modals/fix_unlinked.py @@ -31,7 +31,7 @@ def __init__(self, library: "Library", driver: "QtDriver"): self.missing_count = -1 self.dupe_count = -1 - Translations.translate_with_setter(self.setWindowTitle, "entries.unlinked.title") + self.setWindowTitle(Translations["entries.unlinked.title"]) self.setWindowModality(Qt.WindowModality.ApplicationModal) self.setMinimumSize(400, 300) self.root_layout = QVBoxLayout(self) @@ -110,8 +110,8 @@ def refresh_missing_files(self): minimum=0, maximum=self.lib.entries_count, ) - Translations.translate_with_setter(pw.setWindowTitle, "library.scan_library.title") - Translations.translate_with_setter(pw.update_label, "entries.unlinked.scanning") + pw.setWindowTitle(Translations["library.scan_library.title"]) + pw.update_label(Translations["entries.unlinked.scanning"]) pw.from_iterable_function( self.tracker.refresh_missing_files, diff --git a/tagstudio/src/qt/modals/folders_to_tags.py b/tagstudio/src/qt/modals/folders_to_tags.py index 7c99fcc26..fc045158e 100644 --- a/tagstudio/src/qt/modals/folders_to_tags.py +++ b/tagstudio/src/qt/modals/folders_to_tags.py @@ -166,7 +166,7 @@ def __init__(self, library: "Library", driver: "QtDriver"): self.count = -1 self.filename = "" - Translations.translate_with_setter(self.setWindowTitle, "folders_to_tags.title") + self.setWindowTitle(Translations["folders_to_tags.title"]) self.setWindowModality(Qt.WindowModality.ApplicationModal) self.setMinimumSize(640, 640) self.root_layout = QVBoxLayout(self) diff --git a/tagstudio/src/qt/modals/merge_dupe_entries.py b/tagstudio/src/qt/modals/merge_dupe_entries.py index 35bdf7c15..cd9baed83 100644 --- a/tagstudio/src/qt/modals/merge_dupe_entries.py +++ b/tagstudio/src/qt/modals/merge_dupe_entries.py @@ -30,7 +30,7 @@ def merge_entries(self): minimum=0, maximum=self.tracker.groups_count, ) - Translations.translate_with_setter(pw.setWindowTitle, "entries.duplicate.merge.label") - Translations.translate_with_setter(pw.update_label, "entries.duplicate.merge.label") + pw.setWindowTitle(Translations["entries.duplicate.merge.label"]) + pw.update_label(Translations["entries.duplicate.merge.label"]) pw.from_iterable_function(self.tracker.merge_dupe_entries, None, self.done.emit) diff --git a/tagstudio/src/qt/modals/mirror_entities.py b/tagstudio/src/qt/modals/mirror_entities.py index 2e798a8af..2096af57d 100644 --- a/tagstudio/src/qt/modals/mirror_entities.py +++ b/tagstudio/src/qt/modals/mirror_entities.py @@ -24,7 +24,7 @@ class MirrorEntriesModal(QWidget): def __init__(self, driver: "QtDriver", tracker: DupeRegistry): super().__init__() self.driver = driver - Translations.translate_with_setter(self.setWindowTitle, "entries.mirror.window_title") + self.setWindowTitle(Translations["entries.mirror.window_title"]) self.setWindowModality(Qt.WindowModality.ApplicationModal) self.setMinimumSize(500, 400) self.root_layout = QVBoxLayout(self) @@ -81,7 +81,7 @@ def displayed_text(x): minimum=0, maximum=self.tracker.groups_count, ) - Translations.translate_with_setter(pw.setWindowTitle, "entries.mirror.title") + pw.setWindowTitle(Translations["entries.mirror.title"]) pw.from_iterable_function( self.mirror_entries_runnable, diff --git a/tagstudio/src/qt/modals/relink_unlinked.py b/tagstudio/src/qt/modals/relink_unlinked.py index 5dbee80ad..51b88dee4 100644 --- a/tagstudio/src/qt/modals/relink_unlinked.py +++ b/tagstudio/src/qt/modals/relink_unlinked.py @@ -30,6 +30,6 @@ def displayed_text(x): minimum=0, maximum=self.tracker.missing_file_entries_count, ) - Translations.translate_with_setter(pw.setWindowTitle, "entries.unlinked.relink.title") + pw.setWindowTitle(Translations["entries.unlinked.relink.title"]) pw.from_iterable_function(self.tracker.fix_unlinked_entries, displayed_text, self.done.emit) diff --git a/tagstudio/src/qt/modals/tag_color_manager.py b/tagstudio/src/qt/modals/tag_color_manager.py index 73a23802e..ecd6f6252 100644 --- a/tagstudio/src/qt/modals/tag_color_manager.py +++ b/tagstudio/src/qt/modals/tag_color_manager.py @@ -44,7 +44,7 @@ def __init__( super().__init__() self.driver = driver self.lib = driver.lib - Translations.translate_with_setter(self.setWindowTitle, "color_manager.title") + self.setWindowTitle(Translations["color_manager.title"]) self.setWindowModality(Qt.WindowModality.ApplicationModal) self.setMinimumSize(800, 600) self.is_initialized = False @@ -192,9 +192,7 @@ def create_namespace(self): def delete_namespace_dialog(self, prompt: str, callback: Callable) -> None: message_box = QMessageBox() message_box.setText(prompt) - Translations.translate_with_setter( - message_box.setWindowTitle, "color.namespace.delete.title" - ) + message_box.setWindowTitle(Translations["color.namespace.delete.title"]) message_box.setIcon(QMessageBox.Icon.Warning) cancel_button = message_box.addButton( Translations["generic.cancel_alt"], QMessageBox.ButtonRole.RejectRole diff --git a/tagstudio/src/qt/modals/tag_database.py b/tagstudio/src/qt/modals/tag_database.py index 3e287a8f6..dba82cfa5 100644 --- a/tagstudio/src/qt/modals/tag_database.py +++ b/tagstudio/src/qt/modals/tag_database.py @@ -34,8 +34,8 @@ def build_tag(self, name: str): panel, has_save=True, ) - Translations.translate_with_setter(self.modal.setTitle, "tag.new") - Translations.translate_with_setter(self.modal.setWindowTitle, "tag.new") + self.modal.setTitle(Translations["tag.new"]) + self.modal.setWindowTitle(Translations["tag.new"]) if name.strip(): panel.name_field.setText(name) diff --git a/tagstudio/src/qt/modals/tag_search.py b/tagstudio/src/qt/modals/tag_search.py index 1bfbe28f4..fa115b398 100644 --- a/tagstudio/src/qt/modals/tag_search.py +++ b/tagstudio/src/qt/modals/tag_search.py @@ -94,7 +94,7 @@ def __init__( self.search_field = QLineEdit() self.search_field.setObjectName("searchField") self.search_field.setMinimumSize(QSize(0, 32)) - Translations.translate_with_setter(self.search_field.setPlaceholderText, "home.search_tags") + self.search_field.setPlaceholderText(Translations["home.search_tags"]) self.search_field.textEdited.connect(lambda text: self.update_tags(text)) self.search_field.returnPressed.connect(lambda: self.on_return(self.search_field.text())) @@ -177,8 +177,8 @@ def on_tag_modal_saved(): self.build_tag_modal: BuildTagPanel = build_tag.BuildTagPanel(self.lib) self.add_tag_modal: PanelModal = PanelModal(self.build_tag_modal, has_save=True) - Translations.translate_with_setter(self.add_tag_modal.setTitle, "tag.new") - Translations.translate_with_setter(self.add_tag_modal.setWindowTitle, "tag.add") + self.add_tag_modal.setTitle(Translations["tag.new"]) + self.add_tag_modal.setWindowTitle(Translations["tag.add"]) self.build_tag_modal.name_field.setText(name) self.add_tag_modal.saved.connect(on_tag_modal_saved) @@ -364,7 +364,7 @@ def callback(btp: build_tag.BuildTagPanel): done_callback=(self.update_tags(self.search_field.text())), has_save=True, ) - Translations.translate_with_setter(self.edit_modal.setWindowTitle, "tag.edit") + self.edit_modal.setWindowTitle(Translations["tag.edit"]) self.edit_modal.saved.connect(lambda: callback(build_tag_panel)) self.edit_modal.show() diff --git a/tagstudio/src/qt/translations.py b/tagstudio/src/qt/translations.py index 1ad4684a5..6b4eb33fb 100644 --- a/tagstudio/src/qt/translations.py +++ b/tagstudio/src/qt/translations.py @@ -1,5 +1,4 @@ from pathlib import Path -from typing import Callable import structlog import ujson @@ -28,14 +27,6 @@ def change_language(self, lang: str): self._lang = lang self._strings = self.__get_translation_dict(lang) - def translate_with_setter(self, setter: Callable[[str], None], key: str, **kwargs): - """Calls `setter` everytime the language changes and passes the translated string for `key`. - - Also formats the translation with the given keyword arguments. - """ - # TODO replace calls to this method with direct calls to setter - setter(Translations[key].format(**kwargs)) - def __getitem__(self, key: str) -> str: return self._strings.get(key) or self._default_strings.get(key) or f"[{key}]" diff --git a/tagstudio/src/qt/ts_qt.py b/tagstudio/src/qt/ts_qt.py index 7e59180c0..e3c791cc4 100644 --- a/tagstudio/src/qt/ts_qt.py +++ b/tagstudio/src/qt/ts_qt.py @@ -311,10 +311,8 @@ def start(self) -> None: done_callback=lambda: self.preview_panel.update_widgets(update_preview=False), has_save=False, ) - Translations.translate_with_setter(self.tag_manager_panel.setTitle, "tag_manager.title") - Translations.translate_with_setter( - self.tag_manager_panel.setWindowTitle, "tag_manager.title" - ) + self.tag_manager_panel.setTitle(Translations["tag_manager.title"]) + self.tag_manager_panel.setWindowTitle(Translations["tag_manager.title"]) # Initialize the Color Group Manager panel self.color_manager_panel = TagColorManager(self) @@ -454,7 +452,7 @@ def start(self) -> None: self.copy_buffer: dict = {"fields": [], "tags": []} - self.copy_fields_action = QAction("edit.copy_fields", menu_bar) + self.copy_fields_action = QAction(Translations["edit.copy_fields"], menu_bar) self.copy_fields_action.triggered.connect(self.copy_fields_action_callback) self.copy_fields_action.setShortcut( QtCore.QKeyCombination( @@ -737,12 +735,8 @@ def _filter_items(): sort_dir_dropdown: QComboBox = self.main_window.sorting_direction_combobox sort_dir_dropdown.addItem("Ascending", userData=True) sort_dir_dropdown.addItem("Descending", userData=False) - Translations.translate_with_setter( - lambda text: sort_dir_dropdown.setItemText(0, text), "sorting.direction.ascending" - ) - Translations.translate_with_setter( - lambda text: sort_dir_dropdown.setItemText(1, text), "sorting.direction.descending" - ) + sort_dir_dropdown.setItemText(0, Translations["sorting.direction.ascending"]) + sort_dir_dropdown.setItemText(1, Translations["sorting.direction.descending"]) sort_dir_dropdown.setCurrentIndex(0) # Default: Ascending sort_dir_dropdown.currentIndexChanged.connect(self.sorting_direction_callback) @@ -786,10 +780,8 @@ def init_file_extension_manager(self): panel, has_save=True, ) - Translations.translate_with_setter(self.file_extension_panel.setTitle, "ignore_list.title") - Translations.translate_with_setter( - self.file_extension_panel.setWindowTitle, "ignore_list.title" - ) + self.file_extension_panel.setTitle(Translations["ignore_list.title"]) + self.file_extension_panel.setWindowTitle(Translations["ignore_list.title"]) self.file_extension_panel.saved.connect(lambda: (panel.save(), self.filter_items())) self.manage_file_ext_action.triggered.connect(self.file_extension_panel.show) @@ -906,8 +898,8 @@ def add_tag_action_callback(self): panel, has_save=True, ) - Translations.translate_with_setter(self.modal.setTitle, "tag.new") - Translations.translate_with_setter(self.modal.setWindowTitle, "tag.add") + self.modal.setTitle(Translations["tag.new"]) + self.modal.setWindowTitle(Translations["tag.add"]) self.modal.saved.connect( lambda: ( @@ -1090,8 +1082,8 @@ def add_new_files_callback(self): minimum=0, maximum=0, ) - Translations.translate_with_setter(pw.setWindowTitle, "library.refresh.title") - Translations.translate_with_setter(pw.update_label, "library.refresh.scanning_preparing") + pw.setWindowTitle(Translations["library.refresh.title"]) + pw.update_label(Translations["library.refresh.scanning_preparing"]) pw.show() @@ -1134,9 +1126,9 @@ def add_new_files_runnable(self, tracker: RefreshDirTracker): minimum=0, maximum=0, ) - Translations.translate_with_setter(pw.setWindowTitle, "entries.running.dialog.title") - Translations.translate_with_setter( - pw.update_label, "entries.running.dialog.new_entries", total=f"{files_count:n}" + pw.setWindowTitle(Translations["entries.running.dialog.title"]) + pw.update_label( + Translations["entries.running.dialog.new_entries"].format(total=f"{files_count:n}") ) pw.show() @@ -1817,8 +1809,8 @@ def open_settings_modal(self): done_callback=lambda: self.update_language_settings(settings_panel.get_language()), has_save=False, ) - Translations.translate_with_setter(modal.setTitle, "settings.title") - Translations.translate_with_setter(modal.setWindowTitle, "settings.title") + modal.setTitle(Translations["settings.title"]) + modal.setWindowTitle(Translations["settings.title"]) modal.show() def update_language_settings(self, language: str): @@ -1871,11 +1863,10 @@ def init_library(self, path: Path, open_status: LibraryStatus): self.add_new_files_callback() self.update_libs_list(path) - Translations.translate_with_setter( - self.main_window.setWindowTitle, - "app.title", - base_title=self.base_title, - library_dir=self.lib.library_dir, + self.main_window.setWindowTitle( + Translations["app.title"].format( + base_title=self.base_title, library_dir=self.lib.library_dir + ) ) self.main_window.setAcceptDrops(True) diff --git a/tagstudio/src/qt/widgets/preview_panel.py b/tagstudio/src/qt/widgets/preview_panel.py index 990c57389..252c45563 100644 --- a/tagstudio/src/qt/widgets/preview_panel.py +++ b/tagstudio/src/qt/widgets/preview_panel.py @@ -75,7 +75,7 @@ def __init__(self, library: Library, driver: "QtDriver"): self.tag_search_panel = TagSearchPanel(self.driver.lib, is_tag_chooser=True) self.add_tag_modal = PanelModal(self.tag_search_panel, Translations["tag.add.plural"]) - Translations.translate_with_setter(self.add_tag_modal.setWindowTitle, "tag.add.plural") + self.add_tag_modal.setWindowTitle(Translations["tag.add.plural"]) self.add_field_modal = AddFieldModal(self.lib)