From 8e1ae81ec96162f53643d530ace2e5c6c6d6cbae Mon Sep 17 00:00:00 2001 From: Travis Abendshien <46939827+CyanVoxel@users.noreply.github.com> Date: Fri, 29 Aug 2025 14:25:54 -0700 Subject: [PATCH] feat: replace extension exclusion system with `.ts_ignore` (#1046) * feat: replace extension exclusion with ts_ignore --- src/tagstudio/core/library/alchemy/library.py | 52 ++++++-- src/tagstudio/core/library/ignore.py | 35 +++++- .../widgets/ignore_modal_controller.py | 50 ++++++++ src/tagstudio/qt/main_window.py | 12 +- src/tagstudio/qt/modals/file_extension.py | 112 ------------------ src/tagstudio/qt/ts_qt.py | 38 +++--- .../qt/view/widgets/ignore_modal_view.py | 49 ++++++++ .../qt/widgets/preview/file_attributes.py | 2 +- src/tagstudio/qt/widgets/thumb_renderer.py | 4 +- .../templates/ts_ignore_template.txt | 12 ++ .../templates/ts_ignore_template_blank.txt | 9 ++ src/tagstudio/resources/translations/de.json | 8 +- src/tagstudio/resources/translations/en.json | 9 +- src/tagstudio/resources/translations/es.json | 8 +- src/tagstudio/resources/translations/fil.json | 8 +- src/tagstudio/resources/translations/fr.json | 8 +- src/tagstudio/resources/translations/hu.json | 8 +- src/tagstudio/resources/translations/ja.json | 8 +- .../resources/translations/nb_NO.json | 8 +- src/tagstudio/resources/translations/nl.json | 3 +- src/tagstudio/resources/translations/pl.json | 8 +- src/tagstudio/resources/translations/pt.json | 7 -- .../resources/translations/pt_BR.json | 8 +- src/tagstudio/resources/translations/qpv.json | 8 +- src/tagstudio/resources/translations/ru.json | 8 +- src/tagstudio/resources/translations/sv.json | 4 - src/tagstudio/resources/translations/ta.json | 8 +- src/tagstudio/resources/translations/tok.json | 8 +- src/tagstudio/resources/translations/tr.json | 8 +- .../resources/translations/zh_Hans.json | 8 +- .../resources/translations/zh_Hant.json | 8 +- tests/qt/test_file_path_options.py | 2 +- tests/test_library.py | 21 ---- tests/test_search.py | 30 ++--- 34 files changed, 255 insertions(+), 324 deletions(-) create mode 100644 src/tagstudio/qt/controller/widgets/ignore_modal_controller.py delete mode 100644 src/tagstudio/qt/modals/file_extension.py create mode 100644 src/tagstudio/qt/view/widgets/ignore_modal_view.py create mode 100644 src/tagstudio/resources/templates/ts_ignore_template.txt create mode 100644 src/tagstudio/resources/templates/ts_ignore_template_blank.txt diff --git a/src/tagstudio/core/library/alchemy/library.py b/src/tagstudio/core/library/alchemy/library.py index 64a9e045..f936bfbb 100644 --- a/src/tagstudio/core/library/alchemy/library.py +++ b/src/tagstudio/core/library/alchemy/library.py @@ -50,6 +50,7 @@ from sqlalchemy.orm import ( from tagstudio.core.constants import ( BACKUP_FOLDER_NAME, + IGNORE_NAME, LEGACY_TAG_FIELD_IDS, RESERVED_NAMESPACE_PREFIX, RESERVED_TAG_END, @@ -499,6 +500,16 @@ class Library: session.commit() self.folder = folder + # Generate default .ts_ignore file + if is_new: + try: + ts_ignore_template = ( + Path(__file__).parents[3] / "resources/templates/ts_ignore_template.txt" + ) + shutil.copy2(ts_ignore_template, library_dir / TS_FOLDER_NAME / IGNORE_NAME) + except Exception as e: + logger.error("[ERROR][Library] Could not generate '.ts_ignore' file!", error=e) + # Apply any post-SQL migration patches. if not is_new: # save backup if patches will be applied @@ -523,6 +534,9 @@ class Library: if loaded_db_version < 100: self.__apply_db100_parent_repairs(session) + # Convert file extension list to ts_ignore file, if a .ts_ignore file does not exist + self.migrate_sql_to_ts_ignore(library_dir) + # Update DB_VERSION if loaded_db_version < DB_VERSION: self.set_version(DB_VERSION_CURRENT_KEY, DB_VERSION) @@ -657,6 +671,34 @@ class Library: session.commit() logger.info("[Library][Migration] Refactored TagParent column") + def migrate_sql_to_ts_ignore(self, library_dir: Path): + # Do not continue if existing '.ts_ignore' file is found + if Path(library_dir / TS_FOLDER_NAME / IGNORE_NAME).exists(): + return + + # Create blank '.ts_ignore' file + ts_ignore_template = ( + Path(__file__).parents[3] / "resources/templates/ts_ignore_template_blank.txt" + ) + ts_ignore = library_dir / TS_FOLDER_NAME / IGNORE_NAME + try: + shutil.copy2(ts_ignore_template, ts_ignore) + except Exception as e: + logger.error("[ERROR][Library] Could not generate '.ts_ignore' file!", error=e) + + # Load legacy extension data + extensions: list[str] = self.prefs(LibraryPrefs.EXTENSION_LIST) # pyright: ignore[reportAssignmentType] + is_exclude_list: bool = self.prefs(LibraryPrefs.IS_EXCLUDE_LIST) # pyright: ignore[reportAssignmentType] + + # Copy extensions to '.ts_ignore' file + if ts_ignore.exists(): + with open(ts_ignore, "a") as f: + prefix = "" + if not is_exclude_list: + prefix = "!" + f.write("*\n") + f.writelines([f"{prefix}*.{x.lstrip('.')}\n" for x in extensions]) + @property def default_fields(self) -> list[BaseField]: with Session(self.engine) as session: @@ -940,16 +982,6 @@ class Library: logger.info( f"SQL Expression Builder finished ({format_timespan(end_time - start_time)})" ) - - # TODO: Remove this from the search function and update tests. - extensions = self.prefs(LibraryPrefs.EXTENSION_LIST) - is_exclude_list = self.prefs(LibraryPrefs.IS_EXCLUDE_LIST) - - if extensions and is_exclude_list: - statement = statement.where(Entry.suffix.notin_(extensions)) - elif extensions: - statement = statement.where(Entry.suffix.in_(extensions)) - statement = statement.distinct(Entry.id) sort_on: ColumnExpressionArgument = Entry.id diff --git a/src/tagstudio/core/library/ignore.py b/src/tagstudio/core/library/ignore.py index a46d7171..66237cb2 100644 --- a/src/tagstudio/core/library/ignore.py +++ b/src/tagstudio/core/library/ignore.py @@ -88,6 +88,38 @@ class Ignore(metaclass=Singleton): _patterns: list[str] = [] compiled_patterns: fnmatch.WcMatcher | None = None + @staticmethod + def read_ignore_file(library_dir: Path) -> list[str]: + """Get the entire raw '.ts_ignore' file contents as a list of strings.""" + ts_ignore_path = Path(library_dir / TS_FOLDER_NAME / IGNORE_NAME) + + if not ts_ignore_path.exists(): + logger.info( + "[Ignore] No .ts_ignore file found", + path=ts_ignore_path, + ) + + return [] + + with open(ts_ignore_path, encoding="utf8") as f: + return f.readlines() + + @staticmethod + def write_ignore_file(library_dir: Path, lines: list[str]) -> None: + """Write to the '.ts_ignore' file.""" + ts_ignore_path = Path(library_dir / TS_FOLDER_NAME / IGNORE_NAME) + + if not ts_ignore_path.exists(): + logger.info( + "[Ignore] No .ts_ignore file found", + path=ts_ignore_path, + ) + + return + + with open(ts_ignore_path, "w", encoding="utf8") as f: + f.writelines(lines) + @staticmethod def get_patterns(library_dir: Path, include_global: bool = True) -> list[str]: """Get the ignore patterns for the given library directory. @@ -121,7 +153,8 @@ class Ignore(metaclass=Singleton): ) Ignore._patterns = patterns + Ignore._load_ignore_file(ts_ignore_path) Ignore.compiled_patterns = fnmatch.compile( - "*", PATH_GLOB_FLAGS, exclude=ignore_to_glob(Ignore._patterns) + ignore_to_glob(Ignore._patterns), + PATH_GLOB_FLAGS, ) else: logger.info( diff --git a/src/tagstudio/qt/controller/widgets/ignore_modal_controller.py b/src/tagstudio/qt/controller/widgets/ignore_modal_controller.py new file mode 100644 index 00000000..5f70e60c --- /dev/null +++ b/src/tagstudio/qt/controller/widgets/ignore_modal_controller.py @@ -0,0 +1,50 @@ +# Copyright (C) 2025 Travis Abendshien (CyanVoxel). +# Licensed under the GPL-3.0 License. +# Created for TagStudio: https://github.com/CyanVoxel/TagStudio + + +from pathlib import Path + +import structlog +from PySide6 import QtGui +from PySide6.QtCore import Signal + +from tagstudio.core.constants import IGNORE_NAME, TS_FOLDER_NAME +from tagstudio.core.library.alchemy.library import Library +from tagstudio.core.library.alchemy.models import Tag +from tagstudio.core.library.ignore import Ignore +from tagstudio.qt.helpers import file_opener +from tagstudio.qt.view.widgets.ignore_modal_view import IgnoreModalView + +logger = structlog.get_logger(__name__) + + +class IgnoreModal(IgnoreModalView): + on_edit = Signal(Tag) + + def __init__(self, library: Library) -> None: + super().__init__(library) + self.open_button.clicked.connect(self.__open_file) + + def __load_file(self): + if not self.lib.library_dir: + return + ts_ignore: list[str] = Ignore.read_ignore_file(self.lib.library_dir) + self.text_edit.setPlainText("".join(ts_ignore)) + + def __open_file(self): + if not self.lib.library_dir: + return + ts_ignore_path = Path(self.lib.library_dir / TS_FOLDER_NAME / IGNORE_NAME) + file_opener.open_file(ts_ignore_path, file_manager=True) + + def save(self): + if not self.lib.library_dir: + return + lines = self.text_edit.toPlainText().split("\n") + lines = [f"{line}\n" for line in lines] + Ignore.write_ignore_file(self.lib.library_dir, lines) + + def showEvent(self, event: QtGui.QShowEvent) -> None: # noqa N802 + self.__load_file() + return super().showEvent(event) diff --git a/src/tagstudio/qt/main_window.py b/src/tagstudio/qt/main_window.py index 1830b940..5da072ca 100644 --- a/src/tagstudio/qt/main_window.py +++ b/src/tagstudio/qt/main_window.py @@ -71,7 +71,7 @@ class MainMenuBar(QMenuBar): paste_fields_action: QAction add_tag_to_selected_action: QAction delete_file_action: QAction - manage_file_ext_action: QAction + ignore_modal_action: QAction tag_manager_action: QAction color_manager_action: QAction @@ -271,12 +271,10 @@ class MainMenuBar(QMenuBar): self.edit_menu.addSeparator() - # Manage File Extensions - self.manage_file_ext_action = QAction( - Translations["menu.edit.manage_file_extensions"], self - ) - self.manage_file_ext_action.setEnabled(False) - self.edit_menu.addAction(self.manage_file_ext_action) + # Ignore Files and Directories (.ts_ignore System) + self.ignore_modal_action = QAction(Translations["menu.edit.ignore_files"], self) + self.ignore_modal_action.setEnabled(False) + self.edit_menu.addAction(self.ignore_modal_action) # Manage Tags self.tag_manager_action = QAction(Translations["menu.edit.manage_tags"], self) diff --git a/src/tagstudio/qt/modals/file_extension.py b/src/tagstudio/qt/modals/file_extension.py deleted file mode 100644 index 02b02b58..00000000 --- a/src/tagstudio/qt/modals/file_extension.py +++ /dev/null @@ -1,112 +0,0 @@ -# Copyright (C) 2024 Travis Abendshien (CyanVoxel). -# Licensed under the GPL-3.0 License. -# Created for TagStudio: https://github.com/CyanVoxel/TagStudio - - -from PySide6.QtCore import Qt, Signal -from PySide6.QtWidgets import ( - QComboBox, - QHBoxLayout, - QLabel, - QLineEdit, - QPushButton, - QStyledItemDelegate, - QTableWidget, - QTableWidgetItem, - QVBoxLayout, - QWidget, -) - -from tagstudio.core.enums import LibraryPrefs -from tagstudio.core.library.alchemy.library import Library -from tagstudio.qt.translations import Translations -from tagstudio.qt.widgets.panel import PanelWidget - - -class FileExtensionItemDelegate(QStyledItemDelegate): - def setModelData(self, editor, model, index): # noqa: N802 - if isinstance(editor, QLineEdit) and editor.text() and not editor.text().startswith("."): - editor.setText(f".{editor.text()}") - super().setModelData(editor, model, index) - - -class FileExtensionModal(PanelWidget): - done = Signal() - - def __init__(self, library: "Library"): - super().__init__() - # Initialize Modal ===================================================== - self.lib = library - self.setWindowTitle(Translations["ignore_list.title"]) - self.setWindowModality(Qt.WindowModality.ApplicationModal) - self.setMinimumSize(240, 400) - self.root_layout = QVBoxLayout(self) - self.root_layout.setContentsMargins(6, 6, 6, 6) - - # Create Table Widget -------------------------------------------------- - self.table = QTableWidget(len(self.lib.prefs(LibraryPrefs.EXTENSION_LIST)), 1) - self.table.horizontalHeader().setVisible(False) - self.table.verticalHeader().setVisible(False) - self.table.horizontalHeader().setStretchLastSection(True) - self.table.setItemDelegate(FileExtensionItemDelegate()) - - # Create "Add Button" Widget ------------------------------------------- - 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) - - # Create Mode Widgets -------------------------------------------------- - self.mode_widget = QWidget() - 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["ignore_list.mode.label"]) - self.mode_combobox = QComboBox() - self.mode_combobox.setEditable(False) - self.mode_combobox.addItem("") - self.mode_combobox.addItem("") - 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))) - - self.mode_combobox.setCurrentIndex(is_exclude_list) - self.mode_combobox.currentIndexChanged.connect(lambda i: self.update_list_mode(i)) - self.mode_layout.addWidget(self.mode_label) - self.mode_layout.addWidget(self.mode_combobox) - self.mode_layout.setStretch(1, 1) - - # Add Widgets To Layout ------------------------------------------------ - self.root_layout.addWidget(self.mode_widget) - self.root_layout.addWidget(self.table) - self.root_layout.addWidget(self.add_button, alignment=Qt.AlignmentFlag.AlignCenter) - - # Finalize Modal ------------------------------------------------------- - self.refresh_list() - - def update_list_mode(self, mode: int): - """Update the mode of the extension list: "Exclude" or "Include". - - Args: - mode (int): The list mode, given by the index of the mode inside - the mode combobox. 1 for "Exclude", 0 for "Include". - """ - self.lib.set_prefs(LibraryPrefs.IS_EXCLUDE_LIST, bool(mode)) - - def refresh_list(self): - for i, ext in enumerate(self.lib.prefs(LibraryPrefs.EXTENSION_LIST)): - self.table.setItem(i, 0, QTableWidgetItem(ext)) - - def add_item(self): - self.table.insertRow(self.table.rowCount()) - - def save(self): - extensions = [] - for i in range(self.table.rowCount()): - ext = self.table.item(i, 0) - if ext and ext.text().strip(): - extensions.append(ext.text().strip().lstrip(".").lower()) - - # save preference - self.lib.set_prefs(LibraryPrefs.EXTENSION_LIST, extensions) diff --git a/src/tagstudio/qt/ts_qt.py b/src/tagstudio/qt/ts_qt.py index 7925a584..39abd18b 100644 --- a/src/tagstudio/qt/ts_qt.py +++ b/src/tagstudio/qt/ts_qt.py @@ -69,6 +69,7 @@ from tagstudio.core.utils.refresh_dir import RefreshDirTracker from tagstudio.core.utils.types import unwrap from tagstudio.core.utils.web import strip_web_protocol from tagstudio.qt.cache_manager import CacheManager +from tagstudio.qt.controller.widgets.ignore_modal_controller import IgnoreModal from tagstudio.qt.controller.widgets.library_info_window_controller import LibraryInfoWindow from tagstudio.qt.helpers.custom_runnable import CustomRunnable from tagstudio.qt.helpers.file_deleter import delete_file @@ -79,7 +80,6 @@ from tagstudio.qt.modals.about import AboutModal from tagstudio.qt.modals.build_tag import BuildTagPanel from tagstudio.qt.modals.drop_import import DropImportModal from tagstudio.qt.modals.ffmpeg_checker import FfmpegChecker -from tagstudio.qt.modals.file_extension import FileExtensionModal from tagstudio.qt.modals.fix_dupes import FixDupeFilesModal from tagstudio.qt.modals.fix_unlinked import FixUnlinkedEntriesModal from tagstudio.qt.modals.folders_to_tags import FoldersToTagsModal @@ -175,7 +175,7 @@ class QtDriver(DriverMixin, QObject): tag_manager_panel: PanelModal | None = None color_manager_panel: TagColorManager | None = None - file_extension_panel: PanelModal | None = None + ignore_modal: PanelModal | None = None add_tag_modal: PanelModal | None = None folders_modal: FoldersToTagsModal about_modal: AboutModal @@ -656,27 +656,23 @@ class QtDriver(DriverMixin, QObject): self.splash.finish(self.main_window) - def init_file_extension_manager(self): - """Initialize the File Extension panel.""" - if self.file_extension_panel: + def init_ignore_modal(self): + """Initialize the Ignore Files panel.""" + if self.ignore_modal: with catch_warnings(record=True): - self.main_window.menu_bar.manage_file_ext_action.triggered.disconnect() - self.file_extension_panel.saved.disconnect() - self.file_extension_panel.deleteLater() - self.file_extension_panel = None + self.main_window.menu_bar.ignore_modal_action.triggered.disconnect() + self.ignore_modal.saved.disconnect() + self.ignore_modal.deleteLater() + self.ignore_modal = None - panel = FileExtensionModal(self.lib) - self.file_extension_panel = PanelModal( + panel = IgnoreModal(self.lib) + self.ignore_modal = PanelModal( panel, - Translations["ignore_list.title"], + Translations["menu.edit.ignore_files"], has_save=True, ) - self.file_extension_panel.saved.connect( - lambda: (panel.save(), self.update_browsing_state()) - ) - self.main_window.menu_bar.manage_file_ext_action.triggered.connect( - self.file_extension_panel.show - ) + self.ignore_modal.saved.connect(panel.save) + self.main_window.menu_bar.ignore_modal_action.triggered.connect(self.ignore_modal.show) def show_grid_filenames(self, value: bool): for thumb in self.item_thumbs: @@ -754,7 +750,7 @@ class QtDriver(DriverMixin, QObject): self.main_window.menu_bar.refresh_dir_action.setEnabled(False) self.main_window.menu_bar.tag_manager_action.setEnabled(False) self.main_window.menu_bar.color_manager_action.setEnabled(False) - self.main_window.menu_bar.manage_file_ext_action.setEnabled(False) + self.main_window.menu_bar.ignore_modal_action.setEnabled(False) self.main_window.menu_bar.new_tag_action.setEnabled(False) self.main_window.menu_bar.fix_unlinked_entries_action.setEnabled(False) self.main_window.menu_bar.fix_dupe_files_action.setEnabled(False) @@ -1739,7 +1735,7 @@ class QtDriver(DriverMixin, QObject): ) self.main_window.setAcceptDrops(True) - self.init_file_extension_manager() + self.init_ignore_modal() self.selected.clear() self.set_select_actions_visibility() @@ -1748,7 +1744,7 @@ class QtDriver(DriverMixin, QObject): self.main_window.menu_bar.refresh_dir_action.setEnabled(True) self.main_window.menu_bar.tag_manager_action.setEnabled(True) self.main_window.menu_bar.color_manager_action.setEnabled(True) - self.main_window.menu_bar.manage_file_ext_action.setEnabled(True) + self.main_window.menu_bar.ignore_modal_action.setEnabled(True) self.main_window.menu_bar.new_tag_action.setEnabled(True) self.main_window.menu_bar.fix_unlinked_entries_action.setEnabled(True) self.main_window.menu_bar.fix_dupe_files_action.setEnabled(True) diff --git a/src/tagstudio/qt/view/widgets/ignore_modal_view.py b/src/tagstudio/qt/view/widgets/ignore_modal_view.py new file mode 100644 index 00000000..62afcf52 --- /dev/null +++ b/src/tagstudio/qt/view/widgets/ignore_modal_view.py @@ -0,0 +1,49 @@ +# Copyright (C) 2025 Travis Abendshien (CyanVoxel). +# Licensed under the GPL-3.0 License. +# Created for TagStudio: https://github.com/CyanVoxel/TagStudio + + +import structlog +from PySide6.QtCore import Qt, Signal +from PySide6.QtGui import QFont +from PySide6.QtWidgets import ( + QPlainTextEdit, + QPushButton, + QVBoxLayout, +) + +from tagstudio.core.constants import IGNORE_NAME +from tagstudio.core.library.alchemy.library import Library +from tagstudio.core.library.alchemy.models import Tag +from tagstudio.qt.translations import Translations +from tagstudio.qt.widgets.panel import PanelWidget + +logger = structlog.get_logger(__name__) + + +class IgnoreModalView(PanelWidget): + on_edit = Signal(Tag) + + def __init__(self, library: Library) -> None: + super().__init__() + self.lib = library + + self.setMinimumSize(640, 460) + self.root_layout = QVBoxLayout(self) + self.root_layout.setContentsMargins(6, 0, 6, 0) + self.root_layout.setAlignment(Qt.AlignmentFlag.AlignTop) + + self.text_edit = QPlainTextEdit() + font = QFont() + font.setFamily("monospace") + font.setFixedPitch(True) + font.setStyleHint(QFont.StyleHint.Monospace) + self.text_edit.setFont(font) + + self.open_button = QPushButton( + Translations.format("ignore.open_file", ts_ignore=IGNORE_NAME) + ) + + # Add Widgets to Layout ================================================ + self.root_layout.addWidget(self.text_edit) + self.root_layout.addWidget(self.open_button) diff --git a/src/tagstudio/qt/widgets/preview/file_attributes.py b/src/tagstudio/qt/widgets/preview/file_attributes.py index eb4137d8..1e67ee08 100644 --- a/src/tagstudio/qt/widgets/preview/file_attributes.py +++ b/src/tagstudio/qt/widgets/preview/file_attributes.py @@ -217,7 +217,7 @@ class FileAttributes(QWidget): red = get_ui_color(ColorType.PRIMARY, UiColor.RED) orange = get_ui_color(ColorType.PRIMARY, UiColor.ORANGE) - if Ignore.compiled_patterns and not Ignore.compiled_patterns.match( + if Ignore.compiled_patterns and Ignore.compiled_patterns.match( filepath.relative_to(unwrap(self.library.library_dir)) ): stats_label_text = ( diff --git a/src/tagstudio/qt/widgets/thumb_renderer.py b/src/tagstudio/qt/widgets/thumb_renderer.py index 6823bfc8..16d27b2e 100644 --- a/src/tagstudio/qt/widgets/thumb_renderer.py +++ b/src/tagstudio/qt/widgets/thumb_renderer.py @@ -1436,9 +1436,7 @@ class ThumbRenderer(QObject): if ( image and Ignore.compiled_patterns - and not Ignore.compiled_patterns.match( - filepath.relative_to(self.lib.library_dir) - ) + and Ignore.compiled_patterns.match(filepath.relative_to(self.lib.library_dir)) ): image = render_ignored((adj_size, adj_size), pixel_ratio, image) except TypeError: diff --git a/src/tagstudio/resources/templates/ts_ignore_template.txt b/src/tagstudio/resources/templates/ts_ignore_template.txt new file mode 100644 index 00000000..7152c79c --- /dev/null +++ b/src/tagstudio/resources/templates/ts_ignore_template.txt @@ -0,0 +1,12 @@ +# This is a '.ts_ignore' file for TagStudio. +# +# Basic Usage: +# Ignore filetypes: "*.extension" +# Ignore folders: "/folder_name" +# +# For full usage details, visit https://docs.tagstud.io/utilities/ignore + +# Ignored Filetypes +*.aae +*.json +*.xmp diff --git a/src/tagstudio/resources/templates/ts_ignore_template_blank.txt b/src/tagstudio/resources/templates/ts_ignore_template_blank.txt new file mode 100644 index 00000000..f424b68b --- /dev/null +++ b/src/tagstudio/resources/templates/ts_ignore_template_blank.txt @@ -0,0 +1,9 @@ +# This is a '.ts_ignore' file for TagStudio. +# +# Basic Usage: +# Ignore filetypes: "*.extension" +# Ignore folders: "/folder_name" +# +# For full usage details, visit https://docs.tagstud.io/utilities/ignore + +# Ignored Filetypes diff --git a/src/tagstudio/resources/translations/de.json b/src/tagstudio/resources/translations/de.json index f7d1007b..8c63731e 100644 --- a/src/tagstudio/resources/translations/de.json +++ b/src/tagstudio/resources/translations/de.json @@ -136,11 +136,6 @@ "home.thumbnail_size.medium": "Mittelgroße Vorschau", "home.thumbnail_size.mini": "Mini Vorschau", "home.thumbnail_size.small": "Kleine Vorschau", - "ignore_list.add_extension": "D&ateiendung hinzufügen", - "ignore_list.mode.exclude": "Ausschliessen", - "ignore_list.mode.include": "Einschließen", - "ignore_list.mode.label": "Listen Modus:", - "ignore_list.title": "Dateierweiterungen", "json_migration.checking_for_parity": "Parität wird überprüft...", "json_migration.creating_database_tables": "SQL Datenbank Tabellen werden erstellt...", "json_migration.description": "
Starte den Migrationsprozess der Bibliothek und sehe die Ergebnisse in der Vorschau an. Die migrierte Bibliothek wird nicht verwendet, bis Sie auf \"Migration abschließen\" klicken.

Bibliotheksdaten sollten entweder übereinstimmende Werte oder das Label \"Matched\" besitzen. Werte zu denen keine Übereinstimmungen gefunden werden, werden in Rot dargestellt und erhalten das Symbol \"(!)\".
Der Migrationsprozess kann bei größeren Bibliotheken einige Minuten in Anspruch nehmen.", @@ -192,8 +187,7 @@ "menu.delete_selected_files_plural": "Dateien nach {trash_term} verschieben", "menu.delete_selected_files_singular": "Datei nach {trash_term} verschieben", "menu.edit": "Bearbeiten", - "menu.edit.ignore_list": "Dateien und Verzeichnisse ignorieren", - "menu.edit.manage_file_extensions": "Dateiendungen verwalten", + "menu.edit.ignore_files": "Dateien und Verzeichnisse ignorieren", "menu.edit.manage_tags": "Tags Verwalten", "menu.edit.new_tag": "Neuer &Tag", "menu.file": "Datei", diff --git a/src/tagstudio/resources/translations/en.json b/src/tagstudio/resources/translations/en.json index 11b59878..9cf01257 100644 --- a/src/tagstudio/resources/translations/en.json +++ b/src/tagstudio/resources/translations/en.json @@ -136,11 +136,7 @@ "home.thumbnail_size.mini": "Mini Thumbnails", "home.thumbnail_size.small": "Small Thumbnails", "home.thumbnail_size": "Thumbnail Size", - "ignore_list.add_extension": "&Add Extension", - "ignore_list.mode.exclude": "Exclude", - "ignore_list.mode.include": "Include", - "ignore_list.mode.label": "List Mode:", - "ignore_list.title": "File Extensions", + "ignore.open_file": "Show \"{ts_ignore}\" File on Disk", "json_migration.checking_for_parity": "Checking for Parity...", "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.
", @@ -196,8 +192,7 @@ "menu.delete_selected_files_ambiguous": "Move File(s) to {trash_term}", "menu.delete_selected_files_plural": "Move Files to {trash_term}", "menu.delete_selected_files_singular": "Move File to {trash_term}", - "menu.edit.ignore_list": "Ignore Files and Folders", - "menu.edit.manage_file_extensions": "Manage File Extensions", + "menu.edit.ignore_files": "Ignore Files and Folders", "menu.edit.manage_tags": "Manage Tags", "menu.edit.new_tag": "New &Tag", "menu.edit": "Edit", diff --git a/src/tagstudio/resources/translations/es.json b/src/tagstudio/resources/translations/es.json index 4662be2e..a94b6849 100644 --- a/src/tagstudio/resources/translations/es.json +++ b/src/tagstudio/resources/translations/es.json @@ -136,11 +136,6 @@ "home.thumbnail_size.medium": "Imágenes medianas", "home.thumbnail_size.mini": "Imágenes en miniatura", "home.thumbnail_size.small": "Imágenes pequeñas", - "ignore_list.add_extension": "&Añadir extensión", - "ignore_list.mode.exclude": "Excluir", - "ignore_list.mode.include": "Incluir", - "ignore_list.mode.label": "Modo de lista:", - "ignore_list.title": "Extensiones del archivo", "json_migration.checking_for_parity": "Revisando paridad...", "json_migration.creating_database_tables": "Creando tablas en la base de datos de SQL...", "json_migration.description": "
Inicia y previsualiza el resultado del proceso de migración de la biblioteca. La biblioteca transformada no se utilizará hasta que pulses \"Finalizar migración\".

Los datos de la biblioteca deberían tener valores que concuerdan o disponen de una etiqueta \"Emparejado\". Los valores que no coinciden se mostrarán en rojo y mostrará el símbolo \"(!)\" a su lado.
Este proceso puede tardar hasta varios minutos para bibliotecas de gran tamaño.
", @@ -192,8 +187,7 @@ "menu.delete_selected_files_plural": "Mover archivos a la {trash_term}", "menu.delete_selected_files_singular": "Mover archivo a la {trash_term}", "menu.edit": "Editar", - "menu.edit.ignore_list": "Ignorar archivos y carpetas", - "menu.edit.manage_file_extensions": "Gestionar extensión de archivos", + "menu.edit.ignore_files": "Ignorar archivos y carpetas", "menu.edit.manage_tags": "Gestionar etiquetas", "menu.edit.new_tag": "Nueva &Etiqueta", "menu.file": "&Archivo", diff --git a/src/tagstudio/resources/translations/fil.json b/src/tagstudio/resources/translations/fil.json index 675f2516..1fc271b0 100644 --- a/src/tagstudio/resources/translations/fil.json +++ b/src/tagstudio/resources/translations/fil.json @@ -136,11 +136,6 @@ "home.thumbnail_size.medium": "Bahagyang Thumbnail", "home.thumbnail_size.mini": "Maliliit na Thumbnail", "home.thumbnail_size.small": "Maliit na Thumbnail", - "ignore_list.add_extension": "&Magdagdag ng Extension", - "ignore_list.mode.exclude": "Huwag isama", - "ignore_list.mode.include": "Isama", - "ignore_list.mode.label": "Mode ng Pag-lista:", - "ignore_list.title": "Mga File Extension", "json_migration.checking_for_parity": "Sinusuri para sa pagkakapareho…", "json_migration.creating_database_tables": "Ginagawa ang mga SQL Database Table…", "json_migration.description": "
Simulan at i-preview ang mga resulta ng proseso ng pag-migrate ng library. Hindi gagamitin ang naka-convert na library maliban kung i-click mo ang \"Tapusin ang Migration\".

Dapat ay may mga katumbas na halaga ang data ng library o nagtatampok ng label na \"Tumugugma\". Ang mga value na hindi tumutugma ay ipapakita sa pula at nagtatampok ng \"(!)\" na simbolo sa tabi ng mga ito.
Ang prosesong ito ay maaaring tumagal ng hanggang ilang minuto para sa mas malalaking library.
", @@ -192,8 +187,7 @@ "menu.delete_selected_files_plural": "Ilipat ang Mga File sa {trash_term}", "menu.delete_selected_files_singular": "Ilipat ang File sa {trash_term}", "menu.edit": "I-edit", - "menu.edit.ignore_list": "Huwag Pansinin ang Mga File at Folder", - "menu.edit.manage_file_extensions": "Ipamahala ang Mga File Extension", + "menu.edit.ignore_files": "Huwag Pansinin ang Mga File at Folder", "menu.edit.manage_tags": "Ipamahala ang Mga Tag", "menu.edit.new_tag": "Bagong &Tag", "menu.file": "File", diff --git a/src/tagstudio/resources/translations/fr.json b/src/tagstudio/resources/translations/fr.json index 6bd43341..b85dec2c 100644 --- a/src/tagstudio/resources/translations/fr.json +++ b/src/tagstudio/resources/translations/fr.json @@ -136,11 +136,6 @@ "home.thumbnail_size.medium": "Miniatures Moyennes", "home.thumbnail_size.mini": "Mini Miniatures", "home.thumbnail_size.small": "Petites Miniatures", - "ignore_list.add_extension": "&Ajouter une Extension", - "ignore_list.mode.exclude": "Exclure", - "ignore_list.mode.include": "Inclure", - "ignore_list.mode.label": "Mode de la liste :", - "ignore_list.title": "Extensions de Fichiers", "json_migration.checking_for_parity": "Vérification de la Parité...", "json_migration.creating_database_tables": "Création des Tables de Base de Données SQL...", "json_migration.description": "
Démarrez et prévisualisez les résultats du processus de migration de la bibliothèque. La bibliothèque convertie ne sera utilisée que si vous cliquez sur \"Terminer la migration\".

Les données de la bibliothèque doivent soit avoir des valeurs correspondantes, soit comporter un label \"Matched\". Les valeurs qui ne correspondent pas seront affichées en rouge et comporteront un symbole \"(!)\" à côté d'elles.
Ce processus peut prendre jusqu'à plusieurs minutes pour les bibliothèques plus volumineuses.
", @@ -192,8 +187,7 @@ "menu.delete_selected_files_plural": "Déplacer les Fichiers vers {trash_term}", "menu.delete_selected_files_singular": "Déplacer le Fichier vers {trash_term}", "menu.edit": "Édition", - "menu.edit.ignore_list": "Ignorer les Fichiers et Dossiers", - "menu.edit.manage_file_extensions": "Gérer les extensions de fichier", + "menu.edit.ignore_files": "Ignorer les Fichiers et Dossiers", "menu.edit.manage_tags": "Gérer les Tags", "menu.edit.new_tag": "Nouveaux &Tag", "menu.file": "&Fichier", diff --git a/src/tagstudio/resources/translations/hu.json b/src/tagstudio/resources/translations/hu.json index 8f82afd0..b7a092b2 100644 --- a/src/tagstudio/resources/translations/hu.json +++ b/src/tagstudio/resources/translations/hu.json @@ -136,11 +136,6 @@ "home.thumbnail_size.medium": "Közepes miniatűrök", "home.thumbnail_size.mini": "Pici miniatűrök", "home.thumbnail_size.small": "Kicsi miniatűrök", - "ignore_list.add_extension": "&Kiterjesztés hozzáadása", - "ignore_list.mode.exclude": "Elrejtés", - "ignore_list.mode.include": "Mutatás", - "ignore_list.mode.label": "Listázott elemek módja:", - "ignore_list.title": "Kiterjesztések", "json_migration.checking_for_parity": "Paritás ellenőrzése folyamatban…", "json_migration.creating_database_tables": "SQL-adatbázis táblázatainak létrehozása folyamatban…", "json_migration.description": "
A könyvtárátalakítási folyamat megkezdése és az eredmény előnézete. Az új könyvtár az „Átalakítás befejezése” gomb megnyomásáig nem lesz használatba véve.

A könyvtár adatai változatlanok maradnak vagy egy „Egységesítve” címkével lesznek felruházva. A nem egyező adatok vörösen lesznek megjelenítve és egy „(!)” szimbólummal lesznek ellátva.
Ez a folyamat nagyobb könyvtárak esetén akár több percig is eltarthat.
", @@ -192,8 +187,7 @@ "menu.delete_selected_files_plural": "Fájlok {trash_term} &helyezése", "menu.delete_selected_files_singular": "Fájl {trash_term} &helyezése", "menu.edit": "S&zerkesztés", - "menu.edit.ignore_list": "Fájlok és mappák figyelmen kívül hagyása", - "menu.edit.manage_file_extensions": "&Fájlkiterjesztések kezelése", + "menu.edit.ignore_files": "Fájlok és mappák figyelmen kívül hagyása", "menu.edit.manage_tags": "&Címkék ke&zelése", "menu.edit.new_tag": "Ú&j címke", "menu.file": "&Fájl", diff --git a/src/tagstudio/resources/translations/ja.json b/src/tagstudio/resources/translations/ja.json index 71ca8bb5..1f76be3a 100644 --- a/src/tagstudio/resources/translations/ja.json +++ b/src/tagstudio/resources/translations/ja.json @@ -136,11 +136,6 @@ "home.thumbnail_size.medium": "中サムネイル", "home.thumbnail_size.mini": "極小サムネイル", "home.thumbnail_size.small": "小サムネイル", - "ignore_list.add_extension": "拡張子を追加(&a)", - "ignore_list.mode.exclude": "含めない", - "ignore_list.mode.include": "含める", - "ignore_list.mode.label": "リストのモード:", - "ignore_list.title": "ファイルの拡張子", "json_migration.checking_for_parity": "パリティチェック中...", "json_migration.creating_database_tables": "SQLデータベース テーブルを作成しています...", "json_migration.description": "
ライブラリの移行処理を開始し、結果をプレビューします。変換されたライブラリは、 「移行完了」をクリックしない限り使用されません

ライブラリ データは、値が一致しているか、「一致」ラベルが表示されている必要があります。 値が一致しない場合は赤色で表示され、その横に「(!)」マークが表示されます。
大規模なライブラリの場合、この処理に数分かかることがあります。
", @@ -192,8 +187,7 @@ "menu.delete_selected_files_plural": "ファイルを {trash_term} に移動", "menu.delete_selected_files_singular": "ファイルを {trash_term} に移動", "menu.edit": "編集", - "menu.edit.ignore_list": "ファイルとフォルダを無視", - "menu.edit.manage_file_extensions": "ファイル拡張子の管理", + "menu.edit.ignore_files": "ファイルとフォルダを無視", "menu.edit.manage_tags": "タグの管理", "menu.edit.new_tag": "新しいタグ(&T)", "menu.file": "ファイル(&F)", diff --git a/src/tagstudio/resources/translations/nb_NO.json b/src/tagstudio/resources/translations/nb_NO.json index c2c2395b..d5d818c1 100644 --- a/src/tagstudio/resources/translations/nb_NO.json +++ b/src/tagstudio/resources/translations/nb_NO.json @@ -136,11 +136,6 @@ "home.thumbnail_size.medium": "Medium Store Miniatyrbilder", "home.thumbnail_size.mini": "Bittesmå Miniatyrbilder", "home.thumbnail_size.small": "Små Miniatyrbilder", - "ignore_list.add_extension": "Legg til utvidelse", - "ignore_list.mode.exclude": "Utelat", - "ignore_list.mode.include": "Inkluder", - "ignore_list.mode.label": "Listemodus:", - "ignore_list.title": "Filutvidelse", "json_migration.checking_for_parity": "Sjekker om det stemmer Overens...", "json_migration.creating_database_tables": "Lager SQL-databasetabeller...", "json_migration.description": "
Start og forhåndsvis resultatene av biblioteksmigrasjonsprosessen. Det konverterte biblioteket vil ikke bli brukt med mindre du trykker på \"Fullfør Migrering\".

Biblioteksdata burde enten ha matchende verdier eller ha en \"Matchet\" etikett. Verdier som ikke matcher vil bli vist i rød og ha et \"(!)\" symbol ved siden av dem.
Denne prosessen kan ta opp til flere minutter for større biblioteker
", @@ -192,8 +187,7 @@ "menu.delete_selected_files_plural": "Flytt Filer til {trash_term}", "menu.delete_selected_files_singular": "Flytt Fil til {trash_term}", "menu.edit": "Rediger", - "menu.edit.ignore_list": "Ignorer Filer og Mapper", - "menu.edit.manage_file_extensions": "Administrer Filutvidelser", + "menu.edit.ignore_files": "Ignorer Filer og Mapper", "menu.edit.manage_tags": "Administrer Etiketter", "menu.edit.new_tag": "Ny &Etikett", "menu.file": "Fil", diff --git a/src/tagstudio/resources/translations/nl.json b/src/tagstudio/resources/translations/nl.json index b4d9293c..58bb7858 100644 --- a/src/tagstudio/resources/translations/nl.json +++ b/src/tagstudio/resources/translations/nl.json @@ -75,7 +75,6 @@ "home.thumbnail_size.medium": "Gemiddelde Minituren", "home.thumbnail_size.mini": "Mini Miniaturen", "home.thumbnail_size.small": "Kleine Miniaturen", - "ignore_list.mode.exclude": "Uitsluiten", "json_migration.finish_migration": "Migratie Afronden", "json_migration.heading.aliases": "Aliassen:", "json_migration.heading.colors": "Kleuren:", @@ -93,7 +92,7 @@ "menu.delete_selected_files_plural": "Bestanden verplaatsen naar {trash_term}", "menu.delete_selected_files_singular": "Bestand verplaatsen naar {trash_term}", "menu.edit": "Aanpassen", - "menu.edit.ignore_list": "Bestanden en Mappen Negeren", + "menu.edit.ignore_files": "Bestanden en Mappen Negeren", "menu.edit.manage_tags": "Labels Beheren", "menu.edit.new_tag": "Nieuw &Label", "menu.file": "&Bestand", diff --git a/src/tagstudio/resources/translations/pl.json b/src/tagstudio/resources/translations/pl.json index d0ed6b07..bdfa9294 100644 --- a/src/tagstudio/resources/translations/pl.json +++ b/src/tagstudio/resources/translations/pl.json @@ -136,11 +136,6 @@ "home.thumbnail_size.medium": "Średnie miniaturki", "home.thumbnail_size.mini": "Mini miniaturki", "home.thumbnail_size.small": "Małe miniaturki", - "ignore_list.add_extension": "&Dodaj rozszerzenie", - "ignore_list.mode.exclude": "Wyklucz", - "ignore_list.mode.include": "Uwzględnij", - "ignore_list.mode.label": "Tryb listy:", - "ignore_list.title": "Rozszerzenia pliku", "json_migration.checking_for_parity": "Sprawdzanie zgodności...", "json_migration.creating_database_tables": "Tworzenie tabelek bazy danych SQL...", "json_migration.discrepancies_found": "Znaleziono niezgodności biblioteki", @@ -186,8 +181,7 @@ "menu.delete_selected_files_plural": "Przenieś pliki do {trash_term}", "menu.delete_selected_files_singular": "Przenieś plik do {trash_term}", "menu.edit": "Edytuj", - "menu.edit.ignore_list": "Ignoruj pliki i foldery", - "menu.edit.manage_file_extensions": "Zarządzaj rozszerzeniami plików", + "menu.edit.ignore_files": "Ignoruj pliki i foldery", "menu.edit.manage_tags": "Zarządzaj tagami", "menu.edit.new_tag": "Nowy &Tag", "menu.file": "&Plik", diff --git a/src/tagstudio/resources/translations/pt.json b/src/tagstudio/resources/translations/pt.json index c24a54e1..4633fe77 100644 --- a/src/tagstudio/resources/translations/pt.json +++ b/src/tagstudio/resources/translations/pt.json @@ -134,11 +134,6 @@ "home.thumbnail_size.medium": "Miniaturas Médias", "home.thumbnail_size.mini": "Miniaturas Mini", "home.thumbnail_size.small": "Miniaturas Pequenas", - "ignore_list.add_extension": "&Adicionar Extensão", - "ignore_list.mode.exclude": "Excluir", - "ignore_list.mode.include": "Incluir", - "ignore_list.mode.label": "Modo:", - "ignore_list.title": "Extensões de Ficheiro", "json_migration.creating_database_tables": "A criar Tabelas de Banco de Dados SQL...", "json_migration.discrepancies_found": "Encontradas Discrepâncias na biblioteca", "json_migration.discrepancies_found.description": "Discrepâncias foram encontradas entre os ficheiros de Biblioteca originais e os convertidos. Por favor, revise e escolha continuar com a migração ou cancelar.", @@ -182,8 +177,6 @@ "menu.delete_selected_files_plural": "Mover Ficheiros para {trash_term}", "menu.delete_selected_files_singular": "Mover Ficheiro para {trash_term}", "menu.edit": "Editar", - "menu.edit.ignore_list": "Ignorar Ficheiros e Pastas", - "menu.edit.manage_file_extensions": "Gerir Extensões de Ficheiro", "menu.edit.manage_tags": "Gerir Tags", "menu.edit.new_tag": "Nova &Tag", "menu.file": "&Ficheiro", diff --git a/src/tagstudio/resources/translations/pt_BR.json b/src/tagstudio/resources/translations/pt_BR.json index f7f00fed..98389fe4 100644 --- a/src/tagstudio/resources/translations/pt_BR.json +++ b/src/tagstudio/resources/translations/pt_BR.json @@ -129,11 +129,6 @@ "home.thumbnail_size.medium": "Miniaturas Médias", "home.thumbnail_size.mini": "Miniaturas Mini", "home.thumbnail_size.small": "Miniaturas Pequenas", - "ignore_list.add_extension": "&Adicionar Extensão", - "ignore_list.mode.exclude": "Excluir", - "ignore_list.mode.include": "Incluir", - "ignore_list.mode.label": "Modo:", - "ignore_list.title": "Extensões de Arquivo", "json_migration.creating_database_tables": "Criando Tabelas de Banco de Dados SQL...", "json_migration.discrepancies_found": "Encontradas Discrepâncias na biblioteca", "json_migration.discrepancies_found.description": "Discrepâncias foram encontradas entre os arquivos de Biblioteca originais e os convertidos. Por favor, revise e escolha continuar com a migração ou cancelar.", @@ -174,8 +169,7 @@ "menu.delete_selected_files_plural": "Mover Arquivos para {trash_term}", "menu.delete_selected_files_singular": "Mover Arquivo para {trash_term}", "menu.edit": "Editar", - "menu.edit.ignore_list": "Ignorar Arquivos e Pastas", - "menu.edit.manage_file_extensions": "Gerenciar Extensões de Arquivo", + "menu.edit.ignore_files": "Ignorar Arquivos e Pastas", "menu.edit.manage_tags": "Gerenciar Tags", "menu.edit.new_tag": "Nova &Tag", "menu.file": "&Arquivo", diff --git a/src/tagstudio/resources/translations/qpv.json b/src/tagstudio/resources/translations/qpv.json index 59f3fa08..c6a73ca0 100644 --- a/src/tagstudio/resources/translations/qpv.json +++ b/src/tagstudio/resources/translations/qpv.json @@ -136,11 +136,6 @@ "home.thumbnail_size.medium": "Mellan risonen", "home.thumbnail_size.mini": "Chisai risonen", "home.thumbnail_size.small": "Chisaidai risonen", - "ignore_list.add_extension": "&Nasii taksanting", - "ignore_list.mode.exclude": "Ansenai", - "ignore_list.mode.include": "Anse", - "ignore_list.mode.label": "Tumam fal:", - "ignore_list.title": "Mlafufal", "json_migration.checking_for_parity": "Taskama per chigauzma ima...", "json_migration.creating_database_tables": "Maha tumam na SQL Database ima...", "json_migration.description": "
Hadji au de se shiruzma fu", @@ -186,8 +181,7 @@ "menu.delete_selected_files_plural": "Ugoki mlafu {trash_term} made", "menu.delete_selected_files_singular": "Ugoki mlafu {trash_term} made", "menu.edit": "Kawari", - "menu.edit.ignore_list": "Nai shuchu na mlafu au mlafukaban", - "menu.edit.manage_file_extensions": "Jewalt mlafufal", + "menu.edit.ignore_files": "Nai shuchu na mlafu au mlafukaban", "menu.edit.manage_tags": "Jewalt festaretol", "menu.edit.new_tag": "Neo &festaretol", "menu.file": "&Mlafu", diff --git a/src/tagstudio/resources/translations/ru.json b/src/tagstudio/resources/translations/ru.json index 3b93121f..bbce81eb 100644 --- a/src/tagstudio/resources/translations/ru.json +++ b/src/tagstudio/resources/translations/ru.json @@ -136,11 +136,6 @@ "home.thumbnail_size.medium": "Средние иконки", "home.thumbnail_size.mini": "Крохотные иконки", "home.thumbnail_size.small": "Маленькие иконки", - "ignore_list.add_extension": "&Добавить расширение", - "ignore_list.mode.exclude": "Исключить", - "ignore_list.mode.include": "Включить", - "ignore_list.mode.label": "Тип списка:", - "ignore_list.title": "Расширения файлов", "json_migration.checking_for_parity": "Проверка целостности...", "json_migration.creating_database_tables": "Создание таблиц базы данных SQL...", "json_migration.description": "
Начните и просмотрите результаты процесса миграции библиотеки. Конвертированная библиотека не будет использоваться, если вы не нажмете \"Завершить миграцию\". Данные библиотеки должны либо иметь совпадающие значения, либо содержать метку \"Совпало\". Значения, которые не совпадают, будут отображаться красным цветом и сопровождаться символом \"(!)\" рядом с ними.
Этот процесс может занять несколько минут для больших библиотек.
", @@ -192,8 +187,7 @@ "menu.delete_selected_files_plural": "Перемеcтить файлы в {trash_term}", "menu.delete_selected_files_singular": "Перемеcтить файл в {trash_term}", "menu.edit": "Редактировать", - "menu.edit.ignore_list": "Игнорировать файлы и папки", - "menu.edit.manage_file_extensions": "Управлять расширениями файлов", + "menu.edit.ignore_files": "Игнорировать файлы и папки", "menu.edit.manage_tags": "Управлять тегами", "menu.edit.new_tag": "Новый &тег", "menu.file": "&Файл", diff --git a/src/tagstudio/resources/translations/sv.json b/src/tagstudio/resources/translations/sv.json index e992c7b1..5d81b899 100644 --- a/src/tagstudio/resources/translations/sv.json +++ b/src/tagstudio/resources/translations/sv.json @@ -61,10 +61,6 @@ "home.search_entries": "Sök poster", "home.search_tags": "Sök etikett", "home.thumbnail_size": "Miniatyrbildsstorlek", - "ignore_list.add_extension": "Lägg till tillägg", - "ignore_list.mode.exclude": "Exkludera", - "ignore_list.mode.include": "Inkludera", - "ignore_list.title": "Filnamnstillägg", "library.field.add": "Lägg till fält", "library.field.remove": "Ta bort fält", "library.missing": "Platsen saknas", diff --git a/src/tagstudio/resources/translations/ta.json b/src/tagstudio/resources/translations/ta.json index 43fc8190..00d2bd9b 100644 --- a/src/tagstudio/resources/translations/ta.json +++ b/src/tagstudio/resources/translations/ta.json @@ -136,11 +136,6 @@ "home.thumbnail_size.medium": "நடுத்தர சிறு உருவங்கள்", "home.thumbnail_size.mini": "மினி சிறு உருவங்கள்", "home.thumbnail_size.small": "சிறிய சிறு உருவங்கள்", - "ignore_list.add_extension": "& நீட்டிப்பு சேர்க்கவும்", - "ignore_list.mode.exclude": "தவிர்", - "ignore_list.mode.include": "உள்ளடக்கு", - "ignore_list.mode.label": "பட்டியல் பயன்முறை:", - "ignore_list.title": "கோப்பு நீட்டிப்புகள்", "json_migration.checking_for_parity": "சமத்துவத்தை சரிபார்க்கிறது ...", "json_migration.creating_database_tables": "கவிமொ தரவுத்தள அட்டவணைகளை உருவாக்குதல் ...", "json_migration.description": "
நூலக இடம்பெயர்வு செயல்முறையின் முடிவுகளைத் தொடங்கவும் முன்னோட்டமிடவும். மாற்றப்பட்ட நூலகம் இல்லை நீங்கள் \"இடம்பெயர்வு முடிக்கவும்\" என்பதைக் சொடுக்கு செய்யாவிட்டால் பயன்படுத்தப்படும்.

நூலகத் தரவுகள் பொருந்தக்கூடிய மதிப்புகளைக் கொண்டிருக்க வேண்டும் அல்லது \"பொருந்திய\" லேபிளைக் கொண்டிருக்க வேண்டும். பொருந்தாத மதிப்புகள் சிவப்பு நிறத்தில் காண்பிக்கப்படும் மற்றும் அவர்களுக்கு அடுத்த \" (!) \" சின்னத்தைக் கொண்டிருக்கும்.
இந்தச் செயல்முறை பெரிய நூலகங்களுக்குப் பல நிமிடங்கள்வரை ஆகலாம்.
", @@ -192,8 +187,7 @@ "menu.delete_selected_files_plural": "கோப்புகளை {trash_term} பெறுநர் க்கு நகர்த்தவும்", "menu.delete_selected_files_singular": "கோப்பை {trash_term} பெறுநர் க்கு நகர்த்தவும்", "menu.edit": "திருத்து", - "menu.edit.ignore_list": "கோப்புகள் மற்றும் கோப்புறைகளை புறக்கணிக்கவும்", - "menu.edit.manage_file_extensions": "கோப்பு நீட்டிப்புகளை நிர்வகிக்கவும்", + "menu.edit.ignore_files": "கோப்புகள் மற்றும் கோப்புறைகளை புறக்கணிக்கவும்", "menu.edit.manage_tags": "குறிச்சொற்களை நிர்வகிக்கவும்", "menu.edit.new_tag": "புதிய & குறிச்சொல்", "menu.file": "கோப்பு (&f)", diff --git a/src/tagstudio/resources/translations/tok.json b/src/tagstudio/resources/translations/tok.json index e2658e66..79831895 100644 --- a/src/tagstudio/resources/translations/tok.json +++ b/src/tagstudio/resources/translations/tok.json @@ -132,11 +132,6 @@ "home.thumbnail_size.medium": "sitelen lili meso", "home.thumbnail_size.mini": "sitelen lili pi lili mute", "home.thumbnail_size.small": "sitelen lili pi lili meso", - "ignore_list.add_extension": "o p&ana e nimi anpa", - "ignore_list.mode.exclude": "o kepeken ala", - "ignore_list.mode.include": "o kepeken", - "ignore_list.mode.label": "nasin kulupu:", - "ignore_list.title": "nimi lon nimi ijo anpa", "json_migration.checking_for_parity": "mi alasa e nasin tu...", "json_migration.description": "
o open e tawa tomo o lukin e pini. sina pilin ala e \"o pini e tawa\" la, mi kepeken ala e tomo ante.

sona tomo o jo e nanpa sama anu toki \"sama\" la ale li pona. nanpa ante li loje li jo e sitelen \"(!)\" lon poka ona.
tomo li suli la pali ni li lanpan e tenpo mute.
", "json_migration.discrepancies_found": "mi lukin e ike pi tomo sina", @@ -186,8 +181,7 @@ "menu.delete_selected_files_plural": "o tawa e lipu tawa {trash_term}", "menu.delete_selected_files_singular": "o tawa e lipu tawa {trash_term}", "menu.edit": "o ante", - "menu.edit.ignore_list": "o lukin ala e ijo ni", - "menu.edit.manage_file_extensions": "o lawa e namako lipu", + "menu.edit.ignore_files": "o lukin ala e ijo ni", "menu.edit.manage_tags": "o lawa e poki", "menu.edit.new_tag": "poki sin (&T)", "menu.file": "ijo (&F)", diff --git a/src/tagstudio/resources/translations/tr.json b/src/tagstudio/resources/translations/tr.json index e2c801f8..a775143d 100644 --- a/src/tagstudio/resources/translations/tr.json +++ b/src/tagstudio/resources/translations/tr.json @@ -132,11 +132,6 @@ "home.thumbnail_size.medium": "Orta Boyut Önizlemeler", "home.thumbnail_size.mini": "Minicik Önizlemeler", "home.thumbnail_size.small": "Küçük Önizlemeler", - "ignore_list.add_extension": "&Dosya Uzantısı Ekle", - "ignore_list.mode.exclude": "Hariç Tut", - "ignore_list.mode.include": "Dahil Et", - "ignore_list.mode.label": "Listeleme Modu:", - "ignore_list.title": "Dosya Uzantıları", "json_migration.checking_for_parity": "Uyumluluk Kontrol Ediliyor...", "json_migration.creating_database_tables": "SQL Veritabanı Tabloları Oluşturuluyor...", "json_migration.description": "
Kütüphane dönüştürme işlemini başlatın ve önizleyin. Dönüştürülen kütüphane, \"Dönüştürmeyi Bitir\"e tıklamadığınız sürece kullanılmayacaktır.

Kütüphane verileri ya eşleşen değerlere sahip olmalı ya da \"Eşleşti\" etiketi içermelidir. Eşleşmeyen değerler kırmızı renkte gösterilecek ve yanlarında \"(!)\" sembolü bulunacaktır.
Bu işlem, daha büyük kütüphaneler için birkaç dakika kadar sürebilir.
", @@ -187,8 +182,7 @@ "menu.delete_selected_files_plural": "Dosyaları {trash_term} Klasörüne Taşı", "menu.delete_selected_files_singular": "Dosyayı {trash_term} Klasörüne Taşı", "menu.edit": "Düzenle", - "menu.edit.ignore_list": "Dosyaları ve Klasörleri Yoksay", - "menu.edit.manage_file_extensions": "Dosya Uzantılarını Yönet", + "menu.edit.ignore_files": "Dosyaları ve Klasörleri Yoksay", "menu.edit.manage_tags": "Etiketleri Yönet", "menu.edit.new_tag": "Yeni &Etiket", "menu.file": "&Dosya", diff --git a/src/tagstudio/resources/translations/zh_Hans.json b/src/tagstudio/resources/translations/zh_Hans.json index e45b3698..0b2fc65e 100644 --- a/src/tagstudio/resources/translations/zh_Hans.json +++ b/src/tagstudio/resources/translations/zh_Hans.json @@ -136,11 +136,6 @@ "home.thumbnail_size.medium": "中等缩略图", "home.thumbnail_size.mini": "迷你缩略图", "home.thumbnail_size.small": "小缩略图", - "ignore_list.add_extension": "添加插件(&a)", - "ignore_list.mode.exclude": "排除", - "ignore_list.mode.include": "包含", - "ignore_list.mode.label": "列表模式:", - "ignore_list.title": "文件格式", "json_migration.checking_for_parity": "正在校验奇偶位...", "json_migration.creating_database_tables": "正在建立SQL数据库表...", "json_migration.description": "
开始并预览资源库迁移结果。仓库的转换不会立即生效,除非您点击\"完成迁移\"按钮。

仓库数据应具有匹配值或带有\"已匹配\"标签。不匹配的值将显示为红色,并带有\"(!)\"警示符号。
大型仓库的迁移过程可能需要数分钟。
", @@ -192,8 +187,7 @@ "menu.delete_selected_files_plural": "移动文件到 {trash_term}", "menu.delete_selected_files_singular": "移动文件到 {trash_term}", "menu.edit": "编辑", - "menu.edit.ignore_list": "忽略文件和文件夹", - "menu.edit.manage_file_extensions": "文件扩展名管理", + "menu.edit.ignore_files": "忽略文件和文件夹", "menu.edit.manage_tags": "标签管理", "menu.edit.new_tag": "新标签(&t)", "menu.file": "文件(&f)", diff --git a/src/tagstudio/resources/translations/zh_Hant.json b/src/tagstudio/resources/translations/zh_Hant.json index dbebc212..cfa6eb93 100644 --- a/src/tagstudio/resources/translations/zh_Hant.json +++ b/src/tagstudio/resources/translations/zh_Hant.json @@ -136,11 +136,6 @@ "home.thumbnail_size.mini": "迷你縮圖", "home.thumbnail_size.small": "小縮圖", "home.thumbnail_size": "縮圖大小", - "ignore_list.add_extension": "新增外加套件 (&A)", - "ignore_list.mode.exclude": "排除", - "ignore_list.mode.include": "包含", - "ignore_list.mode.label": "清單模式:", - "ignore_list.title": "檔案副檔名", "json_migration.checking_for_parity": "正在檢查一致性...", "json_migration.creating_database_tables": "正在建立資料庫表格...", "json_migration.description": "
開啟並預覽文件庫遷移過程。除非您按下「完成遷移」,否則被遷移的文件庫不會被使用。

文件庫資料應該是一致的或者要有個「已一致」標籤。不一致的資料會以紅色顯示並會有「(!)」標示在旁邊。
對於較大的文件庫,這個過程可能會花到幾分鐘以上。
", @@ -191,8 +186,7 @@ "menu.delete_selected_files_ambiguous": "移動檔案至「{trash_term}」", "menu.delete_selected_files_plural": "移動多個檔案至「{trash_term}」", "menu.delete_selected_files_singular": "移動檔案至「{trash_term}」", - "menu.edit.ignore_list": "忽略檔案和資料夾", - "menu.edit.manage_file_extensions": "管理檔案副檔名", + "menu.edit.ignore_files": "忽略檔案和資料夾", "menu.edit.manage_tags": "管理標籤", "menu.edit.new_tag": "新增標籤 (&N)", "menu.edit": "編輯", diff --git a/tests/qt/test_file_path_options.py b/tests/qt/test_file_path_options.py index 36e5c31f..d9bbcf30 100644 --- a/tests/qt/test_file_path_options.py +++ b/tests/qt/test_file_path_options.py @@ -134,7 +134,7 @@ def test_title_update( menu_bar = QMenuBar() qt_driver.main_window.menu_bar.open_recent_library_menu = QMenu(menu_bar) - qt_driver.main_window.menu_bar.manage_file_ext_action = QAction(menu_bar) + qt_driver.main_window.menu_bar.ignore_modal_action = QAction(menu_bar) qt_driver.main_window.menu_bar.save_library_backup_action = QAction(menu_bar) qt_driver.main_window.menu_bar.close_library_action = QAction(menu_bar) qt_driver.main_window.menu_bar.refresh_dir_action = QAction(menu_bar) diff --git a/tests/test_library.py b/tests/test_library.py index edade1b2..26f34f23 100644 --- a/tests/test_library.py +++ b/tests/test_library.py @@ -178,27 +178,6 @@ def test_remove_tag(library: Library, generate_tag: Callable[..., Tag]): assert len(library.tags) == tag_count - 1 -@pytest.mark.parametrize("is_exclude", [True, False]) -def test_search_filter_extensions(library: Library, is_exclude: bool): - # Given - entries = list(library.all_entries()) - assert len(entries) == 2, entries - - library.set_prefs(LibraryPrefs.IS_EXCLUDE_LIST, is_exclude) - library.set_prefs(LibraryPrefs.EXTENSION_LIST, ["md"]) - - # When - results = library.search_library(BrowsingState.show_all(), page_size=500) - entries = library.get_entries(results.ids) - - # Then - assert results.total_count == 1 - assert len(results) == 1 - - entry = entries[0] - assert (entry.path.suffix == ".txt") == is_exclude - - def test_search_library_case_insensitive(library: Library): # Given entries = list(library.all_entries(with_joins=True)) diff --git a/tests/test_search.py b/tests/test_search.py index e85e19b8..79812dfa 100644 --- a/tests/test_search.py +++ b/tests/test_search.py @@ -23,11 +23,11 @@ def verify_count(lib: Library, query: str, count: int): @pytest.mark.parametrize( ["query", "count"], [ - ("", 31), - ("path:*", 31), + ("", 32), + ("path:*", 32), ("path:*inherit*", 24), ("path:*comp*", 5), - ("special:untagged", 2), + ("special:untagged", 3), ("filetype:png", 25), ("filetype:jpg", 6), ("filetype:'jpg'", 6), @@ -89,22 +89,22 @@ def test_or(search_library: Library, query: str, count: int): @pytest.mark.parametrize( ["query", "count"], [ - ("not unexistant", 31), + ("not unexistant", 32), ("not path:*", 0), - ("not not path:*", 31), + ("not not path:*", 32), ("not special:untagged", 29), - ("not filetype:png", 6), - ("not filetype:jpg", 25), - ("not tag_id:1011", 26), - ("not tag_id:1038", 20), - ("not green", 26), + ("not filetype:png", 7), + ("not filetype:jpg", 26), + ("not tag_id:1011", 27), + ("not tag_id:1038", 21), + ("not green", 27), ("tag:favorite", 0), - ("not circle", 20), - ("not tag:square", 20), + ("not circle", 21), + ("not tag:square", 21), ("circle and not square", 6), ("not circle and square", 6), - ("special:untagged or not filetype:jpg", 25), - ("not square or green", 22), + ("special:untagged or not filetype:jpg", 26), + ("not square or green", 23), ], ) def test_not(search_library: Library, query: str, count: int): @@ -118,7 +118,7 @@ def test_not(search_library: Library, query: str, count: int): ("(((tag_id:1041)))", 11), ("not (not tag_id:1041)", 11), ("((circle) and (not square))", 6), - ("(not ((square) OR (green)))", 17), + ("(not ((square) OR (green)))", 18), ("filetype:png and (tag:square or green)", 12), ], )