fix: resouce leak in translate_with_setter by deleting the offending code (#817)

* feat: implement first class for translated widget

* feat: add further translated widget types

* refactor: replace usages of translate_qobject with appropriate classes

* refactor: remove wrapper classes

* refactor: remove unnecessary used of Translations.formatted

* refactor: remove further unnecessary format calls

* refactor: replace calls for Translations.formatted with calls to str.format and remove some unused code

* refactor: remove TranslatedString class

* refactor: replace translate_with_setter with direct calls to the setter
This commit is contained in:
Jann Stute
2025-03-03 20:13:49 +01:00
committed by GitHub
parent 152c2b20ba
commit 2a787592b6
37 changed files with 287 additions and 550 deletions

View File

@@ -368,13 +368,9 @@ class Library:
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["status.library_version_mismatch"]
found_text = Translations["status.library_version_found"]
expected_text = Translations["status.library_version_expected"]
return LibraryStatus(
success=False,
message=(

View File

@@ -74,7 +74,7 @@ class Ui_MainWindow(QMainWindow):
# 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 @@ class Ui_MainWindow(QMainWindow):
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))
@@ -152,8 +152,7 @@ class Ui_MainWindow(QMainWindow):
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 = QPushButton(Translations["home.search"], self.centralwidget)
self.searchButton.setObjectName(u"searchButton")
self.searchButton.setMinimumSize(QSize(0, 32))

View File

@@ -6,13 +6,7 @@
from PIL import ImageQt
from PySide6.QtCore import Qt
from PySide6.QtGui import QPixmap
from PySide6.QtWidgets import (
QHBoxLayout,
QLabel,
QPushButton,
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
@@ -22,7 +16,7 @@ from src.qt.translations import Translations
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()
@@ -42,10 +36,6 @@ class AboutModal(QWidget):
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 = '<span style="color:red">Missing</span>'
if ff_version["ffmpeg"] is not None:
@@ -53,23 +43,25 @@ class AboutModal(QWidget):
ffprobe = '<span style="color:red">Missing</span>'
if ff_version["ffprobe"] is not None:
ffprobe = '<span style="color:green">Found</span> (' + ff_version["ffprobe"] + ")"
Translations.translate_qobject(
self.content_widget,
"about.content",
version=VERSION,
branch=VERSION_BRANCH,
config_path=config_path,
ffmpeg=ffmpeg,
ffprobe=ffprobe,
self.content_widget = QLabel(
Translations["about.content"].format(
version=VERSION,
branch=VERSION_BRANCH,
config_path=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 = QPushButton(Translations["generic.close"])
self.close_button.clicked.connect(lambda: self.close())
self.close_button.setMaximumWidth(80)

View File

@@ -31,17 +31,16 @@ class AddFieldModal(QWidget):
# [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)
self.root_layout.setContentsMargins(6, 6, 6, 6)
self.title_widget = QLabel()
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;")
Translations.translate_qobject(self.title_widget, "library.field.add")
self.title_widget.setAlignment(Qt.AlignmentFlag.AlignCenter)
self.list_widget = QListWidget()
@@ -51,13 +50,11 @@ class AddFieldModal(QWidget):
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 = QPushButton(Translations["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 = QPushButton(Translations["generic.add"])
self.save_button.setDefault(True)
self.save_button.clicked.connect(self.hide)
self.save_button.clicked.connect(

View File

@@ -72,30 +72,23 @@ class BuildColorPanel(PanelWidget):
self.preview_layout.addWidget(self.preview_button)
# Name -----------------------------------------------------------------
self.name_title = QLabel()
Translations.translate_qobject(self.name_title, "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)
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 -----------------------------------------------------------------
self.slug_title = QLabel()
Translations.translate_qobject(self.slug_title, "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)
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 --------------------------------------------------------------
self.primary_title = QLabel()
Translations.translate_qobject(self.primary_title, "color.primary")
self.primary_title = QLabel(Translations["color.primary"])
self.primary_button = QPushButton()
self.primary_button.setMinimumSize(44, 22)
self.primary_button.setMaximumHeight(22)
@@ -108,8 +101,7 @@ class BuildColorPanel(PanelWidget):
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 = QLabel(Translations["color.secondary"])
self.secondary_button = QPushButton()
self.secondary_button.setMinimumSize(44, 22)
self.secondary_button.setMaximumHeight(22)
@@ -117,8 +109,7 @@ class BuildColorPanel(PanelWidget):
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 = 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)
@@ -143,8 +134,7 @@ class BuildColorPanel(PanelWidget):
)
)
self.border_layout.addWidget(self.border_checkbox)
self.border_label = QLabel()
Translations.translate_qobject(self.border_label, "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))

View File

@@ -48,15 +48,12 @@ class BuildNamespacePanel(PanelWidget):
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 = QLabel(Translations["library_object.name"])
self.name_layout.addWidget(self.name_title)
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 -----------------------------------------------------------------
@@ -66,26 +63,19 @@ class BuildNamespacePanel(PanelWidget):
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 = QLabel(Translations["library_object.slug"])
self.slug_layout.addWidget(self.slug_title)
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 ----------------------------------------------------------
self.desc_label = QLabel()
self.desc_label = QLabel(Translations["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 = QLabel(Translations["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)

View File

@@ -86,15 +86,12 @@ class BuildTagPanel(PanelWidget):
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 = QLabel(Translations["tag.name"])
self.name_layout.addWidget(self.name_title)
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 ------------------------------------------------------------
@@ -104,8 +101,7 @@ class BuildTagPanel(PanelWidget):
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 = QLabel(Translations["tag.shorthand"])
self.shorthand_layout.addWidget(self.shorthand_title)
self.shorthand_field = QLineEdit()
self.shorthand_layout.addWidget(self.shorthand_field)
@@ -117,8 +113,7 @@ class BuildTagPanel(PanelWidget):
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 = QLabel(Translations["tag.aliases"])
self.aliases_layout.addWidget(self.aliases_title)
self.aliases_table = QTableWidget(0, 2)
@@ -144,8 +139,7 @@ class BuildTagPanel(PanelWidget):
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 = QLabel(Translations["tag.parent_tags"])
self.parent_tags_layout.addWidget(self.parent_tags_title)
self.scroll_contents = QWidget()
@@ -173,8 +167,8 @@ class BuildTagPanel(PanelWidget):
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 ----------------------------------------------------------------
@@ -184,8 +178,7 @@ class BuildTagPanel(PanelWidget):
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 = QLabel(Translations["tag.color"])
self.color_layout.addWidget(self.color_title)
self.color_button: TagColorPreview
try:
@@ -195,7 +188,7 @@ class BuildTagPanel(PanelWidget):
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["tag.choose_color"]
self.choose_color_modal = PanelModal(
self.tag_color_selection,
chose_tag_color_title,
@@ -214,8 +207,7 @@ class BuildTagPanel(PanelWidget):
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 = QLabel(Translations["tag.is_category"])
self.cat_checkbox = QCheckBox()
self.cat_checkbox.setFixedSize(22, 22)
@@ -404,7 +396,7 @@ class BuildTagPanel(PanelWidget):
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["tag.disambiguation.tooltip"])
disam_button.setStyleSheet(
f"QRadioButton{{"
f"background: rgba{primary_color.toTuple()};"

View File

@@ -7,14 +7,7 @@ from typing import TYPE_CHECKING, override
from PySide6 import QtCore, QtGui
from PySide6.QtCore import Qt, QThreadPool, Signal
from PySide6.QtGui import QStandardItem, QStandardItemModel
from PySide6.QtWidgets import (
QHBoxLayout,
QLabel,
QListView,
QPushButton,
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 Translations
@@ -32,20 +25,19 @@ class DeleteUnlinkedEntriesModal(QWidget):
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)
self.root_layout.setContentsMargins(6, 6, 6, 6)
self.desc_widget = QLabel()
self.desc_widget = QLabel(
Translations["entries.unlinked.delete.confirm"].format(
count=self.tracker.missing_file_entries_count,
)
)
self.desc_widget.setObjectName("descriptionLabel")
self.desc_widget.setWordWrap(True)
Translations.translate_qobject(
self.desc_widget,
"entries.unlinked.delete.confirm",
count=self.tracker.missing_file_entries_count,
)
self.desc_widget.setAlignment(Qt.AlignmentFlag.AlignCenter)
self.list_view = QListView()
@@ -57,14 +49,12 @@ class DeleteUnlinkedEntriesModal(QWidget):
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 = 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 = QPushButton()
Translations.translate_qobject(self.delete_button, "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)
@@ -75,8 +65,8 @@ class DeleteUnlinkedEntriesModal(QWidget):
def refresh_list(self):
self.desc_widget.setText(
Translations.translate_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
)
)
@@ -87,20 +77,13 @@ class DeleteUnlinkedEntriesModal(QWidget):
self.model.appendRow(item)
def delete_entries(self):
def displayed_text(x):
return Translations.translate_formatted(
"entries.unlinked.delete.deleting_count",
idx=x,
count=self.tracker.missing_file_entries_count,
)
pw = ProgressWidget(
cancel_button_text=None,
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)

View File

@@ -11,14 +11,7 @@ import structlog
from PySide6 import QtCore, QtGui
from PySide6.QtCore import Qt, QUrl
from PySide6.QtGui import QStandardItem, QStandardItemModel
from PySide6.QtWidgets import (
QHBoxLayout,
QLabel,
QListView,
QPushButton,
QVBoxLayout,
QWidget,
)
from PySide6.QtWidgets import QHBoxLayout, QLabel, QListView, QPushButton, QVBoxLayout, QWidget
from src.qt.translations import Translations
from src.qt.widgets.progress import ProgressWidget
@@ -44,7 +37,7 @@ class DropImportModal(QWidget):
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)
@@ -67,26 +60,22 @@ class DropImportModal(QWidget):
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 = 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 = QPushButton()
Translations.translate_qobject(self.overwrite_button, "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 = QPushButton()
Translations.translate_qobject(self.rename_button, "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 = QPushButton()
Translations.translate_qobject(self.cancel_button, "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)
@@ -142,8 +131,8 @@ class DropImportModal(QWidget):
self.desc_widget.setText(
Translations["drop_import.duplicates_choice.singular"]
if len(self.duplicate_files) == 1
else Translations.translate_formatted(
"drop_import.duplicates_choice.plural", count=len(self.duplicate_files)
else Translations["drop_import.duplicates_choice.plural"].format(
count=len(self.duplicate_files)
)
)
@@ -165,10 +154,11 @@ class DropImportModal(QWidget):
return
def displayed_text(x):
return Translations.translate_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 "",
)
@@ -178,8 +168,8 @@ class DropImportModal(QWidget):
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,

View File

@@ -36,7 +36,7 @@ class FileExtensionModal(PanelWidget):
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)
@@ -50,8 +50,7 @@ class FileExtensionModal(PanelWidget):
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 = QPushButton(Translations["ignore_list.add_extension"])
self.add_button.clicked.connect(self.add_item)
self.add_button.setDefault(True)
self.add_button.setMinimumWidth(100)
@@ -61,18 +60,13 @@ class FileExtensionModal(PanelWidget):
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 = QLabel(Translations["ignore_list.mode.label"])
self.mode_combobox = QComboBox()
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)))

View File

@@ -7,14 +7,7 @@ from typing import TYPE_CHECKING, override
from PySide6 import QtCore, QtGui
from PySide6.QtCore import Qt
from PySide6.QtWidgets import (
QFileDialog,
QHBoxLayout,
QLabel,
QPushButton,
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
@@ -32,7 +25,7 @@ class FixDupeFilesModal(QWidget):
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)
@@ -40,11 +33,10 @@ class FixDupeFilesModal(QWidget):
self.tracker = DupeRegistry(library=self.lib)
self.desc_widget = QLabel()
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;")
Translations.translate_qobject(self.desc_widget, "file.duplicates.description")
self.desc_widget.setAlignment(Qt.AlignmentFlag.AlignCenter)
self.dupe_count = QLabel()
@@ -52,35 +44,29 @@ class FixDupeFilesModal(QWidget):
self.dupe_count.setStyleSheet("font-weight:bold;" "font-size:14px;" "")
self.dupe_count.setAlignment(Qt.AlignmentFlag.AlignCenter)
self.file_label = QLabel()
self.file_label = QLabel(Translations["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 = 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 = QPushButton()
Translations.translate_qobject(self.mirror_button, "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 = QLabel()
self.mirror_desc = QLabel(Translations["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 = QLabel(Translations["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 = QPushButton(Translations["generic.done_alt"])
self.done_button.setDefault(True)
self.done_button.clicked.connect(self.hide)
self.button_layout.addWidget(self.done_button)
@@ -128,14 +114,10 @@ class FixDupeFilesModal(QWidget):
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["file.duplicates.matches"].format(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["file.duplicates.matches"].format(count=count))
@override
def keyPressEvent(self, event: QtGui.QKeyEvent) -> None: # noqa N802

View File

@@ -31,17 +31,16 @@ class FixUnlinkedEntriesModal(QWidget):
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)
self.root_layout.setContentsMargins(6, 6, 6, 6)
self.unlinked_desc_widget = QLabel()
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;")
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 @@ class FixUnlinkedEntriesModal(QWidget):
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 = 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 = QPushButton()
Translations.translate_qobject(self.search_button, "entries.unlinked.search_and_relink")
self.search_button = QPushButton(Translations["entries.unlinked.search_and_relink"])
self.relink_class.done.connect(
# refresh the grid
lambda: (
@@ -71,11 +68,10 @@ class FixUnlinkedEntriesModal(QWidget):
)
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 = QPushButton(Translations["entries.unlinked.relink.manual"])
self.manual_button.setHidden(True)
self.delete_button = QPushButton()
self.delete_button = QPushButton(Translations["entries.unlinked.delete_alt"])
self.delete_modal = DeleteUnlinkedEntriesModal(self.driver, self.tracker)
self.delete_modal.done.connect(
lambda: (
@@ -84,7 +80,6 @@ class FixUnlinkedEntriesModal(QWidget):
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 @@ class FixUnlinkedEntriesModal(QWidget):
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 = QPushButton(Translations["generic.done_alt"])
self.done_button.setDefault(True)
self.done_button.clicked.connect(self.hide)
self.button_layout.addWidget(self.done_button)
@@ -116,8 +110,8 @@ class FixUnlinkedEntriesModal(QWidget):
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,
@@ -141,9 +135,7 @@ class FixUnlinkedEntriesModal(QWidget):
self.search_button.setDisabled(self.missing_count == 0)
self.delete_button.setDisabled(self.missing_count == 0)
self.missing_count_label.setText(
Translations.translate_formatted(
"entries.unlinked.missing_count.some", count=self.missing_count
)
Translations["entries.unlinked.missing_count.some"].format(count=self.missing_count)
)
@override

View File

@@ -166,17 +166,16 @@ class FoldersToTagsModal(QWidget):
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)
self.root_layout.setContentsMargins(6, 6, 6, 6)
self.title_widget = QLabel()
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")
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 @@ class FoldersToTagsModal(QWidget):
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 = QPushButton(Translations["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 = 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)
@@ -213,8 +210,7 @@ class FoldersToTagsModal(QWidget):
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 = QPushButton(Translations["generic.apply_alt"])
self.apply_button.setMinimumWidth(100)
self.apply_button.clicked.connect(self.on_apply)

View File

@@ -30,7 +30,7 @@ class MergeDuplicateEntries(QObject):
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)

View File

@@ -8,14 +8,7 @@ from time import sleep
from PySide6.QtCore import Qt, Signal
from PySide6.QtGui import QStandardItem, QStandardItemModel
from PySide6.QtWidgets import (
QHBoxLayout,
QLabel,
QListView,
QPushButton,
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 Translations
from src.qt.widgets.progress import ProgressWidget
@@ -31,19 +24,18 @@ 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)
self.root_layout.setContentsMargins(6, 6, 6, 6)
self.tracker = tracker
self.desc_widget = QLabel()
self.desc_widget = QLabel(
Translations["entries.mirror.confirmation"].format(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 +47,12 @@ class MirrorEntriesModal(QWidget):
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 = 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 = QPushButton()
Translations.translate_qobject(self.mirror_button, "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)
@@ -73,9 +63,7 @@ class MirrorEntriesModal(QWidget):
def refresh_list(self):
self.desc_widget.setText(
Translations.translate_formatted(
"entries.mirror.confirmation", count=self.tracker.groups_count
)
Translations["entries.mirror.confirmation"].format(count=self.tracker.groups_count)
)
self.model.clear()
@@ -84,8 +72,8 @@ class MirrorEntriesModal(QWidget):
def mirror_entries(self):
def displayed_text(x):
return Translations.translate_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(
@@ -93,7 +81,7 @@ class MirrorEntriesModal(QWidget):
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,

View File

@@ -18,8 +18,7 @@ class RelinkUnlinkedEntries(QObject):
def repair_entries(self):
def displayed_text(x):
return Translations.translate_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,
@@ -31,6 +30,6 @@ class RelinkUnlinkedEntries(QObject):
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)

View File

@@ -22,13 +22,11 @@ class SettingsPanel(PanelWidget):
self.form_layout = QFormLayout(self.form_container)
self.form_layout.setContentsMargins(0, 0, 0, 0)
self.restart_label = QLabel()
self.restart_label = QLabel(Translations["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 = QLabel(Translations["settings.language"])
self.languages = {
# "Cantonese (Traditional)": "yue_Hant", # Empty
"Chinese (Traditional)": "zh_Hant",

View File

@@ -44,7 +44,7 @@ class TagColorManager(QWidget):
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
@@ -91,8 +91,7 @@ class TagColorManager(QWidget):
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 = QPushButton(Translations["namespace.new.button"])
self.new_namespace_button.clicked.connect(self.create_namespace)
self.button_layout.addWidget(self.new_namespace_button)
@@ -102,8 +101,7 @@ class TagColorManager(QWidget):
self.button_layout.addStretch(1)
self.done_button = QPushButton()
Translations.translate_qobject(self.done_button, "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)
@@ -156,8 +154,7 @@ class TagColorManager(QWidget):
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 = 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)
@@ -195,9 +192,7 @@ class TagColorManager(QWidget):
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

View File

@@ -139,7 +139,7 @@ class TagColorSelection(PanelWidget):
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["color.title.no_color"]
self.scroll_layout.addWidget(QLabel(f"<h4>{no_color_str}</h4>"))
color_box_widget = QWidget()
color_group_layout = FlowLayout()

View File

@@ -3,10 +3,7 @@
# Created for TagStudio: https://github.com/CyanVoxel/TagStudio
import structlog
from PySide6.QtWidgets import (
QMessageBox,
QPushButton,
)
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
@@ -26,8 +23,7 @@ class TagDatabasePanel(TagSearchPanel):
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 = 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)
@@ -38,8 +34,8 @@ class TagDatabasePanel(TagSearchPanel):
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)
@@ -61,13 +57,14 @@ class TagDatabasePanel(TagSearchPanel):
if tag.id in range(RESERVED_TAG_START, RESERVED_TAG_END):
return
message_box = QMessageBox()
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 = QMessageBox(
QMessageBox.Question, # type: ignore
Translations["tag.remove"],
Translations["tag.confirm_delete"].format(
tag_name=self.lib.tag_display_name(tag.id),
),
QMessageBox.Ok | QMessageBox.Cancel, # type: ignore
)
message_box.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel) # type: ignore
message_box.setIcon(QMessageBox.Question) # type: ignore
result = message_box.exec()

View File

@@ -77,8 +77,7 @@ class TagSearchPanel(PanelWidget):
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 = QLabel(Translations["tag.view_limit"])
self.limit_layout.addWidget(self.limit_title)
self.limit_combobox = QComboBox()
@@ -95,7 +94,7 @@ class TagSearchPanel(PanelWidget):
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()))
@@ -119,9 +118,9 @@ class TagSearchPanel(PanelWidget):
"""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 = QPushButton(Translations[key].format(**format_args), self)
create_button.setFlat(True)
create_button.setMinimumSize(22, 22)
@@ -178,8 +177,8 @@ class TagSearchPanel(PanelWidget):
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)
@@ -245,11 +244,10 @@ class TagSearchPanel(PanelWidget):
# 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
@@ -366,7 +364,7 @@ class TagSearchPanel(PanelWidget):
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()

View File

@@ -1,47 +1,20 @@
from pathlib import Path
from typing import Callable
import structlog
import ujson
from PySide6.QtCore import QObject, Signal
from PySide6.QtGui import QAction
from PySide6.QtWidgets import QLabel, QMenu, QMessageBox, QPushButton
from .helpers.qbutton_wrapper import QPushButtonWrapper
logger = structlog.get_logger(__name__)
DEFAULT_TRANSLATION = "en"
class TranslatedString(QObject):
changed = Signal(str)
__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):
if self.__value != value:
self.__value = value
self.changed.emit(self.__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(
@@ -52,46 +25,10 @@ class Translator:
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)
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`.
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.translate_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 translate_formatted(self, key: str, **kwargs) -> str:
return self.__format(self[key], **kwargs)
self._strings = self.__get_translation_dict(lang)
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()

View File

@@ -311,10 +311,8 @@ class QtDriver(DriverMixin, QObject):
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)
@@ -324,8 +322,8 @@ class QtDriver(DriverMixin, QObject):
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["tag.add.plural"],
window_title=Translations["tag.add.plural"],
)
self.tag_search_panel.tag_chosen.connect(
lambda t: (
@@ -338,22 +336,15 @@ class QtDriver(DriverMixin, QObject):
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 = 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 = QAction(menu_bar)
Translations.translate_qobject(open_library_action, "menu.file.open_create_library")
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(
@@ -364,15 +355,13 @@ class QtDriver(DriverMixin, QObject):
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 = 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 = QAction(menu_bar)
Translations.translate_qobject(self.save_library_backup_action, "menu.file.save_backup")
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)
)
@@ -390,13 +379,11 @@ class QtDriver(DriverMixin, QObject):
file_menu.addAction(self.save_library_backup_action)
file_menu.addSeparator()
settings_action = QAction(self)
Translations.translate_qobject(settings_action, "menu.settings")
settings_action = QAction(Translations["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 = 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))
@@ -408,8 +395,7 @@ class QtDriver(DriverMixin, QObject):
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 = 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)
)
@@ -424,16 +410,14 @@ class QtDriver(DriverMixin, QObject):
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 = 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 = QAction(menu_bar)
Translations.translate_qobject(self.new_tag_action, "menu.edit.new_tag")
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(
@@ -447,8 +431,7 @@ class QtDriver(DriverMixin, QObject):
edit_menu.addSeparator()
self.select_all_action = QAction(menu_bar)
Translations.translate_qobject(self.select_all_action, "select.all")
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(
@@ -460,8 +443,7 @@ class QtDriver(DriverMixin, QObject):
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 = 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")
@@ -470,8 +452,7 @@ class QtDriver(DriverMixin, QObject):
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(Translations["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 +464,7 @@ class QtDriver(DriverMixin, QObject):
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 = 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(
@@ -496,9 +476,8 @@ class QtDriver(DriverMixin, QObject):
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 = 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(
@@ -516,9 +495,9 @@ class QtDriver(DriverMixin, QObject):
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 = QAction(
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))
self.delete_file_action.setShortcut(QtCore.Qt.Key.Key_Delete)
@@ -527,15 +506,13 @@ class QtDriver(DriverMixin, QObject):
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 = 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 = QAction(menu_bar)
Translations.translate_qobject(self.tag_manager_action, "menu.edit.manage_tags")
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(
@@ -547,22 +524,19 @@ class QtDriver(DriverMixin, QObject):
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 = 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 = QAction(menu_bar)
Translations.translate_qobject(show_libs_list_action, "settings.show_recent_libraries")
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 = QAction(menu_bar)
Translations.translate_qobject(show_filenames_action, "settings.show_filenames_in_grid")
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))
@@ -581,9 +555,8 @@ class QtDriver(DriverMixin, QObject):
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 = 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)
@@ -594,8 +567,9 @@ class QtDriver(DriverMixin, QObject):
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 = 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)
@@ -603,9 +577,8 @@ class QtDriver(DriverMixin, QObject):
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 = QAction(
Translations["settings.clear_thumb_cache.title"], menu_bar
)
self.clear_thumb_cache_action.triggered.connect(
lambda: CacheManager.clear_cache(self.lib.library_dir)
@@ -632,8 +605,7 @@ class QtDriver(DriverMixin, QObject):
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 = 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)
@@ -644,8 +616,7 @@ class QtDriver(DriverMixin, QObject):
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 = 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()
@@ -766,12 +737,8 @@ class QtDriver(DriverMixin, QObject):
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)
@@ -815,10 +782,8 @@ class QtDriver(DriverMixin, QObject):
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)
@@ -911,8 +876,8 @@ class QtDriver(DriverMixin, QObject):
end_time = time.time()
self.main_window.statusbar.showMessage(
Translations.translate_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)
)
)
@@ -923,8 +888,7 @@ class QtDriver(DriverMixin, QObject):
target_path = self.lib.save_library_backup_to_disk()
end_time = time.time()
self.main_window.statusbar.showMessage(
Translations.translate_formatted(
"status.library_backup_success",
Translations["status.library_backup_success"].format(
path=target_path,
time_span=format_timespan(end_time - start_time),
)
@@ -936,8 +900,8 @@ class QtDriver(DriverMixin, QObject):
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: (
@@ -1022,8 +986,8 @@ class QtDriver(DriverMixin, QObject):
self.preview_panel.thumb.stop_file_use()
if delete_file(self.lib.library_dir / f):
self.main_window.statusbar.showMessage(
Translations.translate_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()
@@ -1040,19 +1004,17 @@ class QtDriver(DriverMixin, QObject):
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["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.translate_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.translate_formatted("status.deleted_file_plural", count=deleted_count)
Translations["status.deleted_file_plural"].format(count=deleted_count)
)
self.main_window.statusbar.repaint()
@@ -1069,8 +1031,8 @@ class QtDriver(DriverMixin, QObject):
# 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(
"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"<h4 style='color: {get_ui_color(ColorType.PRIMARY, UiColor.RED)}'>"
@@ -1087,8 +1049,8 @@ class QtDriver(DriverMixin, QObject):
)
msg.setIcon(QMessageBox.Icon.Warning)
if count <= 1:
msg_text = Translations.translate_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"<h3>{msg_text}</h3>"
@@ -1097,8 +1059,7 @@ class QtDriver(DriverMixin, QObject):
f"{perm_warning}<br>"
)
elif count > 1:
msg_text = Translations.translate_formatted(
"trash.dialog.move.confirmation.plural",
msg_text = Translations["trash.dialog.move.confirmation.plural"].format(
count=count,
trash_term=trash_term(),
)
@@ -1123,8 +1084,8 @@ class QtDriver(DriverMixin, QObject):
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()
@@ -1133,10 +1094,11 @@ class QtDriver(DriverMixin, QObject):
lambda x: (
pw.update_progress(x + 1),
pw.update_label(
Translations.translate_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}",
)
@@ -1166,17 +1128,17 @@ class QtDriver(DriverMixin, QObject):
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()
iterator.value.connect(
lambda: (
pw.update_label(
Translations.translate_formatted(
"entries.running.dialog.new_entries", total=f"{files_count:n}"
Translations["entries.running.dialog.new_entries"].format(
total=f"{files_count:n}"
)
),
)
@@ -1735,8 +1697,7 @@ class QtDriver(DriverMixin, QObject):
# inform user about completed search
self.main_window.statusbar.showMessage(
Translations.translate_formatted(
"status.results_found",
Translations["status.results_found"].format(
count=results.total_count,
time_span=format_timespan(end_time - start_time),
)
@@ -1811,8 +1772,9 @@ class QtDriver(DriverMixin, QObject):
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 = 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)
@@ -1849,8 +1811,8 @@ class QtDriver(DriverMixin, QObject):
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):
@@ -1861,13 +1823,9 @@ class QtDriver(DriverMixin, QObject):
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.translate_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:
@@ -1911,11 +1869,10 @@ class QtDriver(DriverMixin, QObject):
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)

View File

@@ -143,12 +143,11 @@ class ColorBoxWidget(FieldWidget):
self.edit_modal.show()
def delete_color(self, color_group: TagColorGroup):
message_box = QMessageBox()
Translations.translate_with_setter(message_box.setWindowTitle, "color.delete")
Translations.translate_qobject(
message_box, "color.confirm_delete", color_name=color_group.name
message_box = QMessageBox(
QMessageBox.Icon.Warning,
Translations["color.delete"],
Translations["color.confirm_delete"].format(color_name=color_group.name),
)
message_box.setIcon(QMessageBox.Icon.Warning)
cancel_button = message_box.addButton(
Translations["generic.cancel_alt"], QMessageBox.ButtonRole.RejectRole
)

View File

@@ -216,15 +216,13 @@ class ItemThumb(FlowWidget):
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 = 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 = QAction(self)
Translations.translate_qobject(
self.delete_action, "trash.context.ambiguous", trash_term=trash_term()
self.delete_action = QAction(
Translations["trash.context.ambiguous"].format(trash_term=trash_term()), self
)
self.thumb_button.addAction(open_file_action)
@@ -313,8 +311,7 @@ class ItemThumb(FlowWidget):
self.cb_layout.addWidget(badge)
# Filename Label =======================================================
self.file_label = QLabel()
Translations.translate_qobject(self.file_label, "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:

View File

@@ -61,11 +61,10 @@ class LandingWidget(QWidget):
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 = QPushButton(
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)
# Create status label --------------------------------------------------

View File

@@ -57,7 +57,7 @@ class JsonMigrationModal(QObject):
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["json_migration.title"].format(path=self.path)
self.warning: str = "<b><a style='color: #e22c3c'>(!)</a></b>"
self.old_entry_count: int = 0
@@ -81,17 +81,14 @@ class JsonMigrationModal(QObject):
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 = 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 = QPushButtonWrapper()
Translations.translate_qobject(cancel_button, "generic.cancel")
next_button = QPushButtonWrapper()
Translations.translate_qobject(next_button, "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(
@@ -142,8 +139,7 @@ class JsonMigrationModal(QObject):
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 = QLabel(Translations["json_migration.title.old_lib"])
old_lib_title.setAlignment(Qt.AlignmentFlag.AlignCenter)
old_lib_layout.addWidget(old_lib_title)
@@ -210,8 +206,7 @@ class JsonMigrationModal(QObject):
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 = QLabel(Translations["json_migration.title.new_lib"])
new_lib_title.setAlignment(Qt.AlignmentFlag.AlignCenter)
new_lib_layout.addWidget(new_lib_title)
@@ -292,15 +287,14 @@ class JsonMigrationModal(QObject):
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 = 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: QPushButtonWrapper = QPushButtonWrapper()
Translations.translate_qobject(finish_button, "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)
@@ -411,8 +405,8 @@ class JsonMigrationModal(QObject):
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(
"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"]
@@ -481,15 +475,12 @@ class JsonMigrationModal(QObject):
QApplication.alert(self.paged_panel)
if not show_msg_box:
return
msg_box = QMessageBox()
Translations.translate_with_setter(
msg_box.setWindowTitle, "json_migration.discrepancies_found"
)
Translations.translate_qobject(
msg_box, "json_migration.discrepancies_found.description"
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):

View File

@@ -15,8 +15,8 @@ class PagedPanelState:
title: str,
body_wrapper: PagedBodyWrapper,
buttons: list[QPushButton | int],
connect_to_back=list[QPushButton],
connect_to_next=list[QPushButton],
connect_to_back: list[QPushButton],
connect_to_next: list[QPushButton],
):
self.title: str = title
self.body_wrapper: PagedBodyWrapper = body_wrapper

View File

@@ -52,8 +52,7 @@ class PanelModal(QWidget):
# 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 = QPushButton(Translations["generic.done"])
self.done_button.setAutoDefault(True)
self.done_button.clicked.connect(self.hide)
if done_callback:
@@ -62,16 +61,14 @@ class PanelModal(QWidget):
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 = 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 = QPushButton()
Translations.translate_qobject(self.save_button, "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)

View File

@@ -246,7 +246,7 @@ class FieldContainers(QWidget):
return cats
def remove_field_prompt(self, name: str) -> str:
return Translations.translate_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.

View File

@@ -228,7 +228,7 @@ class FileAttributes(QWidget):
"""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.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("")

View File

@@ -54,12 +54,10 @@ class PreviewThumb(QWidget):
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 = QAction(Translations["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 = QAction(
Translations["trash.context.ambiguous"].format(trash_term=trash_term()), self
)
self.preview_img = QPushButtonWrapper()
@@ -380,7 +378,7 @@ class PreviewThumb(QWidget):
self.delete_action.triggered.disconnect()
self.delete_action.setText(
Translations.translate_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)

View File

@@ -74,10 +74,8 @@ class PreviewPanel(QWidget):
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.translate_formatted("tag.add.plural")
)
Translations.translate_with_setter(self.add_tag_modal.setWindowTitle, "tag.add.plural")
self.add_tag_modal = PanelModal(self.tag_search_panel, Translations["tag.add.plural"])
self.add_tag_modal.setWindowTitle(Translations["tag.add.plural"])
self.add_field_modal = AddFieldModal(self.lib)
@@ -100,19 +98,17 @@ class PreviewPanel(QWidget):
add_buttons_layout.setContentsMargins(0, 0, 0, 0)
add_buttons_layout.setSpacing(6)
self.add_tag_button = QPushButton()
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)
Translations.translate_qobject(self.add_tag_button, "tag.add")
self.add_field_button = QPushButton()
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)
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)

View File

@@ -130,7 +130,7 @@ class TagWidget(QWidget):
if has_edit:
edit_action = QAction(self)
edit_action.setText(Translations.translate_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 @@ class TagWidget(QWidget):
# 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["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"))

View File

@@ -60,7 +60,7 @@ class TagColorLabel(QWidget):
self.bg_button.setFlat(True)
edit_action = QAction(self)
edit_action.setText(Translations.translate_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)

View File

@@ -70,7 +70,7 @@ class TagColorPreview(QWidget):
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["color.title.no_color"])
primary_color = self._get_primary_color(color_group)
border_color = (

View File

@@ -116,8 +116,7 @@ class VideoPlayer(QGraphicsView):
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 = QAction(Translations["media_player.autoplay"], self)
autoplay_action.setCheckable(True)
self.addAction(autoplay_action)
autoplay_action.setChecked(
@@ -126,8 +125,7 @@ class VideoPlayer(QGraphicsView):
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 = QAction(Translations["file.open_file"], self)
open_file_action.triggered.connect(self.opener.open_file)
open_explorer_action = QAction(open_file_str(), self)