diff --git a/STYLE.md b/STYLE.md index 81e0cf54..3c4fc0e1 100644 --- a/STYLE.md +++ b/STYLE.md @@ -21,11 +21,11 @@ As of writing this section, the QT part of the code base is quite unstructured a The general structure of the QT code base should look like this: ``` qt -├── controller +├── controllers │ ├── widgets │ │ └── preview_panel_controller.py │ └── main_window_controller.py -├── view +├── views │ ├── widgets │ │ └── preview_panel_view.py │ └── main_window_view.py @@ -33,7 +33,7 @@ qt └── mixed.py ``` -In this structure there are the `view` and `controller` sub-directories. They have the exact same structure and for every `_view.py` there is a `_controller.py` at the same location in the other subdirectory and vice versa. +In this structure there are the `views` and `controllers` sub-directories. They have the exact same structure and for every `_view.py` there is a `_controller.py` at the same location in the other subdirectory and vice versa. Typically the classes should look like this: ```py diff --git a/pyproject.toml b/pyproject.toml index 31210019..67286a68 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -85,7 +85,7 @@ ignore_errors = true qt_api = "pyside6" [tool.pyright] -ignore = ["src/tagstudio/qt/helpers/vendored/pydub/", ".venv/**"] +ignore = ["src/tagstudio/qt/previews/vendored/pydub/", ".venv/**"] include = ["src/tagstudio", "tests"] reportAny = false reportIgnoreCommentWithoutRule = false @@ -109,7 +109,7 @@ ignore = ["D100", "D101", "D102", "D103", "D104", "D105", "D106", "D107"] [tool.ruff.lint.per-file-ignores] "tests/**" = ["D", "E402"] -"src/tagstudio/qt/helpers/vendored/**" = ["B", "E", "N", "UP", "SIM115"] +"src/tagstudio/qt/previews/vendored/**" = ["B", "E", "N", "UP", "SIM115"] [tool.ruff.lint.pydocstyle] convention = "google" diff --git a/src/tagstudio/core/driver.py b/src/tagstudio/core/driver.py index 0a59a98e..4343054d 100644 --- a/src/tagstudio/core/driver.py +++ b/src/tagstudio/core/driver.py @@ -5,14 +5,16 @@ from PySide6.QtCore import QSettings from tagstudio.core.constants import TS_FOLDER_NAME from tagstudio.core.enums import SettingItems -from tagstudio.core.global_settings import GlobalSettings from tagstudio.core.library.alchemy.library import LibraryStatus +from tagstudio.qt.global_settings import GlobalSettings logger = structlog.get_logger(__name__) class DriverMixin: cached_values: QSettings + # TODO: GlobalSettings has become closely tied to Qt. + # Should there be a base Settings class? settings: GlobalSettings def evaluate_path(self, open_path: str | None) -> LibraryStatus: diff --git a/src/tagstudio/core/field_template.py b/src/tagstudio/core/field_template.py deleted file mode 100644 index 8c42073e..00000000 --- a/src/tagstudio/core/field_template.py +++ /dev/null @@ -1,28 +0,0 @@ -# Copyright (C) 2024 Travis Abendshien (CyanVoxel). -# Licensed under the GPL-3.0 License. -# Created for TagStudio: https://github.com/CyanVoxel/TagStudio - - -class FieldTemplate: - """A TagStudio Library Field Template object.""" - - def __init__(self, id: int, name: str, type: str) -> None: - self.id = id - self.name = name - self.type = type - - def __str__(self) -> str: - return f"\nID: {self.id}\nName: {self.name}\nType: {self.type}\n" - - def __repr__(self) -> str: - return self.__str__() - - def to_compressed_obj(self) -> dict: - """An alternative to __dict__ that only includes fields containing non-default data.""" - obj: dict = {} - # All Field fields (haha) are mandatory, so no value checks are done. - obj["id"] = self.id - obj["name"] = self.name - obj["type"] = self.type - - return obj diff --git a/src/tagstudio/core/utils/dupe_files.py b/src/tagstudio/core/library/alchemy/registries/dupe_files_registry.py similarity index 99% rename from src/tagstudio/core/utils/dupe_files.py rename to src/tagstudio/core/library/alchemy/registries/dupe_files_registry.py index 9d3b2af4..d99a4f49 100644 --- a/src/tagstudio/core/utils/dupe_files.py +++ b/src/tagstudio/core/library/alchemy/registries/dupe_files_registry.py @@ -12,7 +12,7 @@ logger = structlog.get_logger() @dataclass -class DupeRegistry: +class DupeFilesRegistry: """State handler for DupeGuru results.""" library: Library diff --git a/src/tagstudio/core/utils/ignored_registry.py b/src/tagstudio/core/library/alchemy/registries/ignored_registry.py similarity index 100% rename from src/tagstudio/core/utils/ignored_registry.py rename to src/tagstudio/core/library/alchemy/registries/ignored_registry.py diff --git a/src/tagstudio/core/utils/unlinked_registry.py b/src/tagstudio/core/library/alchemy/registries/unlinked_registry.py similarity index 100% rename from src/tagstudio/core/utils/unlinked_registry.py rename to src/tagstudio/core/library/alchemy/registries/unlinked_registry.py diff --git a/src/tagstudio/core/library/ignore.py b/src/tagstudio/core/library/ignore.py index af850b4e..708eb140 100644 --- a/src/tagstudio/core/library/ignore.py +++ b/src/tagstudio/core/library/ignore.py @@ -10,7 +10,7 @@ import wcmatch.fnmatch as fnmatch from wcmatch import glob, pathlib from tagstudio.core.constants import IGNORE_NAME, TS_FOLDER_NAME -from tagstudio.core.singleton import Singleton +from tagstudio.core.utils.singleton import Singleton logger = structlog.get_logger() diff --git a/src/tagstudio/core/library/json/library.py b/src/tagstudio/core/library/json/library.py index 79d23a26..81367201 100644 --- a/src/tagstudio/core/library/json/library.py +++ b/src/tagstudio/core/library/json/library.py @@ -27,8 +27,7 @@ from tagstudio.core.constants import ( ) from tagstudio.core.enums import OpenStatus from tagstudio.core.library.json.fields import DEFAULT_FIELDS, TEXT_FIELDS -from tagstudio.core.utils.str import strip_punctuation -from tagstudio.core.utils.web import strip_web_protocol +from tagstudio.core.utils.str_formatting import strip_punctuation, strip_web_protocol TYPE = ["file", "meta", "alt", "mask"] diff --git a/src/tagstudio/core/utils/refresh_dir.py b/src/tagstudio/core/library/refresh.py similarity index 98% rename from src/tagstudio/core/utils/refresh_dir.py rename to src/tagstudio/core/library/refresh.py index f32e822d..1d455556 100644 --- a/src/tagstudio/core/utils/refresh_dir.py +++ b/src/tagstudio/core/library/refresh.py @@ -16,13 +16,13 @@ from wcmatch import pathlib from tagstudio.core.library.alchemy.library import Library from tagstudio.core.library.alchemy.models import Entry from tagstudio.core.library.ignore import PATH_GLOB_FLAGS, Ignore, ignore_to_glob -from tagstudio.qt.helpers.silent_popen import silent_run # pyright: ignore +from tagstudio.core.utils.silent_subprocess import silent_run # pyright: ignore logger = structlog.get_logger(__name__) @dataclass -class RefreshDirTracker: +class RefreshTracker: library: Library files_not_in_library: list[Path] = field(default_factory=list) diff --git a/src/tagstudio/core/ts_core.py b/src/tagstudio/core/ts_core.py index 97ead78c..7eaa153d 100644 --- a/src/tagstudio/core/ts_core.py +++ b/src/tagstudio/core/ts_core.py @@ -7,11 +7,14 @@ import json from pathlib import Path +import structlog + from tagstudio.core.constants import TS_FOLDER_NAME from tagstudio.core.library.alchemy.fields import _FieldID from tagstudio.core.library.alchemy.library import Library from tagstudio.core.library.alchemy.models import Entry -from tagstudio.core.utils.unlinked_registry import logger + +logger = structlog.get_logger(__name__) class TagStudioCore: diff --git a/src/tagstudio/qt/helpers/silent_popen.py b/src/tagstudio/core/utils/silent_subprocess.py similarity index 75% rename from src/tagstudio/qt/helpers/silent_popen.py rename to src/tagstudio/core/utils/silent_subprocess.py index 2aefd76f..680e947f 100644 --- a/src/tagstudio/qt/helpers/silent_popen.py +++ b/src/tagstudio/core/utils/silent_subprocess.py @@ -1,46 +1,51 @@ -# Copyright (C) 2024 Travis Abendshien (CyanVoxel). +# Copyright (C) 2025 # Licensed under the GPL-3.0 License. # Created for TagStudio: https://github.com/CyanVoxel/TagStudio +# pyright: reportExplicitAny=false import os import subprocess import sys +from collections.abc import Callable, Collection, Iterable +from typing import Any """Implementation of subprocess.Popen that does not spawn console windows or log output -and sanitizes pyinstall environment variables.""" +and sanitizes pyinstaller environment variables.""" -def silent_Popen( # noqa: N802 +def silent_popen( args, - bufsize=-1, + bufsize: int = -1, executable=None, stdin=None, stdout=None, stderr=None, - preexec_fn=None, - close_fds=True, - shell=False, + preexec_fn: Callable[[], Any] | None = None, + close_fds: bool = True, + shell: bool = False, cwd=None, env=None, - universal_newlines=None, - startupinfo=None, - creationflags=0, - restore_signals=True, - start_new_session=False, - pass_fds=(), + universal_newlines: bool | None = None, + startupinfo: Any | None = None, + creationflags: int = 0, + restore_signals: bool = True, + start_new_session: bool = False, + pass_fds: Collection[int] = (), *, - group=None, - extra_groups=None, - user=None, - umask=-1, - encoding=None, - errors=None, - text=None, - pipesize=-1, - process_group=None, + text: bool | None = None, + encoding: str | None = None, + errors: str | None = None, + user: str | int | None = None, + group: str | int | None = None, + extra_groups: Iterable[str | int] | None = None, + umask: int = -1, + pipesize: int = -1, + process_group: int | None = None, ): """Call subprocess.Popen without creating a console window.""" + current_env = env + if sys.platform == "win32": creationflags |= subprocess.CREATE_NO_WINDOW import ctypes @@ -52,9 +57,9 @@ def silent_Popen( # noqa: N802 or sys.platform.startswith("openbsd") ): # pass clean environment to the subprocess - env = os.environ - original_env = env.get("LD_LIBRARY_PATH_ORIG") - env["LD_LIBRARY_PATH"] = original_env if original_env else "" + current_env = os.environ + original_env = current_env.get("LD_LIBRARY_PATH_ORIG") + current_env["LD_LIBRARY_PATH"] = original_env if original_env else "" return subprocess.Popen( args=args, @@ -67,20 +72,20 @@ def silent_Popen( # noqa: N802 close_fds=close_fds, shell=shell, cwd=cwd, - env=env, + env=current_env, universal_newlines=universal_newlines, startupinfo=startupinfo, creationflags=creationflags, restore_signals=restore_signals, start_new_session=start_new_session, pass_fds=pass_fds, - group=group, - extra_groups=extra_groups, - user=user, - umask=umask, + text=text, encoding=encoding, errors=errors, - text=text, + user=user, + group=group, + extra_groups=extra_groups, + umask=umask, pipesize=pipesize, process_group=process_group, ) diff --git a/src/tagstudio/core/singleton.py b/src/tagstudio/core/utils/singleton.py similarity index 100% rename from src/tagstudio/core/singleton.py rename to src/tagstudio/core/utils/singleton.py diff --git a/src/tagstudio/core/utils/str.py b/src/tagstudio/core/utils/str_formatting.py similarity index 67% rename from src/tagstudio/core/utils/str.py rename to src/tagstudio/core/utils/str_formatting.py index 11c0105c..e4a870cc 100644 --- a/src/tagstudio/core/utils/str.py +++ b/src/tagstudio/core/utils/str_formatting.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 Travis Abendshien (CyanVoxel). +# Copyright (C) 2025 Travis Abendshien (CyanVoxel). # Licensed under the GPL-3.0 License. # Created for TagStudio: https://github.com/CyanVoxel/TagStudio @@ -24,3 +24,11 @@ def strip_punctuation(string: str) -> str: .replace(" ", "") .replace(" ", "") ) + + +def strip_web_protocol(string: str) -> str: + r"""Strips a leading web protocol (ex. \"https://\") as well as \"www.\" from a string.""" + prefixes = ["https://", "http://", "www.", "www2."] + for prefix in prefixes: + string = string.removeprefix(prefix) + return string diff --git a/src/tagstudio/core/utils/web.py b/src/tagstudio/core/utils/web.py deleted file mode 100644 index 67d4ce72..00000000 --- a/src/tagstudio/core/utils/web.py +++ /dev/null @@ -1,11 +0,0 @@ -# Copyright (C) 2024 Travis Abendshien (CyanVoxel). -# Licensed under the GPL-3.0 License. -# Created for TagStudio: https://github.com/CyanVoxel/TagStudio - - -def strip_web_protocol(string: str) -> str: - r"""Strips a leading web protocol (ex. \"https://\") as well as \"www.\" from a string.""" - prefixes = ["https://", "http://", "www.", "www2."] - for prefix in prefixes: - string = string.removeprefix(prefix) - return string diff --git a/src/tagstudio/qt/cache_manager.py b/src/tagstudio/qt/cache_manager.py index 46e15cf4..e15ead68 100644 --- a/src/tagstudio/qt/cache_manager.py +++ b/src/tagstudio/qt/cache_manager.py @@ -12,7 +12,7 @@ import structlog from PIL import Image from tagstudio.core.constants import THUMB_CACHE_NAME, TS_FOLDER_NAME -from tagstudio.core.global_settings import DEFAULT_CACHED_IMAGE_QUALITY, DEFAULT_THUMB_CACHE_SIZE +from tagstudio.qt.global_settings import DEFAULT_CACHED_IMAGE_QUALITY, DEFAULT_THUMB_CACHE_SIZE logger = structlog.get_logger(__name__) diff --git a/src/tagstudio/qt/modals/ffmpeg_checker.py b/src/tagstudio/qt/controllers/ffmpeg_missing_message_box.py similarity index 90% rename from src/tagstudio/qt/modals/ffmpeg_checker.py rename to src/tagstudio/qt/controllers/ffmpeg_missing_message_box.py index 776032b2..3de27f88 100644 --- a/src/tagstudio/qt/modals/ffmpeg_checker.py +++ b/src/tagstudio/qt/controllers/ffmpeg_missing_message_box.py @@ -5,14 +5,14 @@ from PySide6.QtCore import Qt, QUrl from PySide6.QtGui import QDesktopServices from PySide6.QtWidgets import QMessageBox -from tagstudio.core.palette import ColorType, UiColor, get_ui_color -from tagstudio.qt.helpers.vendored.ffmpeg import FFMPEG_CMD, FFPROBE_CMD +from tagstudio.qt.models.palette import ColorType, UiColor, get_ui_color +from tagstudio.qt.previews.vendored.ffmpeg import FFMPEG_CMD, FFPROBE_CMD from tagstudio.qt.translations import Translations logger = structlog.get_logger(__name__) -class FfmpegChecker(QMessageBox): +class FfmpegMissingMessageBox(QMessageBox): """A warning dialog for if FFmpeg is missing.""" HELP_URL = "https://docs.tagstud.io/help/ffmpeg/" diff --git a/src/tagstudio/qt/controller/fix_ignored_modal_controller.py b/src/tagstudio/qt/controllers/fix_ignored_modal_controller.py similarity index 91% rename from src/tagstudio/qt/controller/fix_ignored_modal_controller.py rename to src/tagstudio/qt/controllers/fix_ignored_modal_controller.py index 324fab44..6afc25f8 100644 --- a/src/tagstudio/qt/controller/fix_ignored_modal_controller.py +++ b/src/tagstudio/qt/controllers/fix_ignored_modal_controller.py @@ -9,11 +9,11 @@ import structlog from PySide6 import QtGui from tagstudio.core.library.alchemy.library import Library -from tagstudio.core.utils.ignored_registry import IgnoredRegistry -from tagstudio.qt.modals.remove_ignored_modal import RemoveIgnoredModal +from tagstudio.core.library.alchemy.registries.ignored_registry import IgnoredRegistry +from tagstudio.qt.mixed.progress_bar import ProgressWidget +from tagstudio.qt.mixed.remove_ignored_modal import RemoveIgnoredModal from tagstudio.qt.translations import Translations -from tagstudio.qt.view.widgets.fix_ignored_modal_view import FixIgnoredEntriesModalView -from tagstudio.qt.widgets.progress import ProgressWidget +from tagstudio.qt.views.fix_ignored_modal_view import FixIgnoredEntriesModalView # Only import for type checking/autocompletion, will not be imported at runtime. if TYPE_CHECKING: diff --git a/src/tagstudio/qt/controller/widgets/ignore_modal_controller.py b/src/tagstudio/qt/controllers/ignore_modal_controller.py similarity index 81% rename from src/tagstudio/qt/controller/widgets/ignore_modal_controller.py rename to src/tagstudio/qt/controllers/ignore_modal_controller.py index 5f70e60c..66937d5b 100644 --- a/src/tagstudio/qt/controller/widgets/ignore_modal_controller.py +++ b/src/tagstudio/qt/controllers/ignore_modal_controller.py @@ -4,17 +4,18 @@ from pathlib import Path +from typing import override import structlog -from PySide6 import QtGui from PySide6.QtCore import Signal +from PySide6.QtGui import QShowEvent 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 +from tagstudio.qt.utils.file_opener import open_file +from tagstudio.qt.views.ignore_modal_view import IgnoreModalView logger = structlog.get_logger(__name__) @@ -36,7 +37,7 @@ class IgnoreModal(IgnoreModalView): 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) + open_file(ts_ignore_path, file_manager=True) def save(self): if not self.lib.library_dir: @@ -45,6 +46,7 @@ class IgnoreModal(IgnoreModalView): 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 + @override + def showEvent(self, event: QShowEvent) -> None: # type: ignore self.__load_file() return super().showEvent(event) diff --git a/src/tagstudio/qt/controller/widgets/library_info_window_controller.py b/src/tagstudio/qt/controllers/library_info_window_controller.py similarity index 97% rename from src/tagstudio/qt/controller/widgets/library_info_window_controller.py rename to src/tagstudio/qt/controllers/library_info_window_controller.py index d46164db..e435a798 100644 --- a/src/tagstudio/qt/controller/widgets/library_info_window_controller.py +++ b/src/tagstudio/qt/controllers/library_info_window_controller.py @@ -18,9 +18,9 @@ from tagstudio.core.library.alchemy.constants import ( ) from tagstudio.core.library.alchemy.library import Library from tagstudio.core.utils.types import unwrap -from tagstudio.qt.helpers import file_opener from tagstudio.qt.translations import Translations -from tagstudio.qt.view.widgets.library_info_window_view import LibraryInfoWindowView +from tagstudio.qt.utils import file_opener +from tagstudio.qt.views.library_info_window_view import LibraryInfoWindowView # Only import for type checking/autocompletion, will not be imported at runtime. if TYPE_CHECKING: diff --git a/src/tagstudio/qt/widgets/paged_panel/paged_panel.py b/src/tagstudio/qt/controllers/paged_panel_controller.py similarity index 98% rename from src/tagstudio/qt/widgets/paged_panel/paged_panel.py rename to src/tagstudio/qt/controllers/paged_panel_controller.py index 020f9889..ddffe554 100644 --- a/src/tagstudio/qt/widgets/paged_panel/paged_panel.py +++ b/src/tagstudio/qt/controllers/paged_panel_controller.py @@ -10,7 +10,7 @@ from PySide6 import QtCore, QtGui from PySide6.QtCore import Qt from PySide6.QtWidgets import QHBoxLayout, QLabel, QVBoxLayout, QWidget -from tagstudio.qt.widgets.paged_panel.paged_panel_state import PagedPanelState +from tagstudio.qt.controllers.paged_panel_state import PagedPanelState logger = structlog.get_logger(__name__) diff --git a/src/tagstudio/qt/widgets/paged_panel/paged_panel_state.py b/src/tagstudio/qt/controllers/paged_panel_state.py similarity index 90% rename from src/tagstudio/qt/widgets/paged_panel/paged_panel_state.py rename to src/tagstudio/qt/controllers/paged_panel_state.py index 66e04b28..368cc4d4 100644 --- a/src/tagstudio/qt/widgets/paged_panel/paged_panel_state.py +++ b/src/tagstudio/qt/controllers/paged_panel_state.py @@ -5,7 +5,7 @@ from PySide6.QtWidgets import QPushButton -from tagstudio.qt.widgets.paged_panel.paged_body_wrapper import PagedBodyWrapper +from tagstudio.qt.views.paged_body_wrapper import PagedBodyWrapper class PagedPanelState: diff --git a/src/tagstudio/qt/controller/widgets/preview_panel_controller.py b/src/tagstudio/qt/controllers/preview_panel_controller.py similarity index 89% rename from src/tagstudio/qt/controller/widgets/preview_panel_controller.py rename to src/tagstudio/qt/controllers/preview_panel_controller.py index 57a941f6..0cf66619 100644 --- a/src/tagstudio/qt/controller/widgets/preview_panel_controller.py +++ b/src/tagstudio/qt/controllers/preview_panel_controller.py @@ -7,9 +7,9 @@ from warnings import catch_warnings from PySide6.QtWidgets import QListWidgetItem from tagstudio.core.library.alchemy.library import Library -from tagstudio.qt.modals.add_field import AddFieldModal -from tagstudio.qt.modals.tag_search import TagSearchModal -from tagstudio.qt.view.widgets.preview_panel_view import PreviewPanelView +from tagstudio.qt.mixed.add_field import AddFieldModal +from tagstudio.qt.mixed.tag_search import TagSearchModal +from tagstudio.qt.views.preview_panel_view import PreviewPanelView if typing.TYPE_CHECKING: from tagstudio.qt.ts_qt import QtDriver diff --git a/src/tagstudio/qt/controller/widgets/preview/preview_thumb_controller.py b/src/tagstudio/qt/controllers/preview_thumb_controller.py similarity index 96% rename from src/tagstudio/qt/controller/widgets/preview/preview_thumb_controller.py rename to src/tagstudio/qt/controllers/preview_thumb_controller.py index 65223e54..ecc5d96a 100644 --- a/src/tagstudio/qt/controller/widgets/preview/preview_thumb_controller.py +++ b/src/tagstudio/qt/controllers/preview_thumb_controller.py @@ -14,10 +14,10 @@ from PySide6.QtCore import QSize from tagstudio.core.library.alchemy.library import Library from tagstudio.core.media_types import MediaCategories -from tagstudio.qt.helpers.file_opener import open_file from tagstudio.qt.helpers.file_tester import is_readable_video -from tagstudio.qt.view.widgets.preview.preview_thumb_view import PreviewThumbView -from tagstudio.qt.widgets.preview.file_attributes import FileAttributeData +from tagstudio.qt.mixed.file_attributes import FileAttributeData +from tagstudio.qt.utils.file_opener import open_file +from tagstudio.qt.views.preview_thumb_view import PreviewThumbView if TYPE_CHECKING: from tagstudio.qt.ts_qt import QtDriver diff --git a/src/tagstudio/qt/controller/components/tag_box_controller.py b/src/tagstudio/qt/controllers/tag_box_controller.py similarity index 95% rename from src/tagstudio/qt/controller/components/tag_box_controller.py rename to src/tagstudio/qt/controllers/tag_box_controller.py index 1af5422b..2a5865d8 100644 --- a/src/tagstudio/qt/controller/components/tag_box_controller.py +++ b/src/tagstudio/qt/controllers/tag_box_controller.py @@ -11,9 +11,9 @@ from tagstudio.core.enums import TagClickActionOption from tagstudio.core.library.alchemy.enums import BrowsingState from tagstudio.core.library.alchemy.models import Tag from tagstudio.core.utils.types import unwrap -from tagstudio.qt.modals.build_tag import BuildTagPanel -from tagstudio.qt.view.components.tag_box_view import TagBoxWidgetView -from tagstudio.qt.widgets.panel import PanelModal +from tagstudio.qt.mixed.build_tag import BuildTagPanel +from tagstudio.qt.views.panel_modal import PanelModal +from tagstudio.qt.views.tag_box_view import TagBoxWidgetView if TYPE_CHECKING: from tagstudio.qt.ts_qt import QtDriver diff --git a/src/tagstudio/core/global_settings.py b/src/tagstudio/qt/global_settings.py similarity index 100% rename from src/tagstudio/core/global_settings.py rename to src/tagstudio/qt/global_settings.py diff --git a/src/tagstudio/qt/helpers/color_overlay.py b/src/tagstudio/qt/helpers/color_overlay.py index 0c846b52..8fd43263 100644 --- a/src/tagstudio/qt/helpers/color_overlay.py +++ b/src/tagstudio/qt/helpers/color_overlay.py @@ -7,7 +7,7 @@ from PIL import Image from PySide6.QtCore import Qt from PySide6.QtGui import QGuiApplication -from tagstudio.qt.helpers.gradient import linear_gradient +from tagstudio.qt.helpers.gradients import linear_gradient # TODO: Consolidate the built-in QT theme values with the values # here, in enums.py, and in palette.py. diff --git a/src/tagstudio/qt/helpers/file_tester.py b/src/tagstudio/qt/helpers/file_tester.py index 2f63eef9..d899f7e6 100644 --- a/src/tagstudio/qt/helpers/file_tester.py +++ b/src/tagstudio/qt/helpers/file_tester.py @@ -7,7 +7,9 @@ from pathlib import Path import ffmpeg -from tagstudio.qt.helpers.vendored.ffmpeg import probe +from tagstudio.qt.previews.vendored.ffmpeg import ( + probe, # pyright: ignore[reportUnknownVariableType] +) def is_readable_video(filepath: Path | str): diff --git a/src/tagstudio/qt/helpers/gradient.py b/src/tagstudio/qt/helpers/gradients.py similarity index 100% rename from src/tagstudio/qt/helpers/gradient.py rename to src/tagstudio/qt/helpers/gradients.py diff --git a/src/tagstudio/qt/modals/about.py b/src/tagstudio/qt/mixed/about_modal.py similarity index 98% rename from src/tagstudio/qt/modals/about.py rename to src/tagstudio/qt/mixed/about_modal.py index c85c501b..e7d4a2ec 100644 --- a/src/tagstudio/qt/modals/about.py +++ b/src/tagstudio/qt/mixed/about_modal.py @@ -20,8 +20,8 @@ from PySide6.QtWidgets import ( from tagstudio.core.constants import VERSION, VERSION_BRANCH from tagstudio.core.enums import Theme -from tagstudio.core.palette import ColorType, UiColor, get_ui_color -from tagstudio.qt.helpers.vendored import ffmpeg +from tagstudio.qt.models.palette import ColorType, UiColor, get_ui_color +from tagstudio.qt.previews.vendored import ffmpeg from tagstudio.qt.resource_manager import ResourceManager from tagstudio.qt.translations import Translations diff --git a/src/tagstudio/qt/modals/add_field.py b/src/tagstudio/qt/mixed/add_field.py similarity index 100% rename from src/tagstudio/qt/modals/add_field.py rename to src/tagstudio/qt/mixed/add_field.py diff --git a/src/tagstudio/qt/modals/build_color.py b/src/tagstudio/qt/mixed/build_color.py similarity index 97% rename from src/tagstudio/qt/modals/build_color.py rename to src/tagstudio/qt/mixed/build_color.py index 67d86c86..a007c9ee 100644 --- a/src/tagstudio/qt/modals/build_color.py +++ b/src/tagstudio/qt/mixed/build_color.py @@ -20,19 +20,18 @@ from PySide6.QtWidgets import ( QWidget, ) -from tagstudio.core import palette from tagstudio.core.library.alchemy.enums import TagColorEnum from tagstudio.core.library.alchemy.library import Library, slugify from tagstudio.core.library.alchemy.models import TagColorGroup -from tagstudio.core.palette import ColorType, UiColor, get_tag_color, get_ui_color -from tagstudio.qt.translations import Translations -from tagstudio.qt.widgets.panel import PanelWidget -from tagstudio.qt.widgets.tag import ( +from tagstudio.qt.mixed.tag_color_preview import TagColorPreview +from tagstudio.qt.mixed.tag_widget import ( get_border_color, get_highlight_color, get_text_color, ) -from tagstudio.qt.widgets.tag_color_preview import TagColorPreview +from tagstudio.qt.models.palette import ColorType, UiColor, get_tag_color, get_ui_color +from tagstudio.qt.translations import Translations +from tagstudio.qt.views.panel_modal import PanelWidget logger = structlog.get_logger(__name__) @@ -265,7 +264,7 @@ class BuildColorPanel(PanelWidget): def update_secondary(self, color: QColor | None = None, color_border: bool = False): logger.info("[BuildColorPanel] Updating Secondary", color=color) - color_ = color or QColor(palette.get_tag_color(ColorType.PRIMARY, TagColorEnum.DEFAULT)) + color_ = color or QColor(get_tag_color(ColorType.PRIMARY, TagColorEnum.DEFAULT)) highlight_color = get_highlight_color(color_) text_color = get_text_color(color_, highlight_color) diff --git a/src/tagstudio/qt/modals/build_namespace.py b/src/tagstudio/qt/mixed/build_namespace.py similarity index 98% rename from src/tagstudio/qt/modals/build_namespace.py rename to src/tagstudio/qt/mixed/build_namespace.py index a358a7d9..c7b4ed23 100644 --- a/src/tagstudio/qt/modals/build_namespace.py +++ b/src/tagstudio/qt/mixed/build_namespace.py @@ -13,9 +13,9 @@ from PySide6.QtWidgets import QLabel, QLineEdit, QVBoxLayout, QWidget from tagstudio.core.constants import RESERVED_NAMESPACE_PREFIX from tagstudio.core.library.alchemy.library import Library, ReservedNamespaceError, slugify from tagstudio.core.library.alchemy.models import Namespace -from tagstudio.core.palette import ColorType, UiColor, get_ui_color +from tagstudio.qt.models.palette import ColorType, UiColor, get_ui_color from tagstudio.qt.translations import Translations -from tagstudio.qt.widgets.panel import PanelWidget +from tagstudio.qt.views.panel_modal import PanelWidget logger = structlog.get_logger(__name__) diff --git a/src/tagstudio/qt/modals/build_tag.py b/src/tagstudio/qt/mixed/build_tag.py similarity index 98% rename from src/tagstudio/qt/modals/build_tag.py rename to src/tagstudio/qt/mixed/build_tag.py index 9dd077e4..846a1961 100644 --- a/src/tagstudio/qt/modals/build_tag.py +++ b/src/tagstudio/qt/mixed/build_tag.py @@ -28,19 +28,19 @@ from PySide6.QtWidgets import ( from tagstudio.core.library.alchemy.enums import TagColorEnum from tagstudio.core.library.alchemy.library import Library from tagstudio.core.library.alchemy.models import Tag, TagColorGroup -from tagstudio.core.palette import ColorType, UiColor, get_tag_color, get_ui_color -from tagstudio.qt.modals.tag_color_selection import TagColorSelection -from tagstudio.qt.modals.tag_search import TagSearchModal, TagSearchPanel -from tagstudio.qt.translations import Translations -from tagstudio.qt.widgets.panel import PanelModal, PanelWidget -from tagstudio.qt.widgets.tag import ( +from tagstudio.qt.mixed.tag_color_preview import TagColorPreview +from tagstudio.qt.mixed.tag_color_selection import TagColorSelection +from tagstudio.qt.mixed.tag_search import TagSearchModal, TagSearchPanel +from tagstudio.qt.mixed.tag_widget import ( TagWidget, get_border_color, get_highlight_color, get_primary_color, get_text_color, ) -from tagstudio.qt.widgets.tag_color_preview import TagColorPreview +from tagstudio.qt.models.palette import ColorType, UiColor, get_tag_color, get_ui_color +from tagstudio.qt.translations import Translations +from tagstudio.qt.views.panel_modal import PanelModal, PanelWidget logger = structlog.get_logger(__name__) diff --git a/src/tagstudio/qt/widgets/collage_icon.py b/src/tagstudio/qt/mixed/collage_icon.py similarity index 100% rename from src/tagstudio/qt/widgets/collage_icon.py rename to src/tagstudio/qt/mixed/collage_icon.py diff --git a/src/tagstudio/qt/widgets/color_box.py b/src/tagstudio/qt/mixed/color_box.py similarity index 93% rename from src/tagstudio/qt/widgets/color_box.py rename to src/tagstudio/qt/mixed/color_box.py index cbf39ef2..b5224994 100644 --- a/src/tagstudio/qt/widgets/color_box.py +++ b/src/tagstudio/qt/mixed/color_box.py @@ -13,16 +13,16 @@ from PySide6.QtWidgets import QMessageBox, QPushButton from tagstudio.core.constants import RESERVED_NAMESPACE_PREFIX from tagstudio.core.library.alchemy.enums import TagColorEnum from tagstudio.core.library.alchemy.models import TagColorGroup -from tagstudio.core.palette import ColorType, get_tag_color -from tagstudio.qt.flowlayout import FlowLayout -from tagstudio.qt.modals.build_color import BuildColorPanel +from tagstudio.qt.mixed.build_color import BuildColorPanel +from tagstudio.qt.mixed.field_widget import FieldWidget +from tagstudio.qt.mixed.tag_color_label import TagColorLabel +from tagstudio.qt.models.palette import ColorType, get_tag_color from tagstudio.qt.translations import Translations -from tagstudio.qt.widgets.fields import FieldWidget -from tagstudio.qt.widgets.panel import PanelModal -from tagstudio.qt.widgets.tag_color_label import TagColorLabel +from tagstudio.qt.views.layouts.flow_layout import FlowLayout +from tagstudio.qt.views.panel_modal import PanelModal if typing.TYPE_CHECKING: - from tagstudio.core.library import Library + from tagstudio.core.library.alchemy.library import Library logger = structlog.get_logger(__name__) diff --git a/src/tagstudio/qt/widgets/datetime_picker.py b/src/tagstudio/qt/mixed/datetime_picker.py similarity index 97% rename from src/tagstudio/qt/widgets/datetime_picker.py rename to src/tagstudio/qt/mixed/datetime_picker.py index 3ac991da..b059dd96 100644 --- a/src/tagstudio/qt/widgets/datetime_picker.py +++ b/src/tagstudio/qt/mixed/datetime_picker.py @@ -6,7 +6,7 @@ from typing import cast from PySide6.QtCore import QDateTime from PySide6.QtWidgets import QDateTimeEdit, QVBoxLayout -from tagstudio.qt.widgets.panel import PanelWidget +from tagstudio.qt.views.panel_modal import PanelWidget if typing.TYPE_CHECKING: from tagstudio.qt.ts_qt import QtDriver diff --git a/src/tagstudio/qt/modals/drop_import.py b/src/tagstudio/qt/mixed/drop_import_modal.py similarity index 99% rename from src/tagstudio/qt/modals/drop_import.py rename to src/tagstudio/qt/mixed/drop_import_modal.py index 495740e7..049fe9c8 100644 --- a/src/tagstudio/qt/modals/drop_import.py +++ b/src/tagstudio/qt/mixed/drop_import_modal.py @@ -21,8 +21,8 @@ from PySide6.QtWidgets import ( QWidget, ) +from tagstudio.qt.mixed.progress_bar import ProgressWidget from tagstudio.qt.translations import Translations -from tagstudio.qt.widgets.progress import ProgressWidget if TYPE_CHECKING: from tagstudio.qt.ts_qt import QtDriver diff --git a/src/tagstudio/qt/widgets/preview/field_containers.py b/src/tagstudio/qt/mixed/field_containers.py similarity index 97% rename from src/tagstudio/qt/widgets/preview/field_containers.py rename to src/tagstudio/qt/mixed/field_containers.py index 4bd7d03c..1128e494 100644 --- a/src/tagstudio/qt/widgets/preview/field_containers.py +++ b/src/tagstudio/qt/mixed/field_containers.py @@ -24,23 +24,23 @@ from PySide6.QtWidgets import ( from tagstudio.core.constants import TAG_ARCHIVED, TAG_FAVORITE from tagstudio.core.enums import Theme +from tagstudio.core.library.alchemy.enums import FieldTypeEnum from tagstudio.core.library.alchemy.fields import ( BaseField, DatetimeField, - FieldTypeEnum, TextField, ) from tagstudio.core.library.alchemy.library import Library from tagstudio.core.library.alchemy.models import Entry, Tag from tagstudio.core.utils.types import unwrap -from tagstudio.qt.controller.components.tag_box_controller import TagBoxWidget +from tagstudio.qt.controllers.tag_box_controller import TagBoxWidget +from tagstudio.qt.mixed.datetime_picker import DatetimePicker +from tagstudio.qt.mixed.field_widget import FieldContainer +from tagstudio.qt.mixed.text_field import TextWidget from tagstudio.qt.translations import Translations -from tagstudio.qt.widgets.datetime_picker import DatetimePicker -from tagstudio.qt.widgets.fields import FieldContainer -from tagstudio.qt.widgets.panel import PanelModal -from tagstudio.qt.widgets.text import TextWidget -from tagstudio.qt.widgets.text_box_edit import EditTextBox -from tagstudio.qt.widgets.text_line_edit import EditTextLine +from tagstudio.qt.views.edit_text_box_modal import EditTextBox +from tagstudio.qt.views.edit_text_line_modal import EditTextLine +from tagstudio.qt.views.panel_modal import PanelModal if typing.TYPE_CHECKING: from tagstudio.qt.ts_qt import QtDriver diff --git a/src/tagstudio/qt/widgets/fields.py b/src/tagstudio/qt/mixed/field_widget.py similarity index 100% rename from src/tagstudio/qt/widgets/fields.py rename to src/tagstudio/qt/mixed/field_widget.py diff --git a/src/tagstudio/qt/widgets/preview/file_attributes.py b/src/tagstudio/qt/mixed/file_attributes.py similarity index 98% rename from src/tagstudio/qt/widgets/preview/file_attributes.py rename to src/tagstudio/qt/mixed/file_attributes.py index 1e67ee08..dd1b0dd3 100644 --- a/src/tagstudio/qt/widgets/preview/file_attributes.py +++ b/src/tagstudio/qt/mixed/file_attributes.py @@ -22,10 +22,10 @@ from tagstudio.core.enums import ShowFilepathOption, Theme from tagstudio.core.library.alchemy.library import Library from tagstudio.core.library.ignore import Ignore from tagstudio.core.media_types import MediaCategories -from tagstudio.core.palette import ColorType, UiColor, get_ui_color from tagstudio.core.utils.types import unwrap -from tagstudio.qt.helpers.file_opener import FileOpenerHelper, FileOpenerLabel +from tagstudio.qt.models.palette import ColorType, UiColor, get_ui_color from tagstudio.qt.translations import Translations +from tagstudio.qt.utils.file_opener import FileOpenerHelper, FileOpenerLabel if typing.TYPE_CHECKING: from tagstudio.qt.ts_qt import QtDriver diff --git a/src/tagstudio/qt/modals/fix_dupes.py b/src/tagstudio/qt/mixed/fix_dupe_files.py similarity index 95% rename from src/tagstudio/qt/modals/fix_dupes.py rename to src/tagstudio/qt/mixed/fix_dupe_files.py index c2b141b3..c215e862 100644 --- a/src/tagstudio/qt/modals/fix_dupes.py +++ b/src/tagstudio/qt/mixed/fix_dupe_files.py @@ -17,8 +17,8 @@ from PySide6.QtWidgets import ( ) from tagstudio.core.library.alchemy.library import Library -from tagstudio.core.utils.dupe_files import DupeRegistry -from tagstudio.qt.modals.mirror_entries_modal import MirrorEntriesModal +from tagstudio.core.library.alchemy.registries.dupe_files_registry import DupeFilesRegistry +from tagstudio.qt.mixed.mirror_entries_modal import MirrorEntriesModal from tagstudio.qt.translations import Translations # Only import for type checking/autocompletion, will not be imported at runtime. @@ -40,7 +40,7 @@ class FixDupeFilesModal(QWidget): self.root_layout = QVBoxLayout(self) self.root_layout.setContentsMargins(6, 6, 6, 6) - self.tracker = DupeRegistry(library=self.lib) + self.tracker = DupeFilesRegistry(library=self.lib) self.desc_widget = QLabel(Translations["file.duplicates.description"]) self.desc_widget.setObjectName("descriptionLabel") diff --git a/src/tagstudio/qt/modals/fix_unlinked.py b/src/tagstudio/qt/mixed/fix_unlinked.py similarity index 94% rename from src/tagstudio/qt/modals/fix_unlinked.py rename to src/tagstudio/qt/mixed/fix_unlinked.py index 0e92b153..63a1affc 100644 --- a/src/tagstudio/qt/modals/fix_unlinked.py +++ b/src/tagstudio/qt/mixed/fix_unlinked.py @@ -10,12 +10,12 @@ from PySide6.QtCore import Qt from PySide6.QtWidgets import QHBoxLayout, QLabel, QPushButton, QVBoxLayout, QWidget from tagstudio.core.library.alchemy.library import Library -from tagstudio.core.utils.unlinked_registry import UnlinkedRegistry -from tagstudio.qt.modals.merge_dupe_entries import MergeDuplicateEntries -from tagstudio.qt.modals.relink_entries_modal import RelinkUnlinkedEntries -from tagstudio.qt.modals.remove_unlinked_modal import RemoveUnlinkedEntriesModal +from tagstudio.core.library.alchemy.registries.unlinked_registry import UnlinkedRegistry +from tagstudio.qt.mixed.merge_dupe_entries import MergeDuplicateEntries +from tagstudio.qt.mixed.progress_bar import ProgressWidget +from tagstudio.qt.mixed.relink_entries_modal import RelinkUnlinkedEntries +from tagstudio.qt.mixed.remove_unlinked_modal import RemoveUnlinkedEntriesModal from tagstudio.qt.translations import Translations -from tagstudio.qt.widgets.progress import ProgressWidget # Only import for type checking/autocompletion, will not be imported at runtime. if TYPE_CHECKING: diff --git a/src/tagstudio/qt/modals/folders_to_tags.py b/src/tagstudio/qt/mixed/folders_to_tags.py similarity index 98% rename from src/tagstudio/qt/modals/folders_to_tags.py rename to src/tagstudio/qt/mixed/folders_to_tags.py index 6c4a9d93..f7051f77 100644 --- a/src/tagstudio/qt/modals/folders_to_tags.py +++ b/src/tagstudio/qt/mixed/folders_to_tags.py @@ -20,15 +20,16 @@ from PySide6.QtWidgets import ( QVBoxLayout, QWidget, ) +from typing_extensions import deprecated from tagstudio.core.constants import TAG_ARCHIVED, TAG_FAVORITE from tagstudio.core.library.alchemy.enums import TagColorEnum from tagstudio.core.library.alchemy.library import Library from tagstudio.core.library.alchemy.models import Tag -from tagstudio.core.palette import ColorType, get_tag_color from tagstudio.core.utils.types import unwrap -from tagstudio.qt.flowlayout import FlowLayout +from tagstudio.qt.models.palette import ColorType, get_tag_color from tagstudio.qt.translations import Translations +from tagstudio.qt.views.layouts.flow_layout import FlowLayout if TYPE_CHECKING: from tagstudio.qt.ts_qt import QtDriver @@ -56,6 +57,7 @@ def add_folders_to_tree(library: Library, tree: BranchData, items: tuple[str, .. return branch +@deprecated("Will be replaced with upcoming 'Macros' feature before v9.6") def folders_to_tags(library: Library): logger.info("Converting folders to Tags") tree = BranchData() diff --git a/src/tagstudio/qt/widgets/item_thumb.py b/src/tagstudio/qt/mixed/item_thumb.py similarity index 98% rename from src/tagstudio/qt/widgets/item_thumb.py rename to src/tagstudio/qt/mixed/item_thumb.py index 7b83c0b6..8d2b0762 100644 --- a/src/tagstudio/qt/widgets/item_thumb.py +++ b/src/tagstudio/qt/mixed/item_thumb.py @@ -13,26 +13,19 @@ import structlog from PIL import Image, ImageQt from PySide6.QtCore import QEvent, QMimeData, QSize, Qt, QUrl from PySide6.QtGui import QAction, QDrag, QEnterEvent, QGuiApplication, QMouseEvent, QPixmap -from PySide6.QtWidgets import ( - QBoxLayout, - QCheckBox, - QHBoxLayout, - QLabel, - QVBoxLayout, - QWidget, -) +from PySide6.QtWidgets import QBoxLayout, QCheckBox, QHBoxLayout, QLabel, QVBoxLayout, QWidget from tagstudio.core.constants import TAG_ARCHIVED, TAG_FAVORITE from tagstudio.core.library.alchemy.enums import ItemType from tagstudio.core.library.alchemy.library import Library from tagstudio.core.media_types import MediaCategories, MediaType from tagstudio.core.utils.types import unwrap -from tagstudio.qt.flowlayout import FlowWidget -from tagstudio.qt.helpers.file_opener import FileOpenerHelper from tagstudio.qt.platform_strings import open_file_str, trash_term +from tagstudio.qt.previews.renderer import ThumbRenderer from tagstudio.qt.translations import Translations -from tagstudio.qt.widgets.thumb_button import ThumbButton -from tagstudio.qt.widgets.thumb_renderer import ThumbRenderer +from tagstudio.qt.utils.file_opener import FileOpenerHelper +from tagstudio.qt.views.layouts.flow_layout import FlowWidget +from tagstudio.qt.views.thumb_button import ThumbButton if TYPE_CHECKING: from tagstudio.qt.ts_qt import QtDriver diff --git a/src/tagstudio/qt/widgets/landing.py b/src/tagstudio/qt/mixed/landing.py similarity index 99% rename from src/tagstudio/qt/widgets/landing.py rename to src/tagstudio/qt/mixed/landing.py index 8d710f1f..050994ac 100644 --- a/src/tagstudio/qt/widgets/landing.py +++ b/src/tagstudio/qt/mixed/landing.py @@ -15,7 +15,7 @@ from PySide6.QtWidgets import QLabel, QPushButton, QVBoxLayout, QWidget from tagstudio.qt.helpers.color_overlay import gradient_overlay, theme_fg_overlay from tagstudio.qt.translations import Translations -from tagstudio.qt.widgets.clickable_label import ClickableLabel +from tagstudio.qt.views.clickable_label import ClickableLabel # Only import for type checking/autocompletion, will not be imported at runtime. if typing.TYPE_CHECKING: diff --git a/src/tagstudio/qt/widgets/media_player.py b/src/tagstudio/qt/mixed/media_player.py similarity index 99% rename from src/tagstudio/qt/widgets/media_player.py rename to src/tagstudio/qt/mixed/media_player.py index 99910858..c891cd0a 100644 --- a/src/tagstudio/qt/widgets/media_player.py +++ b/src/tagstudio/qt/mixed/media_player.py @@ -35,8 +35,8 @@ from PySide6.QtWidgets import ( QWidget, ) -from tagstudio.qt.helpers.qslider_wrapper import QClickSlider from tagstudio.qt.translations import Translations +from tagstudio.qt.views.clickable_slider import ClickableSlider if typing.TYPE_CHECKING: from tagstudio.qt.ts_qt import QtDriver @@ -147,7 +147,7 @@ class MediaPlayer(QGraphicsView): self.controls.setStyleSheet("background: transparent;") self.controls.setMinimumHeight(48) - self.timeline_slider = QClickSlider() + self.timeline_slider = ClickableSlider() self.timeline_slider.setFocusPolicy(Qt.FocusPolicy.StrongFocus) self.timeline_slider.setTickPosition(QSlider.TickPosition.NoTicks) self.timeline_slider.setSingleStep(1) @@ -196,7 +196,7 @@ class MediaPlayer(QGraphicsView): sub_layout.addWidget(self.mute_unmute) sub_layout.setAlignment(self.mute_unmute, Qt.AlignmentFlag.AlignLeft) - self.volume_slider = QClickSlider() + self.volume_slider = ClickableSlider() self.volume_slider.setOrientation(Qt.Orientation.Horizontal) self.volume_slider.setValue(int(self.player.audioOutput().volume() * 100)) self.volume_slider.valueChanged.connect(self.volume_slider_changed) diff --git a/src/tagstudio/qt/modals/merge_dupe_entries.py b/src/tagstudio/qt/mixed/merge_dupe_entries.py similarity index 83% rename from src/tagstudio/qt/modals/merge_dupe_entries.py rename to src/tagstudio/qt/mixed/merge_dupe_entries.py index d999f4ea..af56a0bf 100644 --- a/src/tagstudio/qt/modals/merge_dupe_entries.py +++ b/src/tagstudio/qt/mixed/merge_dupe_entries.py @@ -8,9 +8,9 @@ import typing from PySide6.QtCore import QObject, Signal from tagstudio.core.library.alchemy.library import Library -from tagstudio.core.utils.dupe_files import DupeRegistry +from tagstudio.core.library.alchemy.registries.dupe_files_registry import DupeFilesRegistry +from tagstudio.qt.mixed.progress_bar import ProgressWidget from tagstudio.qt.translations import Translations -from tagstudio.qt.widgets.progress import ProgressWidget # Only import for type checking/autocompletion, will not be imported at runtime. if typing.TYPE_CHECKING: @@ -24,7 +24,7 @@ class MergeDuplicateEntries(QObject): super().__init__() self.lib = library self.driver = driver - self.tracker = DupeRegistry(library=self.lib) + self.tracker = DupeFilesRegistry(library=self.lib) def merge_entries(self): pw = ProgressWidget( diff --git a/src/tagstudio/qt/widgets/migration_modal.py b/src/tagstudio/qt/mixed/migration_modal.py similarity index 98% rename from src/tagstudio/qt/widgets/migration_modal.py rename to src/tagstudio/qt/mixed/migration_modal.py index 3de94ae1..c98505d1 100644 --- a/src/tagstudio/qt/widgets/migration_modal.py +++ b/src/tagstudio/qt/mixed/migration_modal.py @@ -37,13 +37,13 @@ from tagstudio.core.library.alchemy.library import Library as SqliteLibrary from tagstudio.core.library.alchemy.models import Entry, TagAlias from tagstudio.core.library.json.library import Library as JsonLibrary from tagstudio.core.library.json.library import Tag as JsonTag -from tagstudio.qt.helpers.custom_runnable import CustomRunnable -from tagstudio.qt.helpers.function_iterator import FunctionIterator -from tagstudio.qt.helpers.qbutton_wrapper import QPushButtonWrapper +from tagstudio.qt.controllers.paged_panel_controller import PagedPanel +from tagstudio.qt.controllers.paged_panel_state import PagedPanelState from tagstudio.qt.translations import Translations -from tagstudio.qt.widgets.paged_panel.paged_body_wrapper import PagedBodyWrapper -from tagstudio.qt.widgets.paged_panel.paged_panel import PagedPanel -from tagstudio.qt.widgets.paged_panel.paged_panel_state import PagedPanelState +from tagstudio.qt.utils.custom_runnable import CustomRunnable +from tagstudio.qt.utils.function_iterator import FunctionIterator +from tagstudio.qt.views.paged_body_wrapper import PagedBodyWrapper +from tagstudio.qt.views.qbutton_wrapper import QPushButtonWrapper logger = structlog.get_logger(__name__) diff --git a/src/tagstudio/qt/modals/mirror_entries_modal.py b/src/tagstudio/qt/mixed/mirror_entries_modal.py similarity index 94% rename from src/tagstudio/qt/modals/mirror_entries_modal.py rename to src/tagstudio/qt/mixed/mirror_entries_modal.py index 3114d429..d67cf12e 100644 --- a/src/tagstudio/qt/modals/mirror_entries_modal.py +++ b/src/tagstudio/qt/mixed/mirror_entries_modal.py @@ -10,9 +10,9 @@ from PySide6.QtCore import Qt, Signal from PySide6.QtGui import QStandardItem, QStandardItemModel from PySide6.QtWidgets import QHBoxLayout, QLabel, QListView, QPushButton, QVBoxLayout, QWidget -from tagstudio.core.utils.dupe_files import DupeRegistry +from tagstudio.core.library.alchemy.registries.dupe_files_registry import DupeFilesRegistry +from tagstudio.qt.mixed.progress_bar import ProgressWidget from tagstudio.qt.translations import Translations -from tagstudio.qt.widgets.progress import ProgressWidget # Only import for type checking/autocompletion, will not be imported at runtime. if typing.TYPE_CHECKING: @@ -22,7 +22,7 @@ if typing.TYPE_CHECKING: class MirrorEntriesModal(QWidget): done = Signal() - def __init__(self, driver: "QtDriver", tracker: DupeRegistry): + def __init__(self, driver: "QtDriver", tracker: DupeFilesRegistry): super().__init__() self.driver = driver self.setWindowTitle(Translations["entries.mirror.window_title"]) diff --git a/src/tagstudio/qt/pagination.py b/src/tagstudio/qt/mixed/pagination.py similarity index 99% rename from src/tagstudio/qt/pagination.py rename to src/tagstudio/qt/mixed/pagination.py index 51cb3604..7a18e56c 100644 --- a/src/tagstudio/qt/pagination.py +++ b/src/tagstudio/qt/mixed/pagination.py @@ -13,8 +13,8 @@ from PySide6.QtGui import QIntValidator, QPixmap from PySide6.QtWidgets import QHBoxLayout, QLabel, QLineEdit, QSizePolicy, QWidget from tagstudio.qt.helpers.color_overlay import theme_fg_overlay -from tagstudio.qt.helpers.qbutton_wrapper import QPushButtonWrapper from tagstudio.qt.resource_manager import ResourceManager +from tagstudio.qt.views.qbutton_wrapper import QPushButtonWrapper class Pagination(QWidget, QObject): diff --git a/src/tagstudio/qt/widgets/progress.py b/src/tagstudio/qt/mixed/progress_bar.py similarity index 94% rename from src/tagstudio/qt/widgets/progress.py rename to src/tagstudio/qt/mixed/progress_bar.py index 6506581e..9dba568a 100644 --- a/src/tagstudio/qt/widgets/progress.py +++ b/src/tagstudio/qt/mixed/progress_bar.py @@ -8,8 +8,8 @@ from collections.abc import Callable from PySide6.QtCore import Qt, QThreadPool from PySide6.QtWidgets import QProgressDialog, QVBoxLayout, QWidget -from tagstudio.qt.helpers.custom_runnable import CustomRunnable -from tagstudio.qt.helpers.function_iterator import FunctionIterator +from tagstudio.qt.utils.custom_runnable import CustomRunnable +from tagstudio.qt.utils.function_iterator import FunctionIterator class ProgressWidget(QWidget): diff --git a/src/tagstudio/qt/modals/relink_entries_modal.py b/src/tagstudio/qt/mixed/relink_entries_modal.py similarity index 88% rename from src/tagstudio/qt/modals/relink_entries_modal.py rename to src/tagstudio/qt/mixed/relink_entries_modal.py index 81603a25..c966f873 100644 --- a/src/tagstudio/qt/modals/relink_entries_modal.py +++ b/src/tagstudio/qt/mixed/relink_entries_modal.py @@ -5,9 +5,9 @@ from PySide6.QtCore import QObject, Signal -from tagstudio.core.utils.unlinked_registry import UnlinkedRegistry +from tagstudio.core.library.alchemy.registries.unlinked_registry import UnlinkedRegistry +from tagstudio.qt.mixed.progress_bar import ProgressWidget from tagstudio.qt.translations import Translations -from tagstudio.qt.widgets.progress import ProgressWidget class RelinkUnlinkedEntries(QObject): diff --git a/src/tagstudio/qt/modals/remove_ignored_modal.py b/src/tagstudio/qt/mixed/remove_ignored_modal.py similarity index 94% rename from src/tagstudio/qt/modals/remove_ignored_modal.py rename to src/tagstudio/qt/mixed/remove_ignored_modal.py index b9e02789..0d45f094 100644 --- a/src/tagstudio/qt/modals/remove_ignored_modal.py +++ b/src/tagstudio/qt/mixed/remove_ignored_modal.py @@ -17,10 +17,10 @@ from PySide6.QtWidgets import ( QWidget, ) -from tagstudio.core.utils.ignored_registry import IgnoredRegistry -from tagstudio.qt.helpers.custom_runnable import CustomRunnable +from tagstudio.core.library.alchemy.registries.ignored_registry import IgnoredRegistry +from tagstudio.qt.mixed.progress_bar import ProgressWidget from tagstudio.qt.translations import Translations -from tagstudio.qt.widgets.progress import ProgressWidget +from tagstudio.qt.utils.custom_runnable import CustomRunnable # Only import for type checking/autocompletion, will not be imported at runtime. if TYPE_CHECKING: diff --git a/src/tagstudio/qt/modals/remove_unlinked_modal.py b/src/tagstudio/qt/mixed/remove_unlinked_modal.py similarity index 94% rename from src/tagstudio/qt/modals/remove_unlinked_modal.py rename to src/tagstudio/qt/mixed/remove_unlinked_modal.py index cfd3fca7..1b5353cb 100644 --- a/src/tagstudio/qt/modals/remove_unlinked_modal.py +++ b/src/tagstudio/qt/mixed/remove_unlinked_modal.py @@ -17,10 +17,10 @@ from PySide6.QtWidgets import ( QWidget, ) -from tagstudio.core.utils.unlinked_registry import UnlinkedRegistry -from tagstudio.qt.helpers.custom_runnable import CustomRunnable +from tagstudio.core.library.alchemy.registries.unlinked_registry import UnlinkedRegistry +from tagstudio.qt.mixed.progress_bar import ProgressWidget from tagstudio.qt.translations import Translations -from tagstudio.qt.widgets.progress import ProgressWidget +from tagstudio.qt.utils.custom_runnable import CustomRunnable # Only import for type checking/autocompletion, will not be imported at runtime. if TYPE_CHECKING: diff --git a/src/tagstudio/qt/modals/settings_panel.py b/src/tagstudio/qt/mixed/settings_panel.py similarity index 99% rename from src/tagstudio/qt/modals/settings_panel.py rename to src/tagstudio/qt/mixed/settings_panel.py index 344f143e..70424061 100644 --- a/src/tagstudio/qt/modals/settings_panel.py +++ b/src/tagstudio/qt/mixed/settings_panel.py @@ -21,14 +21,14 @@ from PySide6.QtWidgets import ( ) from tagstudio.core.enums import ShowFilepathOption, TagClickActionOption -from tagstudio.core.global_settings import ( +from tagstudio.qt.global_settings import ( DEFAULT_THUMB_CACHE_SIZE, MIN_THUMB_CACHE_SIZE, Splash, Theme, ) from tagstudio.qt.translations import DEFAULT_TRANSLATION, LANGUAGES, Translations -from tagstudio.qt.widgets.panel import PanelModal, PanelWidget +from tagstudio.qt.views.panel_modal import PanelModal, PanelWidget if TYPE_CHECKING: from tagstudio.qt.ts_qt import QtDriver diff --git a/src/tagstudio/qt/widgets/tag_color_label.py b/src/tagstudio/qt/mixed/tag_color_label.py similarity index 99% rename from src/tagstudio/qt/widgets/tag_color_label.py rename to src/tagstudio/qt/mixed/tag_color_label.py index 05cdacaf..39d5d96f 100644 --- a/src/tagstudio/qt/widgets/tag_color_label.py +++ b/src/tagstudio/qt/mixed/tag_color_label.py @@ -12,12 +12,12 @@ from PySide6.QtWidgets import QHBoxLayout, QPushButton, QVBoxLayout, QWidget from tagstudio.core.library.alchemy.models import TagColorGroup from tagstudio.qt.helpers.escape_text import escape_text -from tagstudio.qt.translations import Translations -from tagstudio.qt.widgets.tag import ( +from tagstudio.qt.mixed.tag_widget import ( get_border_color, get_highlight_color, get_text_color, ) +from tagstudio.qt.translations import Translations logger = structlog.get_logger(__name__) diff --git a/src/tagstudio/qt/modals/tag_color_manager.py b/src/tagstudio/qt/mixed/tag_color_manager.py similarity index 97% rename from src/tagstudio/qt/modals/tag_color_manager.py rename to src/tagstudio/qt/mixed/tag_color_manager.py index c3242656..d381fcac 100644 --- a/src/tagstudio/qt/modals/tag_color_manager.py +++ b/src/tagstudio/qt/mixed/tag_color_manager.py @@ -23,11 +23,11 @@ from PySide6.QtWidgets import ( from tagstudio.core.constants import RESERVED_NAMESPACE_PREFIX from tagstudio.core.enums import Theme -from tagstudio.qt.modals.build_namespace import BuildNamespacePanel +from tagstudio.qt.mixed.build_namespace import BuildNamespacePanel +from tagstudio.qt.mixed.color_box import ColorBoxWidget +from tagstudio.qt.mixed.field_widget import FieldContainer from tagstudio.qt.translations import Translations -from tagstudio.qt.widgets.color_box import ColorBoxWidget -from tagstudio.qt.widgets.fields import FieldContainer -from tagstudio.qt.widgets.panel import PanelModal +from tagstudio.qt.views.panel_modal import PanelModal logger = structlog.get_logger(__name__) diff --git a/src/tagstudio/qt/widgets/tag_color_preview.py b/src/tagstudio/qt/mixed/tag_color_preview.py similarity index 96% rename from src/tagstudio/qt/widgets/tag_color_preview.py rename to src/tagstudio/qt/mixed/tag_color_preview.py index 2e0fb584..8d8a7e8b 100644 --- a/src/tagstudio/qt/widgets/tag_color_preview.py +++ b/src/tagstudio/qt/mixed/tag_color_preview.py @@ -12,13 +12,9 @@ from PySide6.QtWidgets import QPushButton, QVBoxLayout, QWidget from tagstudio.core.library.alchemy.enums import TagColorEnum from tagstudio.core.library.alchemy.models import TagColorGroup -from tagstudio.core.palette import ColorType, get_tag_color +from tagstudio.qt.mixed.tag_widget import get_border_color, get_highlight_color, get_text_color +from tagstudio.qt.models.palette import ColorType, get_tag_color from tagstudio.qt.translations import Translations -from tagstudio.qt.widgets.tag import ( - get_border_color, - get_highlight_color, - get_text_color, -) if typing.TYPE_CHECKING: from tagstudio.core.library.alchemy.library import Library diff --git a/src/tagstudio/qt/modals/tag_color_selection.py b/src/tagstudio/qt/mixed/tag_color_selection.py similarity index 96% rename from src/tagstudio/qt/modals/tag_color_selection.py rename to src/tagstudio/qt/mixed/tag_color_selection.py index 70472c93..e6bacc1a 100644 --- a/src/tagstudio/qt/modals/tag_color_selection.py +++ b/src/tagstudio/qt/mixed/tag_color_selection.py @@ -21,15 +21,11 @@ from PySide6.QtWidgets import ( from tagstudio.core.library.alchemy.enums import TagColorEnum from tagstudio.core.library.alchemy.library import Library from tagstudio.core.library.alchemy.models import TagColorGroup -from tagstudio.core.palette import ColorType, get_tag_color -from tagstudio.qt.flowlayout import FlowLayout +from tagstudio.qt.mixed.tag_widget import get_border_color, get_highlight_color, get_text_color +from tagstudio.qt.models.palette import ColorType, get_tag_color from tagstudio.qt.translations import Translations -from tagstudio.qt.widgets.panel import PanelWidget -from tagstudio.qt.widgets.tag import ( - get_border_color, - get_highlight_color, - get_text_color, -) +from tagstudio.qt.views.layouts.flow_layout import FlowLayout +from tagstudio.qt.views.panel_modal import PanelWidget logger = structlog.get_logger(__name__) diff --git a/src/tagstudio/qt/modals/tag_database.py b/src/tagstudio/qt/mixed/tag_database.py similarity index 93% rename from src/tagstudio/qt/modals/tag_database.py rename to src/tagstudio/qt/mixed/tag_database.py index 9c8a2924..4ff6499e 100644 --- a/src/tagstudio/qt/modals/tag_database.py +++ b/src/tagstudio/qt/mixed/tag_database.py @@ -9,10 +9,10 @@ from PySide6.QtWidgets import QMessageBox, QPushButton from tagstudio.core.constants import RESERVED_TAG_END, RESERVED_TAG_START from tagstudio.core.library.alchemy.library import Library from tagstudio.core.library.alchemy.models import Tag -from tagstudio.qt.modals.build_tag import BuildTagPanel -from tagstudio.qt.modals.tag_search import TagSearchPanel +from tagstudio.qt.mixed.build_tag import BuildTagPanel +from tagstudio.qt.mixed.tag_search import TagSearchPanel from tagstudio.qt.translations import Translations -from tagstudio.qt.widgets.panel import PanelModal +from tagstudio.qt.views.panel_modal import PanelModal logger = structlog.get_logger(__name__) diff --git a/src/tagstudio/qt/modals/tag_search.py b/src/tagstudio/qt/mixed/tag_search.py similarity index 98% rename from src/tagstudio/qt/modals/tag_search.py rename to src/tagstudio/qt/mixed/tag_search.py index 4cc2b2f4..13ca4b0d 100644 --- a/src/tagstudio/qt/modals/tag_search.py +++ b/src/tagstudio/qt/mixed/tag_search.py @@ -27,10 +27,10 @@ from tagstudio.core.constants import RESERVED_TAG_END, RESERVED_TAG_START from tagstudio.core.library.alchemy.enums import BrowsingState, TagColorEnum from tagstudio.core.library.alchemy.library import Library from tagstudio.core.library.alchemy.models import Tag -from tagstudio.core.palette import ColorType, get_tag_color +from tagstudio.qt.mixed.tag_widget import TagWidget +from tagstudio.qt.models.palette import ColorType, get_tag_color from tagstudio.qt.translations import Translations -from tagstudio.qt.widgets.panel import PanelModal, PanelWidget -from tagstudio.qt.widgets.tag import TagWidget +from tagstudio.qt.views.panel_modal import PanelModal, PanelWidget logger = structlog.get_logger(__name__) diff --git a/src/tagstudio/qt/widgets/tag.py b/src/tagstudio/qt/mixed/tag_widget.py similarity index 99% rename from src/tagstudio/qt/widgets/tag.py rename to src/tagstudio/qt/mixed/tag_widget.py index cdce68a6..85b62c4e 100644 --- a/src/tagstudio/qt/widgets/tag.py +++ b/src/tagstudio/qt/mixed/tag_widget.py @@ -13,8 +13,8 @@ from PySide6.QtWidgets import QHBoxLayout, QLineEdit, QPushButton, QVBoxLayout, from tagstudio.core.library.alchemy.enums import TagColorEnum from tagstudio.core.library.alchemy.models import Tag -from tagstudio.core.palette import ColorType, get_tag_color from tagstudio.qt.helpers.escape_text import escape_text +from tagstudio.qt.models.palette import ColorType, get_tag_color from tagstudio.qt.translations import Translations logger = structlog.get_logger(__name__) diff --git a/src/tagstudio/qt/widgets/text.py b/src/tagstudio/qt/mixed/text_field.py similarity index 96% rename from src/tagstudio/qt/widgets/text.py rename to src/tagstudio/qt/mixed/text_field.py index aa6fcff3..d8052ce9 100644 --- a/src/tagstudio/qt/widgets/text.py +++ b/src/tagstudio/qt/mixed/text_field.py @@ -8,7 +8,7 @@ import re from PySide6.QtCore import Qt from PySide6.QtWidgets import QHBoxLayout, QLabel -from tagstudio.qt.widgets.fields import FieldWidget +from tagstudio.qt.mixed.field_widget import FieldWidget class TextWidget(FieldWidget): diff --git a/src/tagstudio/core/palette.py b/src/tagstudio/qt/models/palette.py similarity index 100% rename from src/tagstudio/core/palette.py rename to src/tagstudio/qt/models/palette.py diff --git a/src/tagstudio/qt/widgets/thumb_renderer.py b/src/tagstudio/qt/previews/renderer.py similarity index 99% rename from src/tagstudio/qt/widgets/thumb_renderer.py rename to src/tagstudio/qt/previews/renderer.py index 5ad1154f..7712d141 100644 --- a/src/tagstudio/qt/widgets/thumb_renderer.py +++ b/src/tagstudio/qt/previews/renderer.py @@ -55,19 +55,19 @@ from tagstudio.core.constants import ( FONT_SAMPLE_TEXT, ) from tagstudio.core.exceptions import NoRendererError -from tagstudio.core.global_settings import DEFAULT_CACHED_IMAGE_RES from tagstudio.core.library.ignore import Ignore from tagstudio.core.media_types import MediaCategories, MediaType -from tagstudio.core.palette import UI_COLORS, ColorType, UiColor, get_ui_color from tagstudio.core.utils.encoding import detect_char_encoding from tagstudio.core.utils.types import unwrap -from tagstudio.qt.helpers.blender_thumbnailer import blend_thumb +from tagstudio.qt.global_settings import DEFAULT_CACHED_IMAGE_RES from tagstudio.qt.helpers.color_overlay import theme_fg_overlay from tagstudio.qt.helpers.file_tester import is_readable_video -from tagstudio.qt.helpers.gradient import four_corner_gradient +from tagstudio.qt.helpers.gradients import four_corner_gradient from tagstudio.qt.helpers.image_effects import replace_transparent_pixels from tagstudio.qt.helpers.text_wrapper import wrap_full_text -from tagstudio.qt.helpers.vendored.pydub.audio_segment import ( +from tagstudio.qt.models.palette import UI_COLORS, ColorType, UiColor, get_ui_color +from tagstudio.qt.previews.vendored.blender_renderer import blend_thumb +from tagstudio.qt.previews.vendored.pydub.audio_segment import ( _AudioSegment as AudioSegment, ) from tagstudio.qt.resource_manager import ResourceManager diff --git a/src/tagstudio/qt/helpers/blender_thumbnailer.py b/src/tagstudio/qt/previews/vendored/blender_renderer.py similarity index 100% rename from src/tagstudio/qt/helpers/blender_thumbnailer.py rename to src/tagstudio/qt/previews/vendored/blender_renderer.py diff --git a/src/tagstudio/qt/helpers/vendored/ffmpeg.py b/src/tagstudio/qt/previews/vendored/ffmpeg.py similarity index 95% rename from src/tagstudio/qt/helpers/vendored/ffmpeg.py rename to src/tagstudio/qt/previews/vendored/ffmpeg.py index 2eb4bce1..e2d9a6c7 100644 --- a/src/tagstudio/qt/helpers/vendored/ffmpeg.py +++ b/src/tagstudio/qt/previews/vendored/ffmpeg.py @@ -12,7 +12,7 @@ from shutil import which import ffmpeg import structlog -from tagstudio.qt.helpers.silent_popen import silent_Popen, silent_run +from tagstudio.core.utils.silent_subprocess import silent_popen, silent_run logger = structlog.get_logger(__name__) @@ -69,7 +69,7 @@ def probe(filename, cmd=FFPROBE_CMD, timeout=None, **kwargs): args += [filename] # PATCHED - p = silent_Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + p = silent_popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) communicate_kwargs = {} if timeout is not None: communicate_kwargs["timeout"] = timeout diff --git a/src/tagstudio/qt/helpers/vendored/pydub/audio_segment.py b/src/tagstudio/qt/previews/vendored/pydub/audio_segment.py similarity index 99% rename from src/tagstudio/qt/helpers/vendored/pydub/audio_segment.py rename to src/tagstudio/qt/previews/vendored/pydub/audio_segment.py index 29a590d5..2baad076 100644 --- a/src/tagstudio/qt/helpers/vendored/pydub/audio_segment.py +++ b/src/tagstudio/qt/previews/vendored/pydub/audio_segment.py @@ -18,7 +18,7 @@ from tempfile import NamedTemporaryFile from pydub.logging_utils import log_conversion, log_subprocess_output from pydub.utils import fsdecode -from tagstudio.qt.helpers.vendored.ffmpeg import FFMPEG_CMD +from tagstudio.qt.previews.vendored.ffmpeg import FFMPEG_CMD try: from itertools import izip @@ -42,8 +42,8 @@ from pydub.utils import ( ratio_to_db, ) -from tagstudio.qt.helpers.silent_popen import silent_Popen -from tagstudio.qt.helpers.vendored.pydub.utils import _mediainfo_json +from tagstudio.core.utils.silent_subprocess import silent_popen +from tagstudio.qt.previews.vendored.pydub.utils import _mediainfo_json basestring = str xrange = range @@ -608,7 +608,7 @@ class _AudioSegment: with open(os.devnull, "rb") as devnull: # PATCHED - p = silent_Popen( + p = silent_popen( conversion_command, stdin=devnull, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) p_out, p_err = p.communicate() @@ -781,7 +781,7 @@ class _AudioSegment: log_conversion(conversion_command) # PATCHED - p = silent_Popen( + p = silent_popen( conversion_command, stdin=stdin_parameter, stdout=subprocess.PIPE, @@ -1008,7 +1008,7 @@ class _AudioSegment: # read stdin / write stdout with open(os.devnull, "rb") as devnull: # PATCHED - p = silent_Popen( + p = silent_popen( conversion_command, stdin=devnull, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) p_out, p_err = p.communicate() diff --git a/src/tagstudio/qt/helpers/vendored/pydub/utils.py b/src/tagstudio/qt/previews/vendored/pydub/utils.py similarity index 95% rename from src/tagstudio/qt/helpers/vendored/pydub/utils.py rename to src/tagstudio/qt/previews/vendored/pydub/utils.py index a325551d..4a4cb889 100644 --- a/src/tagstudio/qt/helpers/vendored/pydub/utils.py +++ b/src/tagstudio/qt/previews/vendored/pydub/utils.py @@ -8,8 +8,8 @@ from pydub.utils import ( get_extra_info, ) -from tagstudio.qt.helpers.silent_popen import silent_Popen -from tagstudio.qt.helpers.vendored.ffmpeg import FFPROBE_CMD +from tagstudio.core.utils.silent_subprocess import silent_popen +from tagstudio.qt.previews.vendored.ffmpeg import FFPROBE_CMD def _mediainfo_json(filepath, read_ahead_limit=-1): @@ -39,7 +39,7 @@ def _mediainfo_json(filepath, read_ahead_limit=-1): command = [prober, "-of", "json"] + command_args # PATCHED - res = silent_Popen( + res = silent_popen( command, stdin=stdin_parameter, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) output, stderr = res.communicate(input=stdin_data) diff --git a/src/tagstudio/qt/ts_qt.py b/src/tagstudio/qt/ts_qt.py index f73b7309..401560c2 100644 --- a/src/tagstudio/qt/ts_qt.py +++ b/src/tagstudio/qt/ts_qt.py @@ -49,11 +49,6 @@ import tagstudio.qt.resources_rc # noqa: F401 from tagstudio.core.constants import TAG_ARCHIVED, TAG_FAVORITE, VERSION, VERSION_BRANCH from tagstudio.core.driver import DriverMixin from tagstudio.core.enums import MacroID, SettingItems, ShowFilepathOption -from tagstudio.core.global_settings import ( - DEFAULT_GLOBAL_SETTINGS_PATH, - GlobalSettings, - Theme, -) from tagstudio.core.library.alchemy.enums import ( BrowsingState, FieldTypeEnum, @@ -64,44 +59,49 @@ from tagstudio.core.library.alchemy.fields import _FieldID from tagstudio.core.library.alchemy.library import Library, LibraryStatus from tagstudio.core.library.alchemy.models import Entry from tagstudio.core.library.ignore import Ignore +from tagstudio.core.library.refresh import RefreshTracker from tagstudio.core.media_types import MediaCategories -from tagstudio.core.palette import ColorType, UiColor, get_ui_color from tagstudio.core.query_lang.util import ParsingError from tagstudio.core.ts_core import TagStudioCore -from tagstudio.core.utils.refresh_dir import RefreshDirTracker +from tagstudio.core.utils.str_formatting import strip_web_protocol 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.controllers.ffmpeg_missing_message_box import FfmpegMissingMessageBox # this import has side-effect of import PySide resources -from tagstudio.qt.controller.fix_ignored_modal_controller import FixIgnoredEntriesModal -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 -from tagstudio.qt.helpers.function_iterator import FunctionIterator -from tagstudio.qt.helpers.vendored.ffmpeg import FFMPEG_CMD, FFPROBE_CMD -from tagstudio.qt.main_window import MainWindow -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.fix_dupes import FixDupeFilesModal -from tagstudio.qt.modals.fix_unlinked import FixUnlinkedEntriesModal -from tagstudio.qt.modals.folders_to_tags import FoldersToTagsModal -from tagstudio.qt.modals.settings_panel import SettingsPanel -from tagstudio.qt.modals.tag_color_manager import TagColorManager -from tagstudio.qt.modals.tag_database import TagDatabasePanel -from tagstudio.qt.modals.tag_search import TagSearchModal +from tagstudio.qt.controllers.fix_ignored_modal_controller import FixIgnoredEntriesModal +from tagstudio.qt.controllers.ignore_modal_controller import IgnoreModal +from tagstudio.qt.controllers.library_info_window_controller import LibraryInfoWindow +from tagstudio.qt.global_settings import ( + DEFAULT_GLOBAL_SETTINGS_PATH, + GlobalSettings, + Theme, +) +from tagstudio.qt.mixed.about_modal import AboutModal +from tagstudio.qt.mixed.build_tag import BuildTagPanel +from tagstudio.qt.mixed.drop_import_modal import DropImportModal +from tagstudio.qt.mixed.fix_dupe_files import FixDupeFilesModal +from tagstudio.qt.mixed.fix_unlinked import FixUnlinkedEntriesModal +from tagstudio.qt.mixed.folders_to_tags import FoldersToTagsModal +from tagstudio.qt.mixed.item_thumb import BadgeType, ItemThumb +from tagstudio.qt.mixed.migration_modal import JsonMigrationModal +from tagstudio.qt.mixed.progress_bar import ProgressWidget +from tagstudio.qt.mixed.settings_panel import SettingsPanel +from tagstudio.qt.mixed.tag_color_manager import TagColorManager +from tagstudio.qt.mixed.tag_database import TagDatabasePanel +from tagstudio.qt.mixed.tag_search import TagSearchModal +from tagstudio.qt.models.palette import ColorType, UiColor, get_ui_color from tagstudio.qt.platform_strings import trash_term +from tagstudio.qt.previews.renderer import ThumbRenderer +from tagstudio.qt.previews.vendored.ffmpeg import FFMPEG_CMD, FFPROBE_CMD from tagstudio.qt.resource_manager import ResourceManager -from tagstudio.qt.splash import SplashScreen from tagstudio.qt.translations import Translations -from tagstudio.qt.widgets.item_thumb import BadgeType, ItemThumb -from tagstudio.qt.widgets.migration_modal import JsonMigrationModal -from tagstudio.qt.widgets.panel import PanelModal -from tagstudio.qt.widgets.progress import ProgressWidget -from tagstudio.qt.widgets.thumb_renderer import ThumbRenderer +from tagstudio.qt.utils.custom_runnable import CustomRunnable +from tagstudio.qt.utils.file_deleter import delete_file +from tagstudio.qt.utils.function_iterator import FunctionIterator +from tagstudio.qt.views.main_window import MainWindow +from tagstudio.qt.views.panel_modal import PanelModal +from tagstudio.qt.views.splash import SplashScreen BADGE_TAGS = { BadgeType.FAVORITE: TAG_FAVORITE, @@ -590,7 +590,7 @@ class QtDriver(DriverMixin, QObject): # Check if FFmpeg or FFprobe are missing and show warning if so if not which(FFMPEG_CMD) or not which(FFPROBE_CMD): - FfmpegChecker().show() + FfmpegMissingMessageBox().show() self.app.exec() self.shutdown() @@ -1005,7 +1005,7 @@ class QtDriver(DriverMixin, QObject): def add_new_files_callback(self): """Run when user initiates adding new files to the Library.""" - tracker = RefreshDirTracker(self.lib) + tracker = RefreshTracker(self.lib) pw = ProgressWidget( cancel_button_text=None, @@ -1043,7 +1043,7 @@ class QtDriver(DriverMixin, QObject): ) QThreadPool.globalInstance().start(r) - def add_new_files_runnable(self, tracker: RefreshDirTracker): + def add_new_files_runnable(self, tracker: RefreshTracker): """Adds any known new files to the library and run default macros on them. Threaded method. diff --git a/src/tagstudio/qt/helpers/custom_runnable.py b/src/tagstudio/qt/utils/custom_runnable.py similarity index 100% rename from src/tagstudio/qt/helpers/custom_runnable.py rename to src/tagstudio/qt/utils/custom_runnable.py diff --git a/src/tagstudio/qt/helpers/file_deleter.py b/src/tagstudio/qt/utils/file_deleter.py similarity index 100% rename from src/tagstudio/qt/helpers/file_deleter.py rename to src/tagstudio/qt/utils/file_deleter.py diff --git a/src/tagstudio/qt/helpers/file_opener.py b/src/tagstudio/qt/utils/file_opener.py similarity index 96% rename from src/tagstudio/qt/helpers/file_opener.py rename to src/tagstudio/qt/utils/file_opener.py index 0227a0d0..3f613b78 100644 --- a/src/tagstudio/qt/helpers/file_opener.py +++ b/src/tagstudio/qt/utils/file_opener.py @@ -14,8 +14,8 @@ from PySide6.QtCore import Qt from PySide6.QtGui import QMouseEvent from PySide6.QtWidgets import QLabel, QWidget +from tagstudio.core.utils.silent_subprocess import silent_popen # pyright: ignore from tagstudio.core.utils.types import unwrap -from tagstudio.qt.helpers.silent_popen import silent_Popen logger = structlog.get_logger(__name__) @@ -45,7 +45,7 @@ def open_file(path: str | Path, file_manager: bool = False, windows_start_comman # For some reason, if the args are passed in a list, this will error when the # path has spaces, even while surrounded in double quotes. - silent_Popen( + silent_popen( command_name + command_arg, shell=True, close_fds=True, @@ -66,7 +66,7 @@ def open_file(path: str | Path, file_manager: bool = False, windows_start_comman ) else: command = f'"{normpath}"' - silent_Popen( + silent_popen( command, shell=True, close_fds=True, @@ -98,7 +98,7 @@ def open_file(path: str | Path, file_manager: bool = False, windows_start_comman command_args = [str(path)] command = shutil.which(command_name) if command is not None: - silent_Popen([command] + command_args, close_fds=True) + silent_popen([command] + command_args, close_fds=True) else: logger.info("Could not find command on system PATH", command=command_name) except Exception: diff --git a/src/tagstudio/qt/helpers/function_iterator.py b/src/tagstudio/qt/utils/function_iterator.py similarity index 100% rename from src/tagstudio/qt/helpers/function_iterator.py rename to src/tagstudio/qt/utils/function_iterator.py diff --git a/src/tagstudio/qt/widgets/clickable_label.py b/src/tagstudio/qt/views/clickable_label.py similarity index 68% rename from src/tagstudio/qt/widgets/clickable_label.py rename to src/tagstudio/qt/views/clickable_label.py index 6d14f63d..c7478b9f 100644 --- a/src/tagstudio/qt/widgets/clickable_label.py +++ b/src/tagstudio/qt/views/clickable_label.py @@ -3,17 +3,21 @@ # Created for TagStudio: https://github.com/CyanVoxel/TagStudio +from typing import override + from PySide6.QtCore import Signal +from PySide6.QtGui import QMouseEvent from PySide6.QtWidgets import QLabel class ClickableLabel(QLabel): - """A clickable Label widget.""" + """A clickable QLabel widget.""" clicked = Signal() def __init__(self): super().__init__() - def mousePressEvent(self, event): # noqa: N802 + @override + def mousePressEvent(self, ev: QMouseEvent): self.clicked.emit() diff --git a/src/tagstudio/qt/helpers/qslider_wrapper.py b/src/tagstudio/qt/views/clickable_slider.py similarity index 95% rename from src/tagstudio/qt/helpers/qslider_wrapper.py rename to src/tagstudio/qt/views/clickable_slider.py index 7aaf9f64..a683a74a 100644 --- a/src/tagstudio/qt/helpers/qslider_wrapper.py +++ b/src/tagstudio/qt/views/clickable_slider.py @@ -11,8 +11,8 @@ from PySide6.QtWidgets import QSlider, QStyle, QStyleOptionSlider logger = structlog.get_logger(__name__) -class QClickSlider(QSlider): - """Custom QSlider wrapper. +class ClickableSlider(QSlider): + """A clickable QSlider wrapper. The purpose of this wrapper is to allow us to set slider positions based on click events. diff --git a/src/tagstudio/qt/widgets/text_box_edit.py b/src/tagstudio/qt/views/edit_text_box_modal.py similarity index 93% rename from src/tagstudio/qt/widgets/text_box_edit.py rename to src/tagstudio/qt/views/edit_text_box_modal.py index 0af6f83f..3c3bce32 100644 --- a/src/tagstudio/qt/widgets/text_box_edit.py +++ b/src/tagstudio/qt/views/edit_text_box_modal.py @@ -5,7 +5,7 @@ from PySide6.QtWidgets import QPlainTextEdit, QVBoxLayout -from tagstudio.qt.widgets.panel import PanelWidget +from tagstudio.qt.views.panel_modal import PanelWidget class EditTextBox(PanelWidget): diff --git a/src/tagstudio/qt/widgets/text_line_edit.py b/src/tagstudio/qt/views/edit_text_line_modal.py similarity index 94% rename from src/tagstudio/qt/widgets/text_line_edit.py rename to src/tagstudio/qt/views/edit_text_line_modal.py index a737d9c6..5ee933cc 100644 --- a/src/tagstudio/qt/widgets/text_line_edit.py +++ b/src/tagstudio/qt/views/edit_text_line_modal.py @@ -5,7 +5,7 @@ from collections.abc import Callable from PySide6.QtWidgets import QLineEdit, QVBoxLayout -from tagstudio.qt.widgets.panel import PanelWidget +from tagstudio.qt.views.panel_modal import PanelWidget class EditTextLine(PanelWidget): diff --git a/src/tagstudio/qt/view/widgets/fix_ignored_modal_view.py b/src/tagstudio/qt/views/fix_ignored_modal_view.py similarity index 100% rename from src/tagstudio/qt/view/widgets/fix_ignored_modal_view.py rename to src/tagstudio/qt/views/fix_ignored_modal_view.py diff --git a/src/tagstudio/qt/view/widgets/ignore_modal_view.py b/src/tagstudio/qt/views/ignore_modal_view.py similarity index 96% rename from src/tagstudio/qt/view/widgets/ignore_modal_view.py rename to src/tagstudio/qt/views/ignore_modal_view.py index 62afcf52..7e7de161 100644 --- a/src/tagstudio/qt/view/widgets/ignore_modal_view.py +++ b/src/tagstudio/qt/views/ignore_modal_view.py @@ -16,7 +16,7 @@ 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 +from tagstudio.qt.views.panel_modal import PanelWidget logger = structlog.get_logger(__name__) diff --git a/src/tagstudio/qt/flowlayout.py b/src/tagstudio/qt/views/layouts/flow_layout.py similarity index 100% rename from src/tagstudio/qt/flowlayout.py rename to src/tagstudio/qt/views/layouts/flow_layout.py diff --git a/src/tagstudio/qt/view/widgets/library_info_window_view.py b/src/tagstudio/qt/views/library_info_window_view.py similarity index 100% rename from src/tagstudio/qt/view/widgets/library_info_window_view.py rename to src/tagstudio/qt/views/library_info_window_view.py diff --git a/src/tagstudio/qt/main_window.py b/src/tagstudio/qt/views/main_window.py similarity index 99% rename from src/tagstudio/qt/main_window.py rename to src/tagstudio/qt/views/main_window.py index bc7045d2..7c23e2ff 100644 --- a/src/tagstudio/qt/main_window.py +++ b/src/tagstudio/qt/views/main_window.py @@ -35,15 +35,15 @@ from PySide6.QtWidgets import ( from tagstudio.core.enums import ShowFilepathOption from tagstudio.core.library.alchemy.enums import SortingModeEnum -from tagstudio.qt.controller.widgets.preview_panel_controller import PreviewPanel -from tagstudio.qt.flowlayout import FlowLayout +from tagstudio.qt.controllers.preview_panel_controller import PreviewPanel from tagstudio.qt.helpers.color_overlay import theme_fg_overlay +from tagstudio.qt.mixed.landing import LandingWidget +from tagstudio.qt.mixed.pagination import Pagination from tagstudio.qt.mnemonics import assign_mnemonics -from tagstudio.qt.pagination import Pagination from tagstudio.qt.platform_strings import trash_term from tagstudio.qt.resource_manager import ResourceManager from tagstudio.qt.translations import Translations -from tagstudio.qt.widgets.landing import LandingWidget +from tagstudio.qt.views.layouts.flow_layout import FlowLayout # Only import for type checking/autocompletion, will not be imported at runtime. if typing.TYPE_CHECKING: diff --git a/src/tagstudio/qt/widgets/paged_panel/paged_body_wrapper.py b/src/tagstudio/qt/views/paged_body_wrapper.py similarity index 100% rename from src/tagstudio/qt/widgets/paged_panel/paged_body_wrapper.py rename to src/tagstudio/qt/views/paged_body_wrapper.py diff --git a/src/tagstudio/qt/widgets/panel.py b/src/tagstudio/qt/views/panel_modal.py similarity index 100% rename from src/tagstudio/qt/widgets/panel.py rename to src/tagstudio/qt/views/panel_modal.py diff --git a/src/tagstudio/qt/view/widgets/preview_panel_view.py b/src/tagstudio/qt/views/preview_panel_view.py similarity index 95% rename from src/tagstudio/qt/view/widgets/preview_panel_view.py rename to src/tagstudio/qt/views/preview_panel_view.py index 6bc961c3..5ae7004c 100644 --- a/src/tagstudio/qt/view/widgets/preview_panel_view.py +++ b/src/tagstudio/qt/views/preview_panel_view.py @@ -18,12 +18,12 @@ from PySide6.QtWidgets import ( from tagstudio.core.enums import Theme from tagstudio.core.library.alchemy.library import Library from tagstudio.core.library.alchemy.models import Entry -from tagstudio.core.palette import ColorType, UiColor, get_ui_color from tagstudio.core.utils.types import unwrap -from tagstudio.qt.controller.widgets.preview.preview_thumb_controller import PreviewThumb +from tagstudio.qt.controllers.preview_thumb_controller import PreviewThumb +from tagstudio.qt.mixed.field_containers import FieldContainers +from tagstudio.qt.mixed.file_attributes import FileAttributeData, FileAttributes +from tagstudio.qt.models.palette import ColorType, UiColor, get_ui_color from tagstudio.qt.translations import Translations -from tagstudio.qt.widgets.preview.field_containers import FieldContainers -from tagstudio.qt.widgets.preview.file_attributes import FileAttributeData, FileAttributes if typing.TYPE_CHECKING: from tagstudio.qt.ts_qt import QtDriver diff --git a/src/tagstudio/qt/view/widgets/preview/preview_thumb_view.py b/src/tagstudio/qt/views/preview_thumb_view.py similarity index 97% rename from src/tagstudio/qt/view/widgets/preview/preview_thumb_view.py rename to src/tagstudio/qt/views/preview_thumb_view.py index 5a16e0a4..6f4b0c2c 100644 --- a/src/tagstudio/qt/view/widgets/preview/preview_thumb_view.py +++ b/src/tagstudio/qt/views/preview_thumb_view.py @@ -13,12 +13,12 @@ from PySide6.QtWidgets import QHBoxLayout, QLabel, QPushButton, QStackedLayout, from tagstudio.core.library.alchemy.library import Library from tagstudio.core.media_types import MediaType -from tagstudio.qt.helpers.rounded_pixmap_style import RoundedPixmapStyle +from tagstudio.qt.mixed.file_attributes import FileAttributeData +from tagstudio.qt.mixed.media_player import MediaPlayer from tagstudio.qt.platform_strings import open_file_str, trash_term +from tagstudio.qt.previews.renderer import ThumbRenderer from tagstudio.qt.translations import Translations -from tagstudio.qt.widgets.media_player import MediaPlayer -from tagstudio.qt.widgets.preview.file_attributes import FileAttributeData -from tagstudio.qt.widgets.thumb_renderer import ThumbRenderer +from tagstudio.qt.views.styles.rounded_pixmap_style import RoundedPixmapStyle if TYPE_CHECKING: from tagstudio.qt.ts_qt import QtDriver diff --git a/src/tagstudio/qt/helpers/qbutton_wrapper.py b/src/tagstudio/qt/views/qbutton_wrapper.py similarity index 81% rename from src/tagstudio/qt/helpers/qbutton_wrapper.py rename to src/tagstudio/qt/views/qbutton_wrapper.py index 5539dc7c..e26703d5 100644 --- a/src/tagstudio/qt/helpers/qbutton_wrapper.py +++ b/src/tagstudio/qt/views/qbutton_wrapper.py @@ -4,8 +4,10 @@ from PySide6.QtWidgets import QPushButton +from typing_extensions import deprecated +@deprecated("Use QPushButton with 'catch warnings' to silence disconnect warnings instead.") class QPushButtonWrapper(QPushButton): """Custom QPushButton wrapper. diff --git a/src/tagstudio/qt/splash.py b/src/tagstudio/qt/views/splash.py similarity index 99% rename from src/tagstudio/qt/splash.py rename to src/tagstudio/qt/views/splash.py index 91ae7f99..fe139d17 100644 --- a/src/tagstudio/qt/splash.py +++ b/src/tagstudio/qt/views/splash.py @@ -12,7 +12,7 @@ from PySide6.QtGui import QColor, QFont, QPainter, QPen, QPixmap from PySide6.QtWidgets import QSplashScreen, QWidget from tagstudio.core.constants import VERSION, VERSION_BRANCH -from tagstudio.core.global_settings import Splash +from tagstudio.qt.global_settings import Splash from tagstudio.qt.resource_manager import ResourceManager logger = structlog.get_logger(__name__) diff --git a/src/tagstudio/qt/helpers/rounded_pixmap_style.py b/src/tagstudio/qt/views/styles/rounded_pixmap_style.py similarity index 68% rename from src/tagstudio/qt/helpers/rounded_pixmap_style.py rename to src/tagstudio/qt/views/styles/rounded_pixmap_style.py index 47c2b580..df83c5a0 100644 --- a/src/tagstudio/qt/helpers/rounded_pixmap_style.py +++ b/src/tagstudio/qt/views/styles/rounded_pixmap_style.py @@ -5,16 +5,22 @@ # Modified for TagStudio: https://github.com/CyanVoxel/TagStudio -from PySide6.QtGui import QBrush, QColor, QPainter, QPixmap +from typing import override + +from PySide6.QtCore import QRect +from PySide6.QtGui import QBrush, QColor, QImage, QPainter, QPixmap from PySide6.QtWidgets import QProxyStyle class RoundedPixmapStyle(QProxyStyle): - def __init__(self, radius=8): + def __init__(self, radius: int = 8): super().__init__() self._radius = radius - def drawItemPixmap(self, painter, rectangle, alignment, pixmap): # noqa: N802 + @override + def drawItemPixmap( + self, painter: QPainter, rect: QRect, alignment: int, pixmap: QPixmap | QImage + ): painter.save() pix = QPixmap(pixmap.size()) pix.fill(QColor("transparent")) @@ -24,5 +30,5 @@ class RoundedPixmapStyle(QProxyStyle): p.setRenderHint(QPainter.RenderHint.Antialiasing) p.drawRoundedRect(pixmap.rect(), self._radius, self._radius) p.end() - super().drawItemPixmap(painter, rectangle, alignment, pix) + super().drawItemPixmap(painter, rect, alignment, pix) painter.restore() diff --git a/src/tagstudio/qt/view/components/tag_box_view.py b/src/tagstudio/qt/views/tag_box_view.py similarity index 92% rename from src/tagstudio/qt/view/components/tag_box_view.py rename to src/tagstudio/qt/views/tag_box_view.py index f6183615..bf24a88c 100644 --- a/src/tagstudio/qt/view/components/tag_box_view.py +++ b/src/tagstudio/qt/views/tag_box_view.py @@ -9,9 +9,9 @@ import structlog from tagstudio.core.library.alchemy.library import Library from tagstudio.core.library.alchemy.models import Tag -from tagstudio.qt.flowlayout import FlowLayout -from tagstudio.qt.widgets.fields import FieldWidget -from tagstudio.qt.widgets.tag import TagWidget +from tagstudio.qt.mixed.field_widget import FieldWidget +from tagstudio.qt.mixed.tag_widget import TagWidget +from tagstudio.qt.views.layouts.flow_layout import FlowLayout if TYPE_CHECKING: from tagstudio.qt.ts_qt import QtDriver diff --git a/src/tagstudio/qt/widgets/thumb_button.py b/src/tagstudio/qt/views/thumb_button.py similarity index 91% rename from src/tagstudio/qt/widgets/thumb_button.py rename to src/tagstudio/qt/views/thumb_button.py index 1be2fb93..88f5f906 100644 --- a/src/tagstudio/qt/widgets/thumb_button.py +++ b/src/tagstudio/qt/views/thumb_button.py @@ -4,6 +4,7 @@ import sys +from typing import override from PySide6 import QtCore from PySide6.QtCore import QEvent @@ -18,11 +19,11 @@ from PySide6.QtGui import ( ) from PySide6.QtWidgets import QWidget -from tagstudio.qt.helpers.qbutton_wrapper import QPushButtonWrapper +from tagstudio.qt.views.qbutton_wrapper import QPushButtonWrapper class ThumbButton(QPushButtonWrapper): - def __init__(self, parent: QWidget, thumb_size: tuple[int, int]) -> None: # noqa: N802 + def __init__(self, parent: QWidget, thumb_size: tuple[int, int]) -> None: super().__init__(parent) self.thumb_size: tuple[int, int] = thumb_size self.hovered = False @@ -85,8 +86,9 @@ class ThumbButton(QPushButtonWrapper): self.hover_color.alpha(), ) - def paintEvent(self, event: QPaintEvent) -> None: # noqa: N802 - super().paintEvent(event) + @override + def paintEvent(self, arg__1: QPaintEvent) -> None: # type: ignore + super().paintEvent(arg__1) if self.hovered or self.selected: painter = QPainter() painter.begin(self) @@ -125,17 +127,19 @@ class ThumbButton(QPushButtonWrapper): painter.end() - def enterEvent(self, event: QEnterEvent) -> None: # noqa: N802 + @override + def enterEvent(self, event: QEnterEvent) -> None: # type: ignore self.hovered = True self.repaint() return super().enterEvent(event) - def leaveEvent(self, event: QEvent) -> None: # noqa: N802 + @override + def leaveEvent(self, event: QEvent) -> None: # type: ignore self.hovered = False self.repaint() return super().leaveEvent(event) - def set_selected(self, value: bool) -> None: # noqa: N802 + def set_selected(self, value: bool) -> None: if value != self.selected: self.selected = value self.repaint() diff --git a/tests/macros/test_dupe_entries.py b/tests/macros/test_dupe_files.py similarity index 88% rename from tests/macros/test_dupe_entries.py rename to tests/macros/test_dupe_files.py index ecaca5cb..e449bd55 100644 --- a/tests/macros/test_dupe_entries.py +++ b/tests/macros/test_dupe_files.py @@ -6,7 +6,7 @@ from pathlib import Path from tagstudio.core.library.alchemy.library import Library from tagstudio.core.library.alchemy.models import Entry -from tagstudio.core.utils.dupe_files import DupeRegistry +from tagstudio.core.library.alchemy.registries.dupe_files_registry import DupeFilesRegistry from tagstudio.core.utils.types import unwrap CWD = Path(__file__).parent @@ -30,7 +30,7 @@ def test_refresh_dupe_files(library: Library): library.add_entries([entry, entry2]) - registry = DupeRegistry(library=library) + registry = DupeFilesRegistry(library=library) dupe_file_path = CWD.parent / "fixtures" / "result.dupeguru" registry.refresh_dupe_files(dupe_file_path) diff --git a/tests/macros/test_folders_tags.py b/tests/macros/test_folders_tags.py index 0daa7da8..7beae3d8 100644 --- a/tests/macros/test_folders_tags.py +++ b/tests/macros/test_folders_tags.py @@ -3,7 +3,7 @@ # Created for TagStudio: https://github.com/CyanVoxel/TagStudio from tagstudio.core.library.alchemy.library import Library -from tagstudio.qt.modals.folders_to_tags import folders_to_tags +from tagstudio.qt.mixed.folders_to_tags import folders_to_tags def test_folders_to_tags(library: Library): diff --git a/tests/macros/test_missing_files.py b/tests/macros/test_missing_files.py index 9734a133..61bacce0 100644 --- a/tests/macros/test_missing_files.py +++ b/tests/macros/test_missing_files.py @@ -9,8 +9,8 @@ import pytest from tagstudio.core.library.alchemy.enums import BrowsingState from tagstudio.core.library.alchemy.library import Library +from tagstudio.core.library.alchemy.registries.unlinked_registry import UnlinkedRegistry from tagstudio.core.utils.types import unwrap -from tagstudio.core.utils.unlinked_registry import UnlinkedRegistry CWD = Path(__file__).parent diff --git a/tests/macros/test_refresh_dir.py b/tests/macros/test_refresh_dir.py index f8651fc3..ebf7292b 100644 --- a/tests/macros/test_refresh_dir.py +++ b/tests/macros/test_refresh_dir.py @@ -9,7 +9,7 @@ import pytest from tagstudio.core.enums import LibraryPrefs from tagstudio.core.library.alchemy.library import Library -from tagstudio.core.utils.refresh_dir import RefreshDirTracker +from tagstudio.core.library.refresh import RefreshTracker from tagstudio.core.utils.types import unwrap CWD = Path(__file__).parent @@ -22,7 +22,7 @@ def test_refresh_new_files(library: Library, exclude_mode: bool): # Given library.set_prefs(LibraryPrefs.IS_EXCLUDE_LIST, exclude_mode) library.set_prefs(LibraryPrefs.EXTENSION_LIST, [".md"]) - registry = RefreshDirTracker(library=library) + registry = RefreshTracker(library=library) library.included_files.clear() (library_dir / "FOO.MD").touch() diff --git a/tests/qt/test_build_tag_panel.py b/tests/qt/test_build_tag_panel.py index 3c92b7d1..9ae15726 100644 --- a/tests/qt/test_build_tag_panel.py +++ b/tests/qt/test_build_tag_panel.py @@ -10,7 +10,7 @@ from pytestqt.qtbot import QtBot from tagstudio.core.library.alchemy.library import Library from tagstudio.core.library.alchemy.models import Tag, TagAlias from tagstudio.core.utils.types import unwrap -from tagstudio.qt.modals.build_tag import BuildTagPanel, CustomTableItem +from tagstudio.qt.mixed.build_tag import BuildTagPanel, CustomTableItem from tagstudio.qt.translations import Translations diff --git a/tests/qt/test_field_containers.py b/tests/qt/test_field_containers.py index 3090437e..2b992114 100644 --- a/tests/qt/test_field_containers.py +++ b/tests/qt/test_field_containers.py @@ -6,7 +6,7 @@ from tagstudio.core.library.alchemy.library import Library from tagstudio.core.library.alchemy.models import Entry, Tag from tagstudio.core.utils.types import unwrap -from tagstudio.qt.controller.widgets.preview_panel_controller import PreviewPanel +from tagstudio.qt.controllers.preview_panel_controller import PreviewPanel from tagstudio.qt.ts_qt import QtDriver diff --git a/tests/qt/test_file_path_options.py b/tests/qt/test_file_path_options.py index d9bbcf30..412cd56f 100644 --- a/tests/qt/test_file_path_options.py +++ b/tests/qt/test_file_path_options.py @@ -19,8 +19,8 @@ from tagstudio.core.enums import ShowFilepathOption from tagstudio.core.library.alchemy.library import Library, LibraryStatus from tagstudio.core.library.alchemy.models import Entry from tagstudio.core.utils.types import unwrap -from tagstudio.qt.controller.widgets.preview_panel_controller import PreviewPanel -from tagstudio.qt.modals.settings_panel import SettingsPanel +from tagstudio.qt.controllers.preview_panel_controller import PreviewPanel +from tagstudio.qt.mixed.settings_panel import SettingsPanel from tagstudio.qt.ts_qt import QtDriver diff --git a/tests/qt/test_flow_widget.py b/tests/qt/test_flow_widget.py index 74cec926..115ded7a 100644 --- a/tests/qt/test_flow_widget.py +++ b/tests/qt/test_flow_widget.py @@ -6,7 +6,7 @@ from PySide6.QtCore import QRect from PySide6.QtWidgets import QPushButton, QWidget -from tagstudio.qt.flowlayout import FlowLayout +from tagstudio.qt.views.layouts.flow_layout import FlowLayout def test_flow_layout_happy_path(): diff --git a/tests/qt/test_folders_to_tags.py b/tests/qt/test_folders_to_tags.py index 7a7637e2..eebee999 100644 --- a/tests/qt/test_folders_to_tags.py +++ b/tests/qt/test_folders_to_tags.py @@ -4,7 +4,7 @@ from tagstudio.core.library.alchemy.library import Library -from tagstudio.qt.modals.folders_to_tags import BranchData, generate_preview_data +from tagstudio.qt.mixed.folders_to_tags import BranchData, generate_preview_data def test_generate_preview_data(library: Library, snapshot: BranchData): diff --git a/tests/qt/test_global_settings.py b/tests/qt/test_global_settings.py index 27a64e09..95d6b5f6 100644 --- a/tests/qt/test_global_settings.py +++ b/tests/qt/test_global_settings.py @@ -5,7 +5,7 @@ from pathlib import Path -from tagstudio.core.global_settings import GlobalSettings, Theme +from tagstudio.qt.global_settings import GlobalSettings, Theme def test_read_settings(library_dir: Path): diff --git a/tests/qt/test_item_thumb.py b/tests/qt/test_item_thumb.py index 5f170e28..a2662a1d 100644 --- a/tests/qt/test_item_thumb.py +++ b/tests/qt/test_item_thumb.py @@ -6,8 +6,8 @@ import pytest from tagstudio.core.library.alchemy.enums import ItemType +from tagstudio.qt.mixed.item_thumb import BadgeType, ItemThumb from tagstudio.qt.ts_qt import QtDriver -from tagstudio.qt.widgets.item_thumb import BadgeType, ItemThumb @pytest.mark.parametrize("new_value", (True, False)) diff --git a/tests/qt/test_preview_panel.py b/tests/qt/test_preview_panel.py index 38c0bf2b..12282c9b 100644 --- a/tests/qt/test_preview_panel.py +++ b/tests/qt/test_preview_panel.py @@ -5,7 +5,7 @@ from tagstudio.core.library.alchemy.library import Library from tagstudio.core.library.alchemy.models import Entry -from tagstudio.qt.controller.widgets.preview_panel_controller import PreviewPanel +from tagstudio.qt.controllers.preview_panel_controller import PreviewPanel from tagstudio.qt.ts_qt import QtDriver diff --git a/tests/qt/test_qt_driver.py b/tests/qt/test_qt_driver.py index 508844df..003179a8 100644 --- a/tests/qt/test_qt_driver.py +++ b/tests/qt/test_qt_driver.py @@ -5,8 +5,8 @@ from tagstudio.core.library.alchemy.enums import BrowsingState, ItemType from tagstudio.core.utils.types import unwrap +from tagstudio.qt.mixed.item_thumb import ItemThumb from tagstudio.qt.ts_qt import QtDriver -from tagstudio.qt.widgets.item_thumb import ItemThumb def test_browsing_state_update(qt_driver: QtDriver): diff --git a/tests/qt/test_tag_panel.py b/tests/qt/test_tag_panel.py index 6b79fb44..0d813da6 100644 --- a/tests/qt/test_tag_panel.py +++ b/tests/qt/test_tag_panel.py @@ -7,7 +7,7 @@ from pytestqt.qtbot import QtBot from tagstudio.core.library.alchemy.library import Library from tagstudio.core.library.alchemy.models import Tag -from tagstudio.qt.modals.build_tag import BuildTagPanel +from tagstudio.qt.mixed.build_tag import BuildTagPanel from tagstudio.qt.ts_qt import QtDriver diff --git a/tests/qt/test_tag_search_panel.py b/tests/qt/test_tag_search_panel.py index 6bfe415b..9045fd8a 100644 --- a/tests/qt/test_tag_search_panel.py +++ b/tests/qt/test_tag_search_panel.py @@ -6,7 +6,7 @@ from pytestqt.qtbot import QtBot from tagstudio.core.library.alchemy.library import Library -from tagstudio.qt.modals.tag_search import TagSearchPanel +from tagstudio.qt.mixed.tag_search import TagSearchPanel def test_update_tags(qtbot: QtBot, library: Library): diff --git a/tests/test_driver.py b/tests/test_driver.py index 620f9e0a..903cf1aa 100644 --- a/tests/test_driver.py +++ b/tests/test_driver.py @@ -9,8 +9,8 @@ from PySide6.QtCore import QSettings from tagstudio.core.driver import DriverMixin from tagstudio.core.enums import SettingItems -from tagstudio.core.global_settings import GlobalSettings from tagstudio.core.library.alchemy.library import LibraryStatus +from tagstudio.qt.global_settings import GlobalSettings class TestDriver(DriverMixin): diff --git a/tests/test_json_migration.py b/tests/test_json_migration.py index c96e2809..25ad8fc1 100644 --- a/tests/test_json_migration.py +++ b/tests/test_json_migration.py @@ -7,7 +7,7 @@ from pathlib import Path from time import time from tagstudio.core.enums import LibraryPrefs -from tagstudio.qt.widgets.migration_modal import JsonMigrationModal +from tagstudio.qt.mixed.migration_modal import JsonMigrationModal CWD = Path(__file__)