mirror of
https://github.com/TagStudioDev/TagStudio.git
synced 2026-01-28 22:01:24 +00:00
feat: replace extension exclusion system with .ts_ignore (#1046)
* feat: replace extension exclusion with ts_ignore
This commit is contained in:
committed by
GitHub
parent
44c7d223ff
commit
8e1ae81ec9
@@ -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
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
|
||||
49
src/tagstudio/qt/view/widgets/ignore_modal_view.py
Normal file
49
src/tagstudio/qt/view/widgets/ignore_modal_view.py
Normal file
@@ -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)
|
||||
@@ -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 = (
|
||||
|
||||
@@ -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:
|
||||
|
||||
12
src/tagstudio/resources/templates/ts_ignore_template.txt
Normal file
12
src/tagstudio/resources/templates/ts_ignore_template.txt
Normal file
@@ -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
|
||||
@@ -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
|
||||
@@ -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": "<br>Starte den Migrationsprozess der Bibliothek und sehe die Ergebnisse in der Vorschau an. Die migrierte Bibliothek wird <i>nicht</i> verwendet, bis Sie auf \"Migration abschließen\" klicken.<br><br>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 \"<b>(!)</b>\".<br><center<i>Der Migrationsprozess kann bei größeren Bibliotheken einige Minuten in Anspruch nehmen.</i></center>",
|
||||
@@ -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",
|
||||
|
||||
@@ -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": "<br>Start and preview the results of the library migration process. The converted library will <i>not</i> be used unless you click \"Finish Migration\". <br><br>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 \"<b>(!)</b>\" symbol next to them.<br><center><i>This process may take up to several minutes for larger libraries.</i></center>",
|
||||
@@ -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",
|
||||
|
||||
@@ -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": "<br>Inicia y previsualiza el resultado del proceso de migración de la biblioteca. La biblioteca transformada <i>no</i> se utilizará hasta que pulses \"Finalizar migración\". <br><br>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 \"<b>(!)</b>\" a su lado.<br><center><i>Este proceso puede tardar hasta varios minutos para bibliotecas de gran tamaño.</i></center>",
|
||||
@@ -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",
|
||||
|
||||
@@ -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": "<br>Simulan at i-preview ang mga resulta ng proseso ng pag-migrate ng library. <i>Hindi</i> gagamitin ang naka-convert na library maliban kung i-click mo ang \"Tapusin ang Migration\". <br><br>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 \"<b>(!)</b>\" na simbolo sa tabi ng mga ito.<br><center><i>Ang prosesong ito ay maaaring tumagal ng hanggang ilang minuto para sa mas malalaking library.</i></center>",
|
||||
@@ -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",
|
||||
|
||||
@@ -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": "<br>Démarrez et prévisualisez les résultats du processus de migration de la bibliothèque. La bibliothèque convertie <i>ne</i> sera utilisée que si vous cliquez sur \"Terminer la migration\". <br><br>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 \"<b>(!)</b>\" à côté d'elles.<br><center><i>Ce processus peut prendre jusqu'à plusieurs minutes pour les bibliothèques plus volumineuses.</i></center>",
|
||||
@@ -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",
|
||||
|
||||
@@ -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": "<br>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 <i>nem</i> lesz használatba véve.<br><br>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 „<b>(!)</b>” szimbólummal lesznek ellátva.<br><center></i>Ez a folyamat nagyobb könyvtárak esetén akár több percig is eltarthat.</i><center>",
|
||||
@@ -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",
|
||||
|
||||
@@ -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": "<br>ライブラリの移行処理を開始し、結果をプレビューします。変換されたライブラリは、 「移行完了」をクリックしない限り<i>使用されません</i>。<br><br>ライブラリ データは、値が一致しているか、「一致」ラベルが表示されている必要があります。 値が一致しない場合は赤色で表示され、その横に「<b>(!)</b>」マークが表示されます。<br><center><i>大規模なライブラリの場合、この処理に数分かかることがあります。</i></center>",
|
||||
@@ -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)",
|
||||
|
||||
@@ -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": "<br>Start og forhåndsvis resultatene av biblioteksmigrasjonsprosessen. Det konverterte biblioteket vil <i>ikke</i> bli brukt med mindre du trykker på \"Fullfør Migrering\". <br><br>Biblioteksdata burde enten ha matchende verdier eller ha en \"Matchet\" etikett. Verdier som ikke matcher vil bli vist i rød og ha et \"<b>(!)</b>\" symbol ved siden av dem.<br><center><i>Denne prosessen kan ta opp til flere minutter for større biblioteker</i></center>",
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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": "<br>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",
|
||||
|
||||
@@ -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": "<br>Начните и просмотрите результаты процесса миграции библиотеки. Конвертированная библиотека <i>не</i> будет использоваться, если вы не нажмете \"Завершить миграцию\". Данные библиотеки должны либо иметь совпадающие значения, либо содержать метку \"Совпало\". Значения, которые не совпадают, будут отображаться красным цветом и сопровождаться символом \"<b>(!)</b>\" рядом с ними. <br><center><i>Этот процесс может занять несколько минут для больших библиотек.</i></center>",
|
||||
@@ -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": "&Файл",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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": "<br> நூலக இடம்பெயர்வு செயல்முறையின் முடிவுகளைத் தொடங்கவும் முன்னோட்டமிடவும். மாற்றப்பட்ட நூலகம் <i> இல்லை </i> நீங்கள் \"இடம்பெயர்வு முடிக்கவும்\" என்பதைக் சொடுக்கு செய்யாவிட்டால் பயன்படுத்தப்படும். <br> <br> நூலகத் தரவுகள் பொருந்தக்கூடிய மதிப்புகளைக் கொண்டிருக்க வேண்டும் அல்லது \"பொருந்திய\" லேபிளைக் கொண்டிருக்க வேண்டும். பொருந்தாத மதிப்புகள் சிவப்பு நிறத்தில் காண்பிக்கப்படும் மற்றும் அவர்களுக்கு அடுத்த \"<b> (!) </b>\" சின்னத்தைக் கொண்டிருக்கும். <br> <center> <i> இந்தச் செயல்முறை பெரிய நூலகங்களுக்குப் பல நிமிடங்கள்வரை ஆகலாம்.</i></center>",
|
||||
@@ -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)",
|
||||
|
||||
@@ -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": "<br>o open e tawa tomo o lukin e pini. sina pilin ala e \"o pini e tawa\" la, mi kepeken <i>ala</i> e tomo ante. <br><br>sona tomo o jo e nanpa sama anu toki \"sama\" la ale li pona. nanpa ante li loje li jo e sitelen \"<b>(!)</b>\" lon poka ona.<br><center><i>tomo li suli la pali ni li lanpan e tenpo mute.</i></center>",
|
||||
"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)",
|
||||
|
||||
@@ -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": "<br>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 <i>kullanılmayacaktır</i>. <br><br>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 \"<b>(!)</b>\" sembolü bulunacaktır.<br><center><i>Bu işlem, daha büyük kütüphaneler için birkaç dakika kadar sürebilir.</i></center>",
|
||||
@@ -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",
|
||||
|
||||
@@ -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": "<br>开始并预览资源库迁移结果。仓库的转换<i>不会</i>立即生效,除非您点击\"完成迁移\"按钮。<br><br>仓库数据应具有匹配值或带有\"已匹配\"标签。不匹配的值将显示为红色,并带有\"<b>(!)</b>\"警示符号。<br><center><i>大型仓库的迁移过程可能需要数分钟。</i></center>",
|
||||
@@ -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)",
|
||||
|
||||
@@ -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": "<br>開啟並預覽文件庫遷移過程。除非您按下「完成遷移」,否則被遷移的文件庫<i>不會</i>被使用。<br><br>文件庫資料應該是一致的或者要有個「已一致」標籤。不一致的資料會以紅色顯示並會有「<b>(!)</b>」標示在旁邊。<br><center><i>對於較大的文件庫,這個過程可能會花到幾分鐘以上。</i></center>",
|
||||
@@ -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": "編輯",
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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),
|
||||
],
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user