mirror of
https://github.com/TagStudioDev/TagStudio.git
synced 2026-01-28 22:01:24 +00:00
refactor!: restructure qt layout, untangle from backend (#1095)
* refactor: untangle backend and frontend files * refactor: more structure organizing * refactor: rename silent_subprocess.py * refactor: update qt ui structure to pure mvc + temporarily mixed * refactor: pluralize MVC folders
This commit is contained in:
committed by
GitHub
parent
fff967617b
commit
f49cb4fade
6
STYLE.md
6
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 `<component>_view.py` there is a `<component>_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 `<component>_view.py` there is a `<component>_controller.py` at the same location in the other subdirectory and vice versa.
|
||||
|
||||
Typically the classes should look like this:
|
||||
```py
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
@@ -12,7 +12,7 @@ logger = structlog.get_logger()
|
||||
|
||||
|
||||
@dataclass
|
||||
class DupeRegistry:
|
||||
class DupeFilesRegistry:
|
||||
"""State handler for DupeGuru results."""
|
||||
|
||||
library: Library
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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"]
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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__)
|
||||
|
||||
|
||||
@@ -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/"
|
||||
@@ -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:
|
||||
@@ -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)
|
||||
@@ -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:
|
||||
@@ -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__)
|
||||
|
||||
@@ -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:
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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.
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
@@ -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__)
|
||||
|
||||
@@ -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__)
|
||||
|
||||
@@ -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__)
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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")
|
||||
@@ -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:
|
||||
@@ -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()
|
||||
@@ -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
|
||||
@@ -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:
|
||||
@@ -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)
|
||||
@@ -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(
|
||||
@@ -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__)
|
||||
|
||||
@@ -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"])
|
||||
@@ -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):
|
||||
@@ -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):
|
||||
@@ -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):
|
||||
@@ -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:
|
||||
@@ -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:
|
||||
@@ -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
|
||||
@@ -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__)
|
||||
|
||||
@@ -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__)
|
||||
|
||||
@@ -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
|
||||
@@ -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__)
|
||||
|
||||
@@ -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__)
|
||||
|
||||
@@ -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__)
|
||||
|
||||
@@ -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__)
|
||||
@@ -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):
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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()
|
||||
@@ -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)
|
||||
@@ -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.
|
||||
|
||||
@@ -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:
|
||||
@@ -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()
|
||||
@@ -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.
|
||||
@@ -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):
|
||||
@@ -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):
|
||||
@@ -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__)
|
||||
|
||||
@@ -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:
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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.
|
||||
|
||||
@@ -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__)
|
||||
@@ -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()
|
||||
@@ -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
|
||||
@@ -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()
|
||||
@@ -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)
|
||||
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user