diff --git a/src/tagstudio/qt/controllers/changelog_modal.py b/src/tagstudio/qt/controllers/changelog_modal.py index 460492654..9c916367e 100644 --- a/src/tagstudio/qt/controllers/changelog_modal.py +++ b/src/tagstudio/qt/controllers/changelog_modal.py @@ -24,6 +24,7 @@ QTextFormat, ) from PySide6.QtNetwork import QNetworkAccessManager, QNetworkReply, QNetworkRequest +from PySide6.QtWidgets import QDialogButtonBox from tagstudio.core.constants import DOCS_URL, GITHUB_REPO_URL from tagstudio.core.utils.types import unwrap @@ -313,8 +314,8 @@ def parent_post_init(self) -> None: assert isinstance(modal_view, ModalView) close_button = unwrap(self.done_button) close_button.setText(Translations["generic.close"]) - modal_view.button_layout.insertWidget( - modal_view.button_layout.indexOf(close_button), self.layout().view_more_button + modal_view.button_box.addButton( + self.layout().view_more_button, QDialogButtonBox.ButtonRole.ActionRole ) # NOTE: A lot of the styling is similar to the "About" window, which eventually needs to be diff --git a/src/tagstudio/qt/controllers/edit_field_template_modal.py b/src/tagstudio/qt/controllers/edit_field_template_modal.py index f8ebaf990..a8915bec3 100644 --- a/src/tagstudio/qt/controllers/edit_field_template_modal.py +++ b/src/tagstudio/qt/controllers/edit_field_template_modal.py @@ -19,8 +19,8 @@ # TODO: Use newer MVC style guidelines class EditFieldTemplateModal(EditFieldTemplateModalView): field_type_map: dict[str, str] = { - "TextFieldTemplate": Translations["field_type.text"], - "DatetimeFieldTemplate": Translations["field_type.datetime"], + "TextFieldTemplate": "field_type.text", + "DatetimeFieldTemplate": "field_type.datetime", } DEFAULT_TYPE_INDEX = 0 @@ -32,7 +32,7 @@ def __init__(self, field_template: BaseFieldTemplate | None = None) -> None: self.old_field_type: str = "" for k, v in EditFieldTemplateModal.field_type_map.items(): - self._type_combobox.addItem(v, k) + self._type_combobox.addItem(Translations[v], k) self.__connect_callbacks() self.set_field_template(field_template) diff --git a/src/tagstudio/qt/controllers/field_template_search_panel.py b/src/tagstudio/qt/controllers/field_template_search_panel.py index 984792291..39d1f53f3 100644 --- a/src/tagstudio/qt/controllers/field_template_search_panel.py +++ b/src/tagstudio/qt/controllers/field_template_search_panel.py @@ -89,11 +89,18 @@ def _on_item_remove(self, item: BaseFieldTemplate) -> None: return message_box = QMessageBox( - QMessageBox.Icon.Question, + QMessageBox.Icon.Warning, Translations["field_template.delete"], Translations.format("field_template.confirm_delete", field_template_name=item.name), QMessageBox.StandardButton.Ok | QMessageBox.StandardButton.Cancel, ) + unwrap(message_box.button(QMessageBox.StandardButton.Ok)).setText( + Translations["generic.delete_alt"] + ) + unwrap(message_box.button(QMessageBox.StandardButton.Cancel)).setText( + Translations["generic.cancel_alt"] + ) + message_box.setDefaultButton(QMessageBox.StandardButton.Cancel) result = message_box.exec() diff --git a/src/tagstudio/qt/controllers/main_window.py b/src/tagstudio/qt/controllers/main_window.py index 46c50bd58..ef13a769f 100644 --- a/src/tagstudio/qt/controllers/main_window.py +++ b/src/tagstudio/qt/controllers/main_window.py @@ -455,11 +455,11 @@ def rebuild_open_recent_library_menu( # View Component class MainWindow(QMainWindow): THUMB_SIZES: list[tuple[str, int]] = [ - (Translations["home.thumbnail_size.extra_large"], 256), - (Translations["home.thumbnail_size.large"], 192), - (Translations["home.thumbnail_size.medium"], 128), - (Translations["home.thumbnail_size.small"], 96), - (Translations["home.thumbnail_size.mini"], 76), + ("home.thumbnail_size.extra_large", 256), + ("home.thumbnail_size.large", 192), + ("home.thumbnail_size.medium", 128), + ("home.thumbnail_size.small", 96), + ("home.thumbnail_size.mini", 76), ] def __init__(self, driver: QtDriver, parent: QWidget | None = None) -> None: @@ -656,7 +656,7 @@ def setup_extra_input_bar(self): self.thumb_size_combobox.setMaximumWidth(352) self.extra_input_layout.addWidget(self.thumb_size_combobox) for size in MainWindow.THUMB_SIZES: - self.thumb_size_combobox.addItem(size[0], size[1]) + self.thumb_size_combobox.addItem(Translations[size[0]], size[1]) self.thumb_size_combobox.setCurrentIndex(2) # Default: Medium def setup_content(self, driver: QtDriver): diff --git a/src/tagstudio/qt/controllers/splash.py b/src/tagstudio/qt/controllers/splash.py index 2a39028f1..90866af52 100644 --- a/src/tagstudio/qt/controllers/splash.py +++ b/src/tagstudio/qt/controllers/splash.py @@ -23,12 +23,6 @@ class SplashScreen: """The custom splash screen widget for TagStudio.""" - VERSION_STR: str = " ".join( - [ - f"{Translations['about.version']}", - f"{VERSION} {(' (' + Translations[BUILD_TYPE] + ')') if BUILD_TYPE else ''}", - ] - ) DEFAULT_SPLASH = Splash.AURORA def __init__( @@ -68,6 +62,13 @@ def get_pixmap(self) -> QPixmap: case _: pass + version_str = " ".join( + [ + f"{Translations['about.version']}", + f"{VERSION} {(' (' + Translations[BUILD_TYPE] + ')') if BUILD_TYPE else ''}", + ] + ) + # TODO: Store any differing data elsewhere and load dynamically instead of hardcoding. match self.splash_name: case Splash.CLASSIC: @@ -88,7 +89,7 @@ def get_pixmap(self) -> QPixmap: painter.drawText( QRect(0, -50, 960, 540), int(Qt.AlignmentFlag.AlignBottom | Qt.AlignmentFlag.AlignHCenter), - SplashScreen.VERSION_STR, + version_str, ) case Splash.GOO_GEARS: @@ -110,7 +111,7 @@ def get_pixmap(self) -> QPixmap: painter.setPen(pen) painter.drawText( QRect(40, 420, 960, 540), - SplashScreen.VERSION_STR, + version_str, ) case Splash.NINETY_FIVE: @@ -136,7 +137,7 @@ def get_pixmap(self) -> QPixmap: painter.drawText( QRect(-30, 25, 960, 540), int(Qt.AlignmentFlag.AlignTop | Qt.AlignmentFlag.AlignRight), - SplashScreen.VERSION_STR, + version_str, ) case Splash.AURORA: @@ -157,7 +158,7 @@ def get_pixmap(self) -> QPixmap: painter.drawText( QRect(0, -50, 960, 540), int(Qt.AlignmentFlag.AlignBottom | Qt.AlignmentFlag.AlignHCenter), - SplashScreen.VERSION_STR, + version_str, ) case _: diff --git a/src/tagstudio/qt/controllers/tag_search_panel.py b/src/tagstudio/qt/controllers/tag_search_panel.py index c7f083721..e6b89b0d7 100644 --- a/src/tagstudio/qt/controllers/tag_search_panel.py +++ b/src/tagstudio/qt/controllers/tag_search_panel.py @@ -88,11 +88,18 @@ def _on_item_remove(self, item: Tag) -> None: return message_box = QMessageBox( - QMessageBox.Icon.Question, + QMessageBox.Icon.Warning, Translations["tag.remove"], Translations.format("tag.confirm_delete", tag_name=self._lib.tag_display_name(item)), QMessageBox.StandardButton.Ok | QMessageBox.StandardButton.Cancel, ) + unwrap(message_box.button(QMessageBox.StandardButton.Ok)).setText( + Translations["generic.delete_alt"] + ) + unwrap(message_box.button(QMessageBox.StandardButton.Cancel)).setText( + Translations["generic.cancel_alt"] + ) + message_box.setDefaultButton(QMessageBox.StandardButton.Cancel) result = message_box.exec() diff --git a/src/tagstudio/qt/controllers/tiles/color_data.py b/src/tagstudio/qt/controllers/tiles/color_data.py index b232adf22..d81d5876a 100644 --- a/src/tagstudio/qt/controllers/tiles/color_data.py +++ b/src/tagstudio/qt/controllers/tiles/color_data.py @@ -95,7 +95,7 @@ def set_colors(self, colors: Iterable[TagColorGroup]): TagColorGroup( slug="slug", namespace=self.namespace, - name="Color", + name=Translations["color.placeholder"], primary="#FFFFFF", secondary=None, ) @@ -108,7 +108,7 @@ def edit_color(self, color_group: TagColorGroup): self.edit_modal = Modal( build_color_panel, - "Edit Color", + Translations["color.edit"], is_savable=True, ) @@ -126,13 +126,13 @@ def delete_color(self, color_group: TagColorGroup): cancel_button = message_box.addButton( Translations["generic.cancel_alt"], QMessageBox.ButtonRole.RejectRole ) - message_box.addButton( - Translations["generic.delete_alt"], QMessageBox.ButtonRole.DestructiveRole + delete_button = message_box.addButton( + Translations["generic.delete_alt"], QMessageBox.ButtonRole.AcceptRole ) message_box.setEscapeButton(cancel_button) - result = message_box.exec_() - logger.info(QMessageBox.ButtonRole.DestructiveRole.value) - if result != QMessageBox.ButtonRole.ActionRole.value: + message_box.setDefaultButton(cancel_button) + message_box.exec() + if message_box.clickedButton() != delete_button: return logger.info("[ColorData] Removing color", color=color_group) diff --git a/src/tagstudio/qt/controllers/tiles/tile_list.py b/src/tagstudio/qt/controllers/tiles/tile_list.py index ff3b79202..3c263030a 100644 --- a/src/tagstudio/qt/controllers/tiles/tile_list.py +++ b/src/tagstudio/qt/controllers/tiles/tile_list.py @@ -418,17 +418,20 @@ def update_datetime_field(self, field: DatetimeField, name: str, value: str) -> self.lib.update_datetime_field(entry_ids, field, name, dt.fromisoformat(value)) def remove_message_box(self, prompt: str, callback: Callable[..., None]) -> None: - remove_mb = QMessageBox() - remove_mb.setText(prompt) - remove_mb.setWindowTitle(Translations["Remove Field"]) - remove_mb.setIcon(QMessageBox.Icon.Warning) - cancel_button = remove_mb.addButton( + message_box = QMessageBox() + message_box.setText(prompt) + message_box.setWindowTitle(Translations["field.remove"]) + message_box.setIcon(QMessageBox.Icon.Warning) + cancel_button = message_box.addButton( Translations["generic.cancel_alt"], QMessageBox.ButtonRole.RejectRole ) - remove_mb.addButton("&Remove", QMessageBox.ButtonRole.DestructiveRole) - remove_mb.setEscapeButton(cancel_button) - result = remove_mb.exec_() - if result == QMessageBox.ButtonRole.ActionRole.value: + remove_button = message_box.addButton( + Translations["generic.remove_alt"], QMessageBox.ButtonRole.AcceptRole + ) + message_box.setEscapeButton(cancel_button) + message_box.setDefaultButton(cancel_button) + message_box.exec() + if message_box.clickedButton() == remove_button: callback() @property diff --git a/src/tagstudio/qt/controllers/update_available_message_box.py b/src/tagstudio/qt/controllers/update_available_message_box.py index 97362438d..033dc6e0b 100644 --- a/src/tagstudio/qt/controllers/update_available_message_box.py +++ b/src/tagstudio/qt/controllers/update_available_message_box.py @@ -54,6 +54,7 @@ def __init__(self): partial(QDesktopServices.openUrl, GITHUB_RELEASE_URL) ) self.button(QMessageBox.StandardButton.Ignore).setText(Translations["generic.dont_remind"]) + self.button(QMessageBox.StandardButton.Close).setText(Translations["generic.close"]) red = get_ui_color(ColorType.PRIMARY, UiColor.RED) green = get_ui_color(ColorType.PRIMARY, UiColor.GREEN) diff --git a/src/tagstudio/qt/mixed/about_modal.py b/src/tagstudio/qt/mixed/about_modal.py index ad166f9fa..48298f07e 100644 --- a/src/tagstudio/qt/mixed/about_modal.py +++ b/src/tagstudio/qt/mixed/about_modal.py @@ -44,13 +44,6 @@ class AboutModal(QWidget): """Modal window showing information about the TagStudio application.""" - VERSION_STR: str = " ".join( - [ - f"{Translations['about.version']}", - f"{VERSION} {(' (' + Translations[BUILD_TYPE] + ')') if BUILD_TYPE else ''}", - ] - ) - def __init__(self, config_path: Path | str): super().__init__() self.setWindowTitle(Translations["about.title"]) @@ -89,7 +82,13 @@ def __init__(self, config_path: Path | str): self.logo_widget.setAlignment(Qt.AlignmentFlag.AlignCenter) # Version -------------------------------------------------------------- - self.version_label = QLabel(header(AboutModal.VERSION_STR, 2)) + version_str = " ".join( + [ + f"{Translations['about.version']}", + f"{VERSION} {(' (' + Translations[BUILD_TYPE] + ')') if BUILD_TYPE else ''}", + ] + ) + self.version_label = QLabel(header(version_str, 2)) self.version_label.setAlignment(Qt.AlignmentFlag.AlignCenter) # Copyright ------------------------------------------------------------ diff --git a/src/tagstudio/qt/mixed/drop_import_modal.py b/src/tagstudio/qt/mixed/drop_import_modal.py index 6f54c5925..aeb256d3a 100644 --- a/src/tagstudio/qt/mixed/drop_import_modal.py +++ b/src/tagstudio/qt/mixed/drop_import_modal.py @@ -63,6 +63,10 @@ def __init__(self, driver: QtDriver): self.button_layout.setContentsMargins(6, 6, 6, 6) self.button_layout.addStretch(1) + 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) + self.skip_button = QPushButton(Translations["generic.skip_alt"]) self.skip_button.setDefault(True) self.skip_button.clicked.connect(lambda: self.begin_transfer(DuplicateChoice.SKIP)) @@ -78,10 +82,6 @@ def __init__(self, driver: QtDriver): self.rename_button.clicked.connect(lambda: self.begin_transfer(DuplicateChoice.RENAME)) self.button_layout.addWidget(self.rename_button) - 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) - # Layout ===================== self.root_layout.addWidget(self.desc_widget) self.root_layout.addWidget(self.list_view) diff --git a/src/tagstudio/qt/mixed/folders_to_tags.py b/src/tagstudio/qt/mixed/folders_to_tags.py index f2e6914c1..47bfed84a 100644 --- a/src/tagstudio/qt/mixed/folders_to_tags.py +++ b/src/tagstudio/qt/mixed/folders_to_tags.py @@ -182,13 +182,9 @@ def __init__(self, library: Library, driver: QtDriver): self.title_widget.setWordWrap(True) self.title_widget.setAlignment(Qt.AlignmentFlag.AlignCenter) - self.desc_widget = QLabel() + self.desc_widget = QLabel(Translations["folders_to_tags.description"]) self.desc_widget.setObjectName("descriptionLabel") self.desc_widget.setWordWrap(True) - self.desc_widget.setText( - """Creates tags based on your folder structure and applies them to your entries. - This tree shows all tags to be created and which entries they will be applied to.""" - ) self.desc_widget.setAlignment(Qt.AlignmentFlag.AlignCenter) self.open_close_button_w = QWidget() diff --git a/src/tagstudio/qt/mixed/migration_modal.py b/src/tagstudio/qt/mixed/migration_modal.py index e300cc692..c2fb54bf2 100644 --- a/src/tagstudio/qt/mixed/migration_modal.py +++ b/src/tagstudio/qt/mixed/migration_modal.py @@ -462,6 +462,7 @@ def update_sql_value_ui(self, show_msg_box: bool = True): Translations["json_migration.discrepancies_found.description"], ) msg_box.setDetailedText("\n".join(self.discrepancies)) + msg_box.addButton(Translations["generic.close"], QMessageBox.ButtonRole.AcceptRole) msg_box.exec() def finish_migration(self): diff --git a/src/tagstudio/qt/mixed/settings_panel.py b/src/tagstudio/qt/mixed/settings_panel.py index 26ffa079a..45557d071 100644 --- a/src/tagstudio/qt/mixed/settings_panel.py +++ b/src/tagstudio/qt/mixed/settings_panel.py @@ -43,30 +43,30 @@ class SettingsPanel(ModalContent): driver: QtDriver filepath_option_map: dict[ShowFilepathOption, str] = { - ShowFilepathOption.SHOW_FULL_PATHS: Translations["settings.filepath.option.full"], - ShowFilepathOption.SHOW_RELATIVE_PATHS: Translations["settings.filepath.option.relative"], - ShowFilepathOption.SHOW_FILENAMES_ONLY: Translations["settings.filepath.option.name"], + ShowFilepathOption.SHOW_FULL_PATHS: "settings.filepath.option.full", + ShowFilepathOption.SHOW_RELATIVE_PATHS: "settings.filepath.option.relative", + ShowFilepathOption.SHOW_FILENAMES_ONLY: "settings.filepath.option.name", } theme_map: dict[Theme, str] = { - Theme.SYSTEM: Translations["settings.theme.system"], - Theme.DARK: Translations["settings.theme.dark"], - Theme.LIGHT: Translations["settings.theme.light"], + Theme.SYSTEM: "settings.theme.system", + Theme.DARK: "settings.theme.dark", + Theme.LIGHT: "settings.theme.light", } splash_map: dict[Splash, str] = { - Splash.DEFAULT: Translations["settings.splash.option.default"], - Splash.RANDOM: Translations["settings.splash.option.random"], - Splash.CLASSIC: Translations["settings.splash.option.classic"], - Splash.GOO_GEARS: Translations["settings.splash.option.goo_gears"], - Splash.NINETY_FIVE: Translations["settings.splash.option.ninety_five"], - Splash.AURORA: Translations["settings.splash.option.aurora"], + Splash.DEFAULT: "settings.splash.option.default", + Splash.RANDOM: "settings.splash.option.random", + Splash.CLASSIC: "settings.splash.option.classic", + Splash.GOO_GEARS: "settings.splash.option.goo_gears", + Splash.NINETY_FIVE: "settings.splash.option.ninety_five", + Splash.AURORA: "settings.splash.option.aurora", } tag_click_action_map: dict[TagClickActionOption, str] = { - TagClickActionOption.OPEN_EDIT: Translations["settings.tag_click_action.open_edit"], - TagClickActionOption.SET_SEARCH: Translations["settings.tag_click_action.set_search"], - TagClickActionOption.ADD_TO_SEARCH: Translations["settings.tag_click_action.add_to_search"], + TagClickActionOption.OPEN_EDIT: "settings.tag_click_action.open_edit", + TagClickActionOption.SET_SEARCH: "settings.tag_click_action.set_search", + TagClickActionOption.ADD_TO_SEARCH: "settings.tag_click_action.add_to_search", } date_format_map: dict[str, str] = { @@ -194,7 +194,7 @@ def on_page_size_changed(): # Show Filepath self.filepath_combobox = QComboBox() for k in SettingsPanel.filepath_option_map: - self.filepath_combobox.addItem(SettingsPanel.filepath_option_map[k], k) + self.filepath_combobox.addItem(Translations[SettingsPanel.filepath_option_map[k]], k) filepath_option: ShowFilepathOption = self.driver.settings.show_filepath if filepath_option not in SettingsPanel.filepath_option_map: filepath_option = ShowFilepathOption.DEFAULT @@ -206,7 +206,9 @@ def on_page_size_changed(): # Tag Click Action self.tag_click_action_combobox = QComboBox() for k in SettingsPanel.tag_click_action_map: - self.tag_click_action_combobox.addItem(SettingsPanel.tag_click_action_map[k], k) + self.tag_click_action_combobox.addItem( + Translations[SettingsPanel.tag_click_action_map[k]], k + ) tag_click_action = self.driver.settings.tag_click_action if tag_click_action not in SettingsPanel.tag_click_action_map: tag_click_action = TagClickActionOption.DEFAULT @@ -375,7 +377,7 @@ def __build_appearance_settings(self): # Dark Mode self.theme_combobox = QComboBox() for k in SettingsPanel.theme_map: - self.theme_combobox.addItem(SettingsPanel.theme_map[k], k) + self.theme_combobox.addItem(Translations[SettingsPanel.theme_map[k]], k) theme = self.driver.settings.theme if theme not in SettingsPanel.theme_map: theme = Theme.DEFAULT @@ -386,7 +388,7 @@ def __build_appearance_settings(self): # Splash Screen self.splash_combobox = QComboBox() for k in SettingsPanel.splash_map: - self.splash_combobox.addItem(SettingsPanel.splash_map[k], k) + self.splash_combobox.addItem(Translations[SettingsPanel.splash_map[k]], k) splash = self.driver.settings.splash if splash not in SettingsPanel.splash_map: splash = Splash.DEFAULT diff --git a/src/tagstudio/qt/mixed/tag_color_manager.py b/src/tagstudio/qt/mixed/tag_color_manager.py index 19ef50aea..eb66738d1 100644 --- a/src/tagstudio/qt/mixed/tag_color_manager.py +++ b/src/tagstudio/qt/mixed/tag_color_manager.py @@ -200,12 +200,13 @@ def delete_namespace_dialog(self, prompt: str, callback: Callable[..., Any]) -> cancel_button = message_box.addButton( Translations["generic.cancel_alt"], QMessageBox.ButtonRole.RejectRole ) - message_box.addButton( - Translations["generic.delete_alt"], QMessageBox.ButtonRole.DestructiveRole + delete_button = message_box.addButton( + Translations["generic.delete_alt"], QMessageBox.ButtonRole.AcceptRole ) message_box.setEscapeButton(cancel_button) - result = message_box.exec_() - if result != QMessageBox.ButtonRole.ActionRole.value: + message_box.setDefaultButton(cancel_button) + message_box.exec() + if message_box.clickedButton() != delete_button: return callback() diff --git a/src/tagstudio/qt/qt_driver.py b/src/tagstudio/qt/qt_driver.py index f3f812e8d..28d80bb58 100644 --- a/src/tagstudio/qt/qt_driver.py +++ b/src/tagstudio/qt/qt_driver.py @@ -979,25 +979,19 @@ def delete_files_callback(self, origin_path: str | Path, origin_id: int | None = filepath: Path = entry.path pending.append((item, filepath)) - if pending: - return_code = self.delete_file_confirmation(len(pending), pending[0][1]) - # If there was a confirmation and not a cancellation - if ( - return_code == QMessageBox.ButtonRole.DestructiveRole.value - and return_code != QMessageBox.ButtonRole.ActionRole.value - ): - for e_id, f in pending: - if (origin_path == f) or (not origin_path): - self.main_window.inspector.stop_media_playback() - - if e_id is not None: - self.lib.remove_entries([e_id]) - delete_file(library_dir / f) - - self.clear_select_action_callback() - self.update_browsing_state() - - def delete_file_confirmation(self, count: int, filename: Path | None = None) -> int: + if pending and self.delete_file_confirmation(len(pending), pending[0][1]): + for e_id, f in pending: + if (origin_path == f) or (not origin_path): + self.main_window.inspector.stop_media_playback() + + if e_id is not None: + self.lib.remove_entries([e_id]) + delete_file(library_dir / f) + + self.clear_select_action_callback() + self.update_browsing_state() + + def delete_file_confirmation(self, count: int, filename: Path | None = None) -> bool: """A confirmation dialogue box for deleting files. Args: @@ -1021,9 +1015,9 @@ def delete_file_confirmation(self, count: int, filename: Path | None = None) -> msg.setStyleSheet("font-weight:normal;") msg.setTextFormat(Qt.TextFormat.RichText) msg.setWindowTitle( - Translations["trash.title.singular"] + Translations["trash.dialog.title.singular"] if count == 1 - else Translations["trash.title.plural"] + else Translations["trash.dialog.title.plural"] ) msg.setIcon(QMessageBox.Icon.Warning) if count <= 1: @@ -1048,11 +1042,23 @@ def delete_file_confirmation(self, count: int, filename: Path | None = None) -> f"{perm_warning}
" ) - yes_button: QPushButton = msg.addButton("&Yes", QMessageBox.ButtonRole.YesRole) - msg.addButton("&No", QMessageBox.ButtonRole.NoRole) - msg.setDefaultButton(yes_button) + move_key = ( + "menu.delete_selected_files_singular" + if count <= 1 + else "menu.delete_selected_files_plural" + ) + cancel_button = msg.addButton( + Translations["generic.cancel_alt"], QMessageBox.ButtonRole.RejectRole + ) + move_button: QPushButton = msg.addButton( + Translations.format(move_key, trash_term=trash_term()), + QMessageBox.ButtonRole.AcceptRole, + ) + msg.setEscapeButton(cancel_button) + msg.setDefaultButton(cancel_button) - return msg.exec() + msg.exec() + return msg.clickedButton() == move_button def _run_sync_step( self, diff --git a/src/tagstudio/qt/views/library_info_window_view.py b/src/tagstudio/qt/views/library_info_window_view.py index c6de871b2..7c5a2b05d 100644 --- a/src/tagstudio/qt/views/library_info_window_view.py +++ b/src/tagstudio/qt/views/library_info_window_view.py @@ -39,7 +39,7 @@ def __init__(self, library: Library, driver: QtDriver): self.lib = library self.driver = driver - self.setWindowTitle("Library Information") + self.setWindowTitle(Translations["library_info.window_title"]) self.setMinimumSize(800, 480) self.root_layout = QVBoxLayout(self) self.root_layout.setContentsMargins(PAD, PAD, PAD, PAD) diff --git a/src/tagstudio/qt/views/modal_view.py b/src/tagstudio/qt/views/modal_view.py index 026a06ce9..c8c15ad12 100644 --- a/src/tagstudio/qt/views/modal_view.py +++ b/src/tagstudio/qt/views/modal_view.py @@ -4,7 +4,7 @@ import structlog from PySide6.QtCore import Qt -from PySide6.QtWidgets import QHBoxLayout, QLabel, QPushButton, QVBoxLayout, QWidget +from PySide6.QtWidgets import QDialogButtonBox, QLabel, QVBoxLayout from tagstudio.i18n.translations import Translations from tagstudio.qt.controllers.modal_content import ModalContent @@ -28,28 +28,26 @@ def __init__( self.content_widget = content_widget self.setContentsMargins(PAD, PAD if inline_title else PAD * 2, PAD, PAD) - self.button_container = QWidget() - self.button_layout = QHBoxLayout(self.button_container) - self.button_layout.setContentsMargins(PAD, PAD, PAD, PAD) - self.button_layout.addStretch(1) + self.button_box = QDialogButtonBox() + self.button_box.setContentsMargins(PAD, PAD, PAD, PAD) - # [Done] - # - OR - - # [Cancel] [Save] if not is_savable: - done_button = QPushButton(Translations["generic.done"]) + done_button = self.button_box.addButton( + Translations["generic.done"], QDialogButtonBox.ButtonRole.AcceptRole + ) done_button.setAutoDefault(True) self.content_widget.done_button = done_button - self.button_layout.addWidget(done_button) else: - cancel_button = QPushButton(Translations["generic.cancel"]) + cancel_button = self.button_box.addButton( + Translations["generic.cancel"], QDialogButtonBox.ButtonRole.RejectRole + ) self.content_widget.cancel_button = cancel_button - self.button_layout.addWidget(cancel_button) - save_button = QPushButton(Translations["generic.save"]) + save_button = self.button_box.addButton( + Translations["generic.save"], QDialogButtonBox.ButtonRole.AcceptRole + ) save_button.setAutoDefault(True) self.content_widget.save_button = save_button - self.button_layout.addWidget(save_button) if inline_title: self.title_label = QLabel() @@ -61,4 +59,4 @@ def __init__( self.addWidget(content_widget) self.setStretch(1, 2) - self.addWidget(self.button_container) + self.addWidget(self.button_box) diff --git a/src/tagstudio/resources/translations/en.json b/src/tagstudio/resources/translations/en.json index 42d84dc44..32d44c650 100644 --- a/src/tagstudio/resources/translations/en.json +++ b/src/tagstudio/resources/translations/en.json @@ -21,7 +21,8 @@ "color_manager.title": "Manage Tag Colors", "color.color_border": "Use Secondary Color for Border", "color.confirm_delete": "Are you sure you want to delete the color \"{color_name}\"?", - "color.delete": "Delete Tag", + "color.delete": "Delete Color", + "color.edit": "Edit Color", "color.import_pack": "Import Color Pack", "color.name": "Name", "color.namespace.delete.prompt": "Are you sure you want to delete this color namespace? This will delete ALL colors in the namespace along with it!", @@ -38,7 +39,7 @@ "drop_import.duplicates_choice.singular": "The following file matches a file path that already exists in the library.", "drop_import.progress.label.initial": "Importing New Files…", "drop_import.progress.label.plural": "Importing New Files…\n{count} Files Imported.{suffix}", - "drop_import.progress.label.singular": "Importing New Files…\n1 File imported.{suffix}", + "drop_import.progress.label.singular": "Importing New Files…\n1 File Imported.{suffix}", "drop_import.progress.window_title": "Import Files", "drop_import.title": "Conflicting File(s)", "edit.color_manager": "Manage Tag Colors", @@ -69,10 +70,10 @@ "entries.tags": "Tags", "entries.unlinked.description": "Unlinked entries are file entries that can no longer find their original file on disk. Most entries are automatically relinked during a library sync, however some cases require manual review.", "entries.unlinked.description.ambiguous": "For unlinked entries that have ambiguous matches to multiple files in your library, you may manually choose how they get relinked.", - "entries.unlinked.description.deleted": "When you delete files outside of TagStudio, their associated entries become unlinked. You may manually delete any unlinked entries at your own discretion.", + "entries.unlinked.description.deleted": "When you delete files outside of TagStudio, their associated entries become unlinked. You may manually remove any unlinked entries at your own discretion.", "entries.unlinked.relink.manual": "&Manual Relink", - "entries.unlinked.remove": "Delete Unlinked Entries", - "entries.unlinked.remove_alt": "&Delete Unlinked Entries", + "entries.unlinked.remove": "Remove Unlinked Entries", + "entries.unlinked.remove_alt": "Remo&ve Unlinked Entries", "entries.unlinked.review": "Manual &Review", "entries.unlinked.title": "Fix Unlinked Entries", "entries.unlinked.unlinked_count": "Unlinked Entries: {count}", @@ -105,7 +106,7 @@ "file.date_modified": "Date Modified", "file.dimensions": "Dimensions", "file.duplicates.description": "TagStudio supports importing DupeGuru results to manage duplicate files.", - "file.duplicates.dupeguru.advice": "After mirroring, you're free to use DupeGuru to delete the unwanted files. Afterwards, use TagStudio's \"Fix Unlinked Entries\" feature in the Tools menu in order to delete the unlinked Entries.", + "file.duplicates.dupeguru.advice": "After mirroring, you're free to use DupeGuru to delete the unwanted files. Afterwards, use TagStudio's \"Fix Unlinked Entries\" feature in the Tools menu in order to remove the unlinked Entries.", "file.duplicates.dupeguru.file_extension": "DupeGuru Files (*.dupeguru)", "file.duplicates.dupeguru.load_file": "&Load DupeGuru File", "file.duplicates.dupeguru.no_file": "No DupeGuru File Selected", @@ -186,7 +187,7 @@ "json_migration.creating_database_tables": "Creating SQL Database Tables…", "json_migration.description": "
Start and preview the results of the library migration process. The converted library will not be used unless you click \"Finish Migration\".

Library data should either have matching values or feature a \"Matched\" label. Values that do not match will be displayed in red and feature a \"(!)\" symbol next to them.
This process may take up to several minutes for larger libraries.
", "json_migration.discrepancies_found": "Library Discrepancies Found", - "json_migration.discrepancies_found.description": "Discrepancies were found between the original and converted library formats. Please review and choose to whether continue with the migration or to cancel.", + "json_migration.discrepancies_found.description": "Discrepancies were found between the original and converted library formats. Please review and choose whether to continue with the migration or to cancel.", "json_migration.finish_migration": "Finish Migration", "json_migration.heading.aliases": "Aliases:", "json_migration.heading.colors": "Colors:", @@ -251,6 +252,7 @@ "library_info.stats.tags": "Tags:", "library_info.title": "Library '{library_dir}'", "library_info.version": "Library Format Version: {version}", + "library_info.window_title": "Library Information", "library_object.name": "Name", "library_object.name_required": "Name (Required)", "library_object.slug": "ID Slug", @@ -372,7 +374,7 @@ "settings.tag_click_action.open_edit": "Edit Tag", "settings.tag_click_action.set_search": "Search for Tag", "settings.theme.dark": "Dark", - "settings.theme.label": "Theme:", + "settings.theme.label": "Theme", "settings.theme.light": "Light", "settings.theme.system": "System", "settings.thumb_cache_size.label": "Thumbnail Cache Size", @@ -431,7 +433,7 @@ "tag.parent_tags.info.searches.description": "Files tagged with \"{child}\" will also show up in searches for \"{parent}\" and \"{grandparent}\", so you don't need to apply those parent tags directly to files.
This only works one way: searching for \"{child}\" won't find everything tagged with \"{parent}\".", "tag.parent_tags.info.searches.title": "Searches", "tag.properties": "Properties", - "tag.remove": "Remove Tag", + "tag.remove": "Delete Tag", "tag.search_for_tag": "Search for Tag", "tag.shorthand": "Shorthand", "tag.tag_name_required": "Tag Name (Required)",