mirror of
https://github.com/TagStudioDev/TagStudio.git
synced 2026-01-28 22:01:24 +00:00
refactor(preview_panel): mvc split (#952)
* refactor: basic split * fix: renaming and usage test didn't work for the tests * fix: tests * refactor: restructuring * refactor: further separation and lots of related changes * refactor: remove last reference to a widget from controller * refactor: address todo * fix: failing tests and mypy compaint * refactor: move control logic to controller * refactor: more readable button style * fix: set_selection was called with invalid argument
This commit is contained in:
@@ -84,7 +84,8 @@ qt_api = "pyside6"
|
||||
|
||||
[tool.pyright]
|
||||
ignore = [".venv/**"]
|
||||
include = ["src/tagstudio/**"]
|
||||
include = ["src/tagstudio", "tests"]
|
||||
extraPaths = ["src/tagstudio", "tests"]
|
||||
reportAny = false
|
||||
reportIgnoreCommentWithoutRule = false
|
||||
reportImplicitStringConcatenation = false
|
||||
|
||||
@@ -674,7 +674,7 @@ class Library:
|
||||
start_time = time.time()
|
||||
entry = session.scalar(entry_stmt)
|
||||
if with_tags:
|
||||
tags = set(session.scalars(tag_stmt)) # pyright: ignore [reportPossiblyUnboundVariable]
|
||||
tags = set(session.scalars(tag_stmt)) # pyright: ignore[reportPossiblyUnboundVariable]
|
||||
end_time = time.time()
|
||||
logger.info(
|
||||
f"[Library] Time it took to get entry: "
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
import typing
|
||||
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
|
||||
|
||||
if typing.TYPE_CHECKING:
|
||||
from tagstudio.qt.ts_qt import QtDriver
|
||||
|
||||
|
||||
class PreviewPanel(PreviewPanelView):
|
||||
def __init__(self, library: Library, driver: "QtDriver"):
|
||||
super().__init__(library, driver)
|
||||
|
||||
self.__add_field_modal = AddFieldModal(self.lib)
|
||||
self.__add_tag_modal = TagSearchModal(self.lib, is_tag_chooser=True)
|
||||
|
||||
def _add_field_button_callback(self):
|
||||
self.__add_field_modal.show()
|
||||
|
||||
def _add_tag_button_callback(self):
|
||||
self.__add_tag_modal.show()
|
||||
|
||||
def _set_selection_callback(self):
|
||||
with catch_warnings(record=True):
|
||||
self.__add_field_modal.done.disconnect()
|
||||
self.__add_tag_modal.tsp.tag_chosen.disconnect()
|
||||
|
||||
self.__add_field_modal.done.connect(self._add_field_to_selected)
|
||||
self.__add_tag_modal.tsp.tag_chosen.connect(self._add_tag_to_selected)
|
||||
|
||||
def _add_field_to_selected(self, field_list: list[QListWidgetItem]):
|
||||
self._fields.add_field_to_selected(field_list)
|
||||
if len(self._selected) == 1:
|
||||
self._fields.update_from_entry(self._selected[0])
|
||||
|
||||
def _add_tag_to_selected(self, tag_id: int):
|
||||
self._fields.add_tags_to_selected(tag_id)
|
||||
if len(self._selected) == 1:
|
||||
self._fields.update_from_entry(self._selected[0])
|
||||
@@ -33,12 +33,12 @@ 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.pagination import Pagination
|
||||
from tagstudio.qt.platform_strings import trash_term
|
||||
from tagstudio.qt.translations import Translations
|
||||
from tagstudio.qt.widgets.landing import LandingWidget
|
||||
from tagstudio.qt.widgets.preview_panel import PreviewPanel
|
||||
|
||||
# Only import for type checking/autocompletion, will not be imported at runtime.
|
||||
if typing.TYPE_CHECKING:
|
||||
|
||||
@@ -30,7 +30,7 @@ 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 TagSearchPanel
|
||||
from tagstudio.qt.modals.tag_search import TagSearchModal
|
||||
from tagstudio.qt.translations import Translations
|
||||
from tagstudio.qt.widgets.panel import PanelModal, PanelWidget
|
||||
from tagstudio.qt.widgets.tag import (
|
||||
@@ -166,9 +166,8 @@ class BuildTagPanel(PanelWidget):
|
||||
if tag is not None:
|
||||
exclude_ids.append(tag.id)
|
||||
|
||||
tsp = TagSearchPanel(self.lib, exclude_ids)
|
||||
tsp.tag_chosen.connect(lambda x: self.add_parent_tag_callback(x))
|
||||
self.add_tag_modal = PanelModal(tsp, Translations["tag.parent_tags.add"])
|
||||
self.add_tag_modal = TagSearchModal(self.lib, exclude_ids)
|
||||
self.add_tag_modal.tsp.tag_chosen.connect(lambda x: self.add_parent_tag_callback(x))
|
||||
self.parent_tags_add_button.clicked.connect(self.add_tag_modal.show)
|
||||
|
||||
# Color ----------------------------------------------------------------
|
||||
|
||||
@@ -227,7 +227,9 @@ class FoldersToTagsModal(QWidget):
|
||||
def on_apply(self):
|
||||
folders_to_tags(self.library)
|
||||
self.close()
|
||||
self.driver.main_window.preview_panel.update_widgets(update_preview=False)
|
||||
self.driver.main_window.preview_panel.set_selection(
|
||||
self.driver.selected, update_preview=False
|
||||
)
|
||||
|
||||
@override
|
||||
def showEvent(self, event: QtGui.QShowEvent):
|
||||
|
||||
@@ -87,7 +87,7 @@ class MirrorEntriesModal(QWidget):
|
||||
pw.from_iterable_function(
|
||||
self.mirror_entries_runnable,
|
||||
displayed_text,
|
||||
self.driver.main_window.preview_panel.update_widgets,
|
||||
lambda s=self.driver.selected: self.driver.main_window.preview_panel.set_selection(s),
|
||||
self.done.emit,
|
||||
)
|
||||
|
||||
|
||||
@@ -263,7 +263,7 @@ class SettingsPanel(PanelWidget):
|
||||
# Apply changes
|
||||
# Show File Path
|
||||
driver.update_recent_lib_menu()
|
||||
driver.main_window.preview_panel.update_widgets()
|
||||
driver.main_window.preview_panel.set_selection(self.driver.selected)
|
||||
library_directory = driver.lib.library_dir
|
||||
if settings["show_filepath"] == ShowFilepathOption.SHOW_FULL_PATHS:
|
||||
display_path = library_directory or ""
|
||||
|
||||
@@ -124,7 +124,7 @@ class TagColorManager(QWidget):
|
||||
self.setup_color_groups(),
|
||||
()
|
||||
if len(self.driver.selected) < 1
|
||||
else self.driver.main_window.preview_panel.fields.update_from_entry(
|
||||
else self.driver.main_window.preview_panel.field_containers_widget.update_from_entry( # noqa: E501
|
||||
self.driver.selected[0], update_badges=False
|
||||
),
|
||||
)
|
||||
@@ -141,7 +141,7 @@ class TagColorManager(QWidget):
|
||||
self.setup_color_groups(),
|
||||
()
|
||||
if len(self.driver.selected) < 1
|
||||
else self.driver.main_window.preview_panel.fields.update_from_entry(
|
||||
else self.driver.main_window.preview_panel.field_containers_widget.update_from_entry( # noqa: E501
|
||||
self.driver.selected[0], update_badges=False
|
||||
),
|
||||
),
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
|
||||
import contextlib
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import TYPE_CHECKING, Union
|
||||
from warnings import catch_warnings
|
||||
|
||||
import structlog
|
||||
@@ -39,10 +39,32 @@ if TYPE_CHECKING:
|
||||
from tagstudio.qt.ts_qt import QtDriver
|
||||
|
||||
|
||||
class TagSearchModal(PanelModal):
|
||||
tsp: "TagSearchPanel"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
library: Library,
|
||||
exclude: list[int] | None = None,
|
||||
is_tag_chooser: bool = True,
|
||||
done_callback=None,
|
||||
save_callback=None,
|
||||
has_save=False,
|
||||
):
|
||||
self.tsp = TagSearchPanel(library, exclude, is_tag_chooser)
|
||||
super().__init__(
|
||||
self.tsp,
|
||||
Translations["tag.add.plural"],
|
||||
done_callback=done_callback,
|
||||
save_callback=save_callback,
|
||||
has_save=has_save,
|
||||
)
|
||||
|
||||
|
||||
class TagSearchPanel(PanelWidget):
|
||||
tag_chosen = Signal(int)
|
||||
lib: Library
|
||||
driver: "QtDriver"
|
||||
driver: Union["QtDriver", None]
|
||||
is_initialized: bool = False
|
||||
first_tag_id: int | None = None
|
||||
is_tag_chooser: bool
|
||||
@@ -56,7 +78,7 @@ class TagSearchPanel(PanelWidget):
|
||||
def __init__(
|
||||
self,
|
||||
library: Library,
|
||||
exclude: list[int] = None,
|
||||
exclude: list[int] | None = None,
|
||||
is_tag_chooser: bool = True,
|
||||
):
|
||||
super().__init__()
|
||||
@@ -194,6 +216,7 @@ class TagSearchPanel(PanelWidget):
|
||||
create_button: QPushButton | None = None
|
||||
if self.create_button_in_layout and self.scroll_layout.count():
|
||||
create_button = self.scroll_layout.takeAt(self.scroll_layout.count() - 1).widget() # type: ignore
|
||||
assert create_button is not None
|
||||
create_button.deleteLater()
|
||||
self.create_button_in_layout = False
|
||||
|
||||
@@ -264,7 +287,8 @@ class TagSearchPanel(PanelWidget):
|
||||
self.scroll_layout.addWidget(new_tw)
|
||||
|
||||
# Assign the tag to the widget at the given index.
|
||||
tag_widget: TagWidget = self.scroll_layout.itemAt(index).widget()
|
||||
tag_widget: TagWidget = self.scroll_layout.itemAt(index).widget() # pyright: ignore[reportAssignmentType]
|
||||
assert isinstance(tag_widget, TagWidget)
|
||||
tag_widget.set_tag(tag)
|
||||
|
||||
# Set tag widget viability and potentially return early
|
||||
@@ -288,11 +312,11 @@ class TagSearchPanel(PanelWidget):
|
||||
tag_widget.on_remove.connect(lambda t=tag: self.delete_tag(t))
|
||||
tag_widget.bg_button.clicked.connect(lambda: self.tag_chosen.emit(tag_id))
|
||||
|
||||
if self.driver:
|
||||
if self.driver is not None:
|
||||
tag_widget.search_for_tag_action.triggered.connect(
|
||||
lambda checked=False, tag_id=tag.id: (
|
||||
self.driver.main_window.search_field.setText(f"tag_id:{tag_id}"),
|
||||
self.driver.update_browsing_state(BrowsingState.from_tag_id(tag_id)),
|
||||
lambda checked=False, tag_id=tag.id, driver=self.driver: (
|
||||
driver.main_window.search_field.setText(f"tag_id:{tag_id}"),
|
||||
driver.update_browsing_state(BrowsingState.from_tag_id(tag_id)),
|
||||
)
|
||||
)
|
||||
tag_widget.search_for_tag_action.setEnabled(True)
|
||||
|
||||
@@ -83,7 +83,7 @@ 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 TagSearchPanel
|
||||
from tagstudio.qt.modals.tag_search import TagSearchModal
|
||||
from tagstudio.qt.platform_strings import trash_term
|
||||
from tagstudio.qt.resource_manager import ResourceManager
|
||||
from tagstudio.qt.splash import Splash
|
||||
@@ -173,7 +173,6 @@ class QtDriver(DriverMixin, QObject):
|
||||
tag_manager_panel: PanelModal | None = None
|
||||
color_manager_panel: TagColorManager | None = None
|
||||
file_extension_panel: PanelModal | None = None
|
||||
tag_search_panel: TagSearchPanel | None = None
|
||||
add_tag_modal: PanelModal | None = None
|
||||
folders_modal: FoldersToTagsModal
|
||||
about_modal: AboutModal
|
||||
@@ -364,8 +363,8 @@ class QtDriver(DriverMixin, QObject):
|
||||
self.tag_manager_panel = PanelModal(
|
||||
widget=TagDatabasePanel(self, self.lib),
|
||||
title=Translations["tag_manager.title"],
|
||||
done_callback=lambda: self.main_window.preview_panel.update_widgets(
|
||||
update_preview=False
|
||||
done_callback=lambda s=self.selected: self.main_window.preview_panel.set_selection(
|
||||
s, update_preview=False
|
||||
),
|
||||
has_save=False,
|
||||
)
|
||||
@@ -374,16 +373,12 @@ class QtDriver(DriverMixin, QObject):
|
||||
self.color_manager_panel = TagColorManager(self)
|
||||
|
||||
# Initialize the Tag Search panel
|
||||
self.tag_search_panel = TagSearchPanel(self.lib, is_tag_chooser=True)
|
||||
self.tag_search_panel.set_driver(self)
|
||||
self.add_tag_modal = PanelModal(
|
||||
widget=self.tag_search_panel,
|
||||
title=Translations["tag.add.plural"],
|
||||
)
|
||||
self.tag_search_panel.tag_chosen.connect(
|
||||
lambda t: (
|
||||
self.add_tag_modal = TagSearchModal(self.lib, is_tag_chooser=True)
|
||||
self.add_tag_modal.tsp.set_driver(self)
|
||||
self.add_tag_modal.tsp.tag_chosen.connect(
|
||||
lambda t, s=self.selected: (
|
||||
self.add_tags_to_selected_callback(t),
|
||||
self.main_window.preview_panel.update_widgets(),
|
||||
self.main_window.preview_panel.set_selection(s),
|
||||
)
|
||||
)
|
||||
|
||||
@@ -536,12 +531,12 @@ class QtDriver(DriverMixin, QObject):
|
||||
|
||||
self.main_window.search_field.textChanged.connect(self.update_completions_list)
|
||||
|
||||
self.main_window.preview_panel.fields.archived_updated.connect(
|
||||
self.main_window.preview_panel.field_containers_widget.archived_updated.connect(
|
||||
lambda hidden: self.update_badges(
|
||||
{BadgeType.ARCHIVED: hidden}, origin_id=0, add_tags=False
|
||||
)
|
||||
)
|
||||
self.main_window.preview_panel.fields.favorite_updated.connect(
|
||||
self.main_window.preview_panel.field_containers_widget.favorite_updated.connect(
|
||||
lambda hidden: self.update_badges(
|
||||
{BadgeType.FAVORITE: hidden}, origin_id=0, add_tags=False
|
||||
)
|
||||
@@ -709,7 +704,7 @@ class QtDriver(DriverMixin, QObject):
|
||||
self.cached_values.sync()
|
||||
|
||||
# Reset library state
|
||||
self.main_window.preview_panel.update_widgets()
|
||||
self.main_window.preview_panel.set_selection(self.selected)
|
||||
self.main_window.search_field.setText("")
|
||||
scrollbar: QScrollArea = self.main_window.entry_scroll_area
|
||||
scrollbar.verticalScrollBar().setValue(0)
|
||||
@@ -733,7 +728,7 @@ class QtDriver(DriverMixin, QObject):
|
||||
self.set_clipboard_menu_viability()
|
||||
self.set_select_actions_visibility()
|
||||
|
||||
self.main_window.preview_panel.update_widgets()
|
||||
self.main_window.preview_panel.set_selection(self.selected)
|
||||
self.main_window.toggle_landing_page(enabled=True)
|
||||
self.main_window.pagination.setHidden(True)
|
||||
try:
|
||||
@@ -811,7 +806,7 @@ class QtDriver(DriverMixin, QObject):
|
||||
self.set_clipboard_menu_viability()
|
||||
self.set_select_actions_visibility()
|
||||
|
||||
self.main_window.preview_panel.update_widgets(update_preview=False)
|
||||
self.main_window.preview_panel.set_selection(self.selected, update_preview=False)
|
||||
|
||||
def select_inverse_action_callback(self):
|
||||
"""Invert the selection of all visible items."""
|
||||
@@ -830,7 +825,7 @@ class QtDriver(DriverMixin, QObject):
|
||||
self.set_clipboard_menu_viability()
|
||||
self.set_select_actions_visibility()
|
||||
|
||||
self.main_window.preview_panel.update_widgets(update_preview=False)
|
||||
self.main_window.preview_panel.set_selection(self.selected, update_preview=False)
|
||||
|
||||
def clear_select_action_callback(self):
|
||||
self.selected.clear()
|
||||
@@ -839,7 +834,7 @@ class QtDriver(DriverMixin, QObject):
|
||||
item.thumb_button.set_selected(False)
|
||||
|
||||
self.set_clipboard_menu_viability()
|
||||
self.main_window.preview_panel.update_widgets()
|
||||
self.main_window.preview_panel.set_selection(self.selected)
|
||||
|
||||
def add_tags_to_selected_callback(self, tag_ids: list[int]):
|
||||
self.lib.add_tags_to_entries(self.selected, tag_ids)
|
||||
@@ -884,7 +879,7 @@ class QtDriver(DriverMixin, QObject):
|
||||
for i, tup in enumerate(pending):
|
||||
e_id, f = tup
|
||||
if (origin_path == f) or (not origin_path):
|
||||
self.main_window.preview_panel.thumb.media_player.stop()
|
||||
self.main_window.preview_panel.thumb_media_player_stop()
|
||||
if delete_file(self.lib.library_dir / f):
|
||||
self.main_window.status_bar.showMessage(
|
||||
Translations.format(
|
||||
@@ -899,7 +894,7 @@ class QtDriver(DriverMixin, QObject):
|
||||
|
||||
if deleted_count > 0:
|
||||
self.update_browsing_state()
|
||||
self.main_window.preview_panel.update_widgets()
|
||||
self.main_window.preview_panel.set_selection(self.selected)
|
||||
|
||||
if len(self.selected) <= 1 and deleted_count == 0:
|
||||
self.main_window.status_bar.showMessage(Translations["status.deleted_none"])
|
||||
@@ -1224,7 +1219,7 @@ class QtDriver(DriverMixin, QObject):
|
||||
if TAG_FAVORITE in self.copy_buffer["tags"]:
|
||||
self.update_badges({BadgeType.FAVORITE: True}, origin_id=0, add_tags=False)
|
||||
else:
|
||||
self.main_window.preview_panel.update_widgets()
|
||||
self.main_window.preview_panel.set_selection(self.selected)
|
||||
|
||||
def toggle_item_selection(self, item_id: int, append: bool, bridge: bool):
|
||||
"""Toggle the selection of an item in the Thumbnail Grid.
|
||||
@@ -1298,7 +1293,7 @@ class QtDriver(DriverMixin, QObject):
|
||||
self.set_clipboard_menu_viability()
|
||||
self.set_select_actions_visibility()
|
||||
|
||||
self.main_window.preview_panel.update_widgets()
|
||||
self.main_window.preview_panel.set_selection(self.selected)
|
||||
|
||||
def set_clipboard_menu_viability(self):
|
||||
if len(self.selected) == 1:
|
||||
@@ -1742,7 +1737,7 @@ class QtDriver(DriverMixin, QObject):
|
||||
self.main_window.menu_bar.clear_thumb_cache_action.setEnabled(True)
|
||||
self.main_window.menu_bar.folders_to_tags_action.setEnabled(True)
|
||||
|
||||
self.main_window.preview_panel.update_widgets()
|
||||
self.main_window.preview_panel.set_selection(self.selected)
|
||||
|
||||
# page (re)rendering, extract eventually
|
||||
self.update_browsing_state()
|
||||
|
||||
208
src/tagstudio/qt/view/widgets/preview_panel_view.py
Normal file
208
src/tagstudio/qt/view/widgets/preview_panel_view.py
Normal file
@@ -0,0 +1,208 @@
|
||||
import traceback
|
||||
import typing
|
||||
from pathlib import Path
|
||||
|
||||
import structlog
|
||||
from PySide6.QtCore import Qt
|
||||
from PySide6.QtWidgets import (
|
||||
QHBoxLayout,
|
||||
QPushButton,
|
||||
QSplitter,
|
||||
QVBoxLayout,
|
||||
QWidget,
|
||||
)
|
||||
|
||||
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.qt.translations import Translations
|
||||
from tagstudio.qt.widgets.preview.field_containers import FieldContainers
|
||||
from tagstudio.qt.widgets.preview.file_attributes import FileAttributes
|
||||
from tagstudio.qt.widgets.preview.preview_thumb import PreviewThumb
|
||||
|
||||
if typing.TYPE_CHECKING:
|
||||
from tagstudio.qt.ts_qt import QtDriver
|
||||
|
||||
logger = structlog.get_logger(__name__)
|
||||
|
||||
BUTTON_STYLE = f"""
|
||||
QPushButton{{
|
||||
background-color: {Theme.COLOR_BG.value};
|
||||
border-radius: 6px;
|
||||
font-weight: 500;
|
||||
text-align: center;
|
||||
}}
|
||||
QPushButton::hover{{
|
||||
background-color: {Theme.COLOR_HOVER.value};
|
||||
border-color: {get_ui_color(ColorType.BORDER, UiColor.THEME_DARK)};
|
||||
border-style: solid;
|
||||
border-width: 2px;
|
||||
}}
|
||||
QPushButton::pressed{{
|
||||
background-color: {Theme.COLOR_PRESSED.value};
|
||||
border-color: {get_ui_color(ColorType.LIGHT_ACCENT, UiColor.THEME_DARK)};
|
||||
border-style: solid;
|
||||
border-width: 2px;
|
||||
}}
|
||||
QPushButton::disabled{{
|
||||
background-color: {Theme.COLOR_DISABLED_BG.value};
|
||||
}}
|
||||
"""
|
||||
|
||||
|
||||
class PreviewPanelView(QWidget):
|
||||
lib: Library
|
||||
|
||||
_selected: list[int]
|
||||
|
||||
def __init__(self, library: Library, driver: "QtDriver"):
|
||||
super().__init__()
|
||||
self.lib = library
|
||||
|
||||
self.__thumb = PreviewThumb(self.lib, driver)
|
||||
self.__file_attrs = FileAttributes(self.lib, driver)
|
||||
self._fields = FieldContainers(
|
||||
self.lib, driver
|
||||
) # TODO: this should be name mangled, but is still needed on the controller side atm
|
||||
|
||||
preview_section = QWidget()
|
||||
preview_layout = QVBoxLayout(preview_section)
|
||||
preview_layout.setContentsMargins(0, 0, 0, 0)
|
||||
preview_layout.setSpacing(6)
|
||||
|
||||
info_section = QWidget()
|
||||
info_layout = QVBoxLayout(info_section)
|
||||
info_layout.setContentsMargins(0, 0, 0, 0)
|
||||
info_layout.setSpacing(6)
|
||||
|
||||
splitter = QSplitter()
|
||||
splitter.setOrientation(Qt.Orientation.Vertical)
|
||||
splitter.setHandleWidth(12)
|
||||
|
||||
add_buttons_container = QWidget()
|
||||
add_buttons_layout = QHBoxLayout(add_buttons_container)
|
||||
add_buttons_layout.setContentsMargins(0, 0, 0, 0)
|
||||
add_buttons_layout.setSpacing(6)
|
||||
|
||||
self.__add_tag_button = QPushButton(Translations["tag.add"])
|
||||
self.__add_tag_button.setEnabled(False)
|
||||
self.__add_tag_button.setCursor(Qt.CursorShape.PointingHandCursor)
|
||||
self.__add_tag_button.setMinimumHeight(28)
|
||||
self.__add_tag_button.setStyleSheet(BUTTON_STYLE)
|
||||
|
||||
self.__add_field_button = QPushButton(Translations["library.field.add"])
|
||||
self.__add_field_button.setEnabled(False)
|
||||
self.__add_field_button.setCursor(Qt.CursorShape.PointingHandCursor)
|
||||
self.__add_field_button.setMinimumHeight(28)
|
||||
self.__add_field_button.setStyleSheet(BUTTON_STYLE)
|
||||
|
||||
add_buttons_layout.addWidget(self.__add_tag_button)
|
||||
add_buttons_layout.addWidget(self.__add_field_button)
|
||||
|
||||
preview_layout.addWidget(self.__thumb)
|
||||
info_layout.addWidget(self.__file_attrs)
|
||||
info_layout.addWidget(self._fields)
|
||||
|
||||
splitter.addWidget(preview_section)
|
||||
splitter.addWidget(info_section)
|
||||
splitter.setStretchFactor(1, 2)
|
||||
|
||||
root_layout = QVBoxLayout(self)
|
||||
root_layout.setContentsMargins(0, 0, 0, 0)
|
||||
root_layout.addWidget(splitter)
|
||||
root_layout.addWidget(add_buttons_container)
|
||||
|
||||
self.__connect_callbacks()
|
||||
|
||||
def __connect_callbacks(self):
|
||||
self.__add_field_button.clicked.connect(self._add_field_button_callback)
|
||||
self.__add_tag_button.clicked.connect(self._add_tag_button_callback)
|
||||
|
||||
def _add_field_button_callback(self):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _add_tag_button_callback(self):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _set_selection_callback(self):
|
||||
raise NotImplementedError()
|
||||
|
||||
def thumb_media_player_stop(self):
|
||||
self.__thumb.media_player.stop()
|
||||
|
||||
def set_selection(self, selected: list[int], update_preview: bool = True):
|
||||
"""Render the panel widgets with the newest data from the Library.
|
||||
|
||||
Args:
|
||||
selected (list[int]): List of the IDs of the selected entries.
|
||||
update_preview (bool): Should the file preview be updated?
|
||||
(Only works with one or more items selected)
|
||||
"""
|
||||
self._selected = selected
|
||||
try:
|
||||
# No Items Selected
|
||||
if len(selected) == 0:
|
||||
self.__thumb.hide_preview()
|
||||
self.__file_attrs.update_stats()
|
||||
self.__file_attrs.update_date_label()
|
||||
self._fields.hide_containers()
|
||||
|
||||
self.add_buttons_enabled = False
|
||||
|
||||
# One Item Selected
|
||||
elif len(selected) == 1:
|
||||
entry_id = selected[0]
|
||||
entry: Entry | None = self.lib.get_entry(entry_id)
|
||||
assert entry is not None
|
||||
|
||||
assert self.lib.library_dir is not None
|
||||
filepath: Path = self.lib.library_dir / entry.path
|
||||
|
||||
if update_preview:
|
||||
stats: dict = self.__thumb.update_preview(filepath)
|
||||
self.__file_attrs.update_stats(filepath, stats)
|
||||
self.__file_attrs.update_date_label(filepath)
|
||||
self._fields.update_from_entry(entry_id)
|
||||
|
||||
self._set_selection_callback()
|
||||
|
||||
self.add_buttons_enabled = True
|
||||
|
||||
# Multiple Selected Items
|
||||
elif len(selected) > 1:
|
||||
# items: list[Entry] = [self.lib.get_entry_full(x) for x in self.driver.selected]
|
||||
self.__thumb.hide_preview() # TODO: Render mixed selection
|
||||
self.__file_attrs.update_multi_selection(len(selected))
|
||||
self.__file_attrs.update_date_label()
|
||||
self._fields.hide_containers() # TODO: Allow for mixed editing
|
||||
|
||||
self._set_selection_callback()
|
||||
|
||||
self.add_buttons_enabled = True
|
||||
|
||||
except Exception as e:
|
||||
logger.error("[Preview Panel] Error updating selection", error=e)
|
||||
traceback.print_exc()
|
||||
|
||||
@property
|
||||
def add_buttons_enabled(self) -> bool: # needed for the tests
|
||||
field = self.__add_field_button.isEnabled()
|
||||
tag = self.__add_tag_button.isEnabled()
|
||||
assert field == tag
|
||||
return field
|
||||
|
||||
@add_buttons_enabled.setter
|
||||
def add_buttons_enabled(self, enabled: bool):
|
||||
self.__add_field_button.setEnabled(enabled)
|
||||
self.__add_tag_button.setEnabled(enabled)
|
||||
|
||||
@property
|
||||
def _file_attributes_widget(self) -> FileAttributes: # needed for the tests
|
||||
"""Getter for the file attributes widget."""
|
||||
return self.__file_attrs
|
||||
|
||||
@property
|
||||
def field_containers_widget(self) -> FieldContainers: # needed for the tests
|
||||
"""Getter for the field containers widget."""
|
||||
return self._fields
|
||||
@@ -502,9 +502,9 @@ class ItemThumb(FlowWidget):
|
||||
toggle_value: bool,
|
||||
tag_id: int,
|
||||
):
|
||||
if entry_id in self.driver.selected and self.driver.main_window.preview_panel.is_open:
|
||||
if entry_id in self.driver.selected:
|
||||
if len(self.driver.selected) == 1:
|
||||
self.driver.main_window.preview_panel.fields.update_toggled_tag(
|
||||
self.driver.main_window.preview_panel.field_containers_widget.update_toggled_tag(
|
||||
tag_id, toggle_value
|
||||
)
|
||||
else:
|
||||
|
||||
@@ -1,203 +0,0 @@
|
||||
# Copyright (C) 2025 Travis Abendshien (CyanVoxel).
|
||||
# Licensed under the GPL-3.0 License.
|
||||
# Created for TagStudio: https://github.com/CyanVoxel/TagStudio
|
||||
|
||||
|
||||
import traceback
|
||||
import typing
|
||||
from pathlib import Path
|
||||
from warnings import catch_warnings
|
||||
|
||||
import structlog
|
||||
from PySide6.QtCore import Qt
|
||||
from PySide6.QtWidgets import QHBoxLayout, QPushButton, QSplitter, QVBoxLayout, QWidget
|
||||
|
||||
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.qt.modals.add_field import AddFieldModal
|
||||
from tagstudio.qt.modals.tag_search import TagSearchPanel
|
||||
from tagstudio.qt.translations import Translations
|
||||
from tagstudio.qt.widgets.panel import PanelModal
|
||||
from tagstudio.qt.widgets.preview.field_containers import FieldContainers
|
||||
from tagstudio.qt.widgets.preview.file_attributes import FileAttributes
|
||||
from tagstudio.qt.widgets.preview.preview_thumb import PreviewThumb
|
||||
|
||||
if typing.TYPE_CHECKING:
|
||||
from tagstudio.qt.ts_qt import QtDriver
|
||||
|
||||
logger = structlog.get_logger(__name__)
|
||||
|
||||
|
||||
class PreviewPanel(QWidget):
|
||||
"""The Preview Panel Widget."""
|
||||
|
||||
# TODO: There should be a global button theme somewhere.
|
||||
button_style = (
|
||||
f"QPushButton{{"
|
||||
f"background-color:{Theme.COLOR_BG.value};"
|
||||
"border-radius:6px;"
|
||||
"font-weight: 500;"
|
||||
"text-align: center;"
|
||||
f"}}"
|
||||
f"QPushButton::hover{{"
|
||||
f"background-color:{Theme.COLOR_HOVER.value};"
|
||||
f"border-color:{get_ui_color(ColorType.BORDER, UiColor.THEME_DARK)};"
|
||||
f"border-style:solid;"
|
||||
f"border-width: 2px;"
|
||||
f"}}"
|
||||
f"QPushButton::pressed{{"
|
||||
f"background-color:{Theme.COLOR_PRESSED.value};"
|
||||
f"border-color:{get_ui_color(ColorType.LIGHT_ACCENT, UiColor.THEME_DARK)};"
|
||||
f"border-style:solid;"
|
||||
f"border-width: 2px;"
|
||||
f"}}"
|
||||
f"QPushButton::disabled{{"
|
||||
f"background-color:{Theme.COLOR_DISABLED_BG.value};"
|
||||
f"}}"
|
||||
)
|
||||
|
||||
def __init__(self, library: Library, driver: "QtDriver"):
|
||||
super().__init__()
|
||||
self.lib = library
|
||||
self.driver: QtDriver = driver
|
||||
self.initialized = False
|
||||
self.is_open: bool = True
|
||||
|
||||
self.thumb = PreviewThumb(library, driver)
|
||||
self.file_attrs = FileAttributes(library, driver)
|
||||
self.fields = FieldContainers(library, driver)
|
||||
|
||||
self.tag_search_panel = TagSearchPanel(self.driver.lib, is_tag_chooser=True)
|
||||
self.add_tag_modal = PanelModal(self.tag_search_panel, Translations["tag.add.plural"])
|
||||
|
||||
self.add_field_modal = AddFieldModal(self.lib)
|
||||
|
||||
preview_section = QWidget()
|
||||
preview_layout = QVBoxLayout(preview_section)
|
||||
preview_layout.setContentsMargins(0, 0, 0, 0)
|
||||
preview_layout.setSpacing(6)
|
||||
|
||||
info_section = QWidget()
|
||||
info_layout = QVBoxLayout(info_section)
|
||||
info_layout.setContentsMargins(0, 0, 0, 0)
|
||||
info_layout.setSpacing(6)
|
||||
|
||||
splitter = QSplitter()
|
||||
splitter.setOrientation(Qt.Orientation.Vertical)
|
||||
splitter.setHandleWidth(12)
|
||||
|
||||
add_buttons_container = QWidget()
|
||||
add_buttons_layout = QHBoxLayout(add_buttons_container)
|
||||
add_buttons_layout.setContentsMargins(0, 0, 0, 0)
|
||||
add_buttons_layout.setSpacing(6)
|
||||
|
||||
self.add_tag_button = QPushButton(Translations["tag.add"])
|
||||
self.add_tag_button.setEnabled(False)
|
||||
self.add_tag_button.setCursor(Qt.CursorShape.PointingHandCursor)
|
||||
self.add_tag_button.setMinimumHeight(28)
|
||||
self.add_tag_button.setStyleSheet(PreviewPanel.button_style)
|
||||
|
||||
self.add_field_button = QPushButton(Translations["library.field.add"])
|
||||
self.add_field_button.setEnabled(False)
|
||||
self.add_field_button.setCursor(Qt.CursorShape.PointingHandCursor)
|
||||
self.add_field_button.setMinimumHeight(28)
|
||||
self.add_field_button.setStyleSheet(PreviewPanel.button_style)
|
||||
|
||||
add_buttons_layout.addWidget(self.add_tag_button)
|
||||
add_buttons_layout.addWidget(self.add_field_button)
|
||||
|
||||
preview_layout.addWidget(self.thumb)
|
||||
info_layout.addWidget(self.file_attrs)
|
||||
info_layout.addWidget(self.fields)
|
||||
|
||||
splitter.addWidget(preview_section)
|
||||
splitter.addWidget(info_section)
|
||||
splitter.setStretchFactor(1, 2)
|
||||
|
||||
root_layout = QVBoxLayout(self)
|
||||
root_layout.setContentsMargins(0, 0, 0, 0)
|
||||
root_layout.addWidget(splitter)
|
||||
root_layout.addWidget(add_buttons_container)
|
||||
|
||||
def update_widgets(self, update_preview: bool = True) -> bool:
|
||||
"""Render the panel widgets with the newest data from the Library.
|
||||
|
||||
Args:
|
||||
update_preview(bool): Should the file preview be updated?
|
||||
(Only works with one or more items selected)
|
||||
"""
|
||||
# No Items Selected
|
||||
try:
|
||||
if len(self.driver.selected) == 0:
|
||||
self.thumb.hide_preview()
|
||||
self.file_attrs.update_stats()
|
||||
self.file_attrs.update_date_label()
|
||||
self.fields.hide_containers()
|
||||
|
||||
self.add_tag_button.setEnabled(False)
|
||||
self.add_field_button.setEnabled(False)
|
||||
|
||||
# One Item Selected
|
||||
elif len(self.driver.selected) == 1:
|
||||
entry: Entry = self.lib.get_entry(self.driver.selected[0])
|
||||
entry_id = self.driver.selected[0]
|
||||
filepath: Path = self.lib.library_dir / entry.path
|
||||
|
||||
if update_preview:
|
||||
stats: dict = self.thumb.update_preview(filepath)
|
||||
self.file_attrs.update_stats(filepath, stats)
|
||||
self.file_attrs.update_date_label(filepath)
|
||||
self.fields.update_from_entry(entry_id)
|
||||
self.update_add_tag_button(entry_id)
|
||||
self.update_add_field_button(entry_id)
|
||||
|
||||
self.add_tag_button.setEnabled(True)
|
||||
self.add_field_button.setEnabled(True)
|
||||
|
||||
# Multiple Selected Items
|
||||
elif len(self.driver.selected) > 1:
|
||||
# items: list[Entry] = [self.lib.get_entry_full(x) for x in self.driver.selected]
|
||||
self.thumb.hide_preview() # TODO: Render mixed selection
|
||||
self.file_attrs.update_multi_selection(len(self.driver.selected))
|
||||
self.file_attrs.update_date_label()
|
||||
self.fields.hide_containers() # TODO: Allow for mixed editing
|
||||
self.update_add_tag_button()
|
||||
self.update_add_field_button()
|
||||
|
||||
self.add_tag_button.setEnabled(True)
|
||||
self.add_field_button.setEnabled(True)
|
||||
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.error("[Preview Panel] Error updating selection", error=e)
|
||||
traceback.print_exc()
|
||||
return False
|
||||
|
||||
def update_add_field_button(self, entry_id: int | None = None):
|
||||
with catch_warnings(record=True):
|
||||
self.add_field_modal.done.disconnect()
|
||||
self.add_field_button.clicked.disconnect()
|
||||
|
||||
self.add_field_modal.done.connect(
|
||||
lambda f: (
|
||||
self.fields.add_field_to_selected(f),
|
||||
(self.fields.update_from_entry(entry_id) if entry_id else ()),
|
||||
)
|
||||
)
|
||||
self.add_field_button.clicked.connect(self.add_field_modal.show)
|
||||
|
||||
def update_add_tag_button(self, entry_id: int = None):
|
||||
with catch_warnings(record=True):
|
||||
self.tag_search_panel.tag_chosen.disconnect()
|
||||
self.add_tag_button.clicked.disconnect()
|
||||
|
||||
self.tag_search_panel.tag_chosen.connect(
|
||||
lambda t: (
|
||||
self.fields.add_tags_to_selected(t),
|
||||
(self.fields.update_from_entry(entry_id) if entry_id else ()),
|
||||
)
|
||||
)
|
||||
|
||||
self.add_tag_button.clicked.connect(self.add_tag_modal.show)
|
||||
@@ -63,9 +63,9 @@ class TagBoxWidget(FieldWidget):
|
||||
tag_widget.on_click.connect(lambda t=tag: self.__on_tag_clicked(t))
|
||||
|
||||
tag_widget.on_remove.connect(
|
||||
lambda tag_id=tag.id: (
|
||||
lambda tag_id=tag.id, s=self.driver.selected: (
|
||||
self.remove_tag(tag_id),
|
||||
self.driver.main_window.preview_panel.update_widgets(update_preview=False),
|
||||
self.driver.main_window.preview_panel.set_selection(s, update_preview=False),
|
||||
)
|
||||
)
|
||||
tag_widget.on_edit.connect(lambda t=tag: self.edit_tag(t))
|
||||
@@ -107,8 +107,9 @@ class TagBoxWidget(FieldWidget):
|
||||
build_tag_panel,
|
||||
self.driver.lib.tag_display_name(tag.id),
|
||||
"Edit Tag",
|
||||
done_callback=lambda: self.driver.main_window.preview_panel.update_widgets(
|
||||
update_preview=False
|
||||
done_callback=lambda _=None,
|
||||
s=self.driver.selected: self.driver.main_window.preview_panel.set_selection( # noqa: E501
|
||||
s, update_preview=False
|
||||
),
|
||||
has_save=True,
|
||||
)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from tagstudio.qt.widgets.preview_panel import PreviewPanel
|
||||
from tagstudio.qt.controller.widgets.preview_panel_controller import PreviewPanel
|
||||
|
||||
|
||||
def test_update_selection_empty(qt_driver, library):
|
||||
@@ -7,10 +7,10 @@ def test_update_selection_empty(qt_driver, library):
|
||||
# Clear the library selection (selecting 1 then unselecting 1)
|
||||
qt_driver.toggle_item_selection(1, append=False, bridge=False)
|
||||
qt_driver.toggle_item_selection(1, append=True, bridge=False)
|
||||
panel.update_widgets()
|
||||
panel.set_selection(qt_driver.selected)
|
||||
|
||||
# FieldContainer should hide all containers
|
||||
for container in panel.fields.containers:
|
||||
for container in panel.field_containers_widget.containers:
|
||||
assert container.isHidden()
|
||||
|
||||
|
||||
@@ -19,10 +19,10 @@ def test_update_selection_single(qt_driver, library, entry_full):
|
||||
|
||||
# Select the single entry
|
||||
qt_driver.toggle_item_selection(entry_full.id, append=False, bridge=False)
|
||||
panel.update_widgets()
|
||||
panel.set_selection(qt_driver.selected)
|
||||
|
||||
# FieldContainer should show all applicable tags and field containers
|
||||
for container in panel.fields.containers:
|
||||
for container in panel.field_containers_widget.containers:
|
||||
assert not container.isHidden()
|
||||
|
||||
|
||||
@@ -34,10 +34,10 @@ def test_update_selection_multiple(qt_driver, library):
|
||||
# Select the multiple entries
|
||||
qt_driver.toggle_item_selection(1, append=False, bridge=False)
|
||||
qt_driver.toggle_item_selection(2, append=True, bridge=False)
|
||||
panel.update_widgets()
|
||||
panel.set_selection(qt_driver.selected)
|
||||
|
||||
# FieldContainer should show mixed field editing
|
||||
for container in panel.fields.containers:
|
||||
for container in panel.field_containers_widget.containers:
|
||||
assert container.isHidden()
|
||||
|
||||
|
||||
@@ -48,10 +48,10 @@ def test_add_tag_to_selection_single(qt_driver, library, entry_full):
|
||||
|
||||
# Select the single entry
|
||||
qt_driver.toggle_item_selection(entry_full.id, append=False, bridge=False)
|
||||
panel.update_widgets()
|
||||
panel.set_selection(qt_driver.selected)
|
||||
|
||||
# Add new tag
|
||||
panel.fields.add_tags_to_selected(2000)
|
||||
panel.field_containers_widget.add_tags_to_selected(2000)
|
||||
|
||||
# Then reload entry
|
||||
refreshed_entry = next(library.get_entries(with_joins=True))
|
||||
@@ -65,10 +65,10 @@ def test_add_same_tag_to_selection_single(qt_driver, library, entry_full):
|
||||
|
||||
# Select the single entry
|
||||
qt_driver.toggle_item_selection(entry_full.id, append=False, bridge=False)
|
||||
panel.update_widgets()
|
||||
panel.set_selection(qt_driver.selected)
|
||||
|
||||
# Add an existing tag
|
||||
panel.fields.add_tags_to_selected(1000)
|
||||
panel.field_containers_widget.add_tags_to_selected(1000)
|
||||
|
||||
# Then reload entry
|
||||
refreshed_entry = next(library.get_entries(with_joins=True))
|
||||
@@ -95,10 +95,10 @@ def test_add_tag_to_selection_multiple(qt_driver, library):
|
||||
# Select the multiple entries
|
||||
for i, e in enumerate(library.get_entries(with_joins=True), start=0):
|
||||
qt_driver.toggle_item_selection(e.id, append=(True if i == 0 else False), bridge=False) # noqa: SIM210
|
||||
panel.update_widgets()
|
||||
panel.set_selection(qt_driver.selected)
|
||||
|
||||
# Add new tag
|
||||
panel.fields.add_tags_to_selected(1000)
|
||||
panel.field_containers_widget.add_tags_to_selected(1000)
|
||||
|
||||
# Then reload all entries and recheck the presence of tag 1000
|
||||
refreshed_entries = library.get_entries(with_joins=True)
|
||||
@@ -123,11 +123,11 @@ def test_meta_tag_category(qt_driver, library, entry_full):
|
||||
|
||||
# Select the single entry
|
||||
qt_driver.toggle_item_selection(entry_full.id, append=False, bridge=False)
|
||||
panel.update_widgets()
|
||||
panel.set_selection(qt_driver.selected)
|
||||
|
||||
# FieldContainer should hide all containers
|
||||
assert len(panel.fields.containers) == 3
|
||||
for i, container in enumerate(panel.fields.containers):
|
||||
assert len(panel.field_containers_widget.containers) == 3
|
||||
for i, container in enumerate(panel.field_containers_widget.containers):
|
||||
match i:
|
||||
case 0:
|
||||
# Check if the container is the Meta Tags category
|
||||
@@ -155,11 +155,11 @@ def test_custom_tag_category(qt_driver, library, entry_full):
|
||||
|
||||
# Select the single entry
|
||||
qt_driver.toggle_item_selection(entry_full.id, append=False, bridge=False)
|
||||
panel.update_widgets()
|
||||
panel.set_selection(qt_driver.selected)
|
||||
|
||||
# FieldContainer should hide all containers
|
||||
assert len(panel.fields.containers) == 3
|
||||
for i, container in enumerate(panel.fields.containers):
|
||||
assert len(panel.field_containers_widget.containers) == 3
|
||||
for i, container in enumerate(panel.field_containers_widget.containers):
|
||||
match i:
|
||||
case 0:
|
||||
# Check if the container is the Meta Tags category
|
||||
|
||||
@@ -12,9 +12,9 @@ from pytestqt.qtbot import QtBot
|
||||
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.qt.controller.widgets.preview_panel_controller import PreviewPanel
|
||||
from tagstudio.qt.modals.settings_panel import SettingsPanel
|
||||
from tagstudio.qt.ts_qt import QtDriver
|
||||
from tagstudio.qt.widgets.preview_panel import PreviewPanel
|
||||
|
||||
|
||||
# Tests to see if the file path setting is applied correctly
|
||||
@@ -59,7 +59,7 @@ def test_file_path_display(
|
||||
|
||||
# Select 2
|
||||
qt_driver.toggle_item_selection(2, append=False, bridge=False)
|
||||
panel.update_widgets()
|
||||
panel.set_selection(qt_driver.selected)
|
||||
|
||||
qt_driver.settings.show_filepath = filepath_option
|
||||
|
||||
@@ -68,7 +68,7 @@ def test_file_path_display(
|
||||
assert isinstance(entry, Entry)
|
||||
filename = entry.path
|
||||
assert library.library_dir is not None
|
||||
panel.file_attrs.update_stats(filepath=library.library_dir / filename)
|
||||
panel._file_attributes_widget.update_stats(filepath=library.library_dir / filename)
|
||||
|
||||
# Generate the expected file string.
|
||||
# This is copied directly from the file_attributes.py file
|
||||
@@ -86,7 +86,7 @@ def test_file_path_display(
|
||||
file_str += f"<b>{'\u200b'.join(part_)}</b>"
|
||||
|
||||
# Assert the file path is displayed correctly
|
||||
assert panel.file_attrs.file_label.text() == file_str
|
||||
assert panel._file_attributes_widget.file_label.text() == file_str
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from tagstudio.qt.widgets.preview_panel import PreviewPanel
|
||||
from tagstudio.qt.controller.widgets.preview_panel_controller import PreviewPanel
|
||||
|
||||
|
||||
def test_update_selection_empty(qt_driver, library):
|
||||
@@ -7,11 +7,10 @@ def test_update_selection_empty(qt_driver, library):
|
||||
# Clear the library selection (selecting 1 then unselecting 1)
|
||||
qt_driver.toggle_item_selection(1, append=False, bridge=False)
|
||||
qt_driver.toggle_item_selection(1, append=True, bridge=False)
|
||||
panel.update_widgets()
|
||||
panel.set_selection(qt_driver.selected)
|
||||
|
||||
# Panel should disable UI that allows for entry modification
|
||||
assert not panel.add_tag_button.isEnabled()
|
||||
assert not panel.add_field_button.isEnabled()
|
||||
assert not panel.add_buttons_enabled
|
||||
|
||||
|
||||
def test_update_selection_single(qt_driver, library, entry_full):
|
||||
@@ -19,11 +18,10 @@ def test_update_selection_single(qt_driver, library, entry_full):
|
||||
|
||||
# Select the single entry
|
||||
qt_driver.toggle_item_selection(entry_full.id, append=False, bridge=False)
|
||||
panel.update_widgets()
|
||||
panel.set_selection(qt_driver.selected)
|
||||
|
||||
# Panel should enable UI that allows for entry modification
|
||||
assert panel.add_tag_button.isEnabled()
|
||||
assert panel.add_field_button.isEnabled()
|
||||
assert panel.add_buttons_enabled
|
||||
|
||||
|
||||
def test_update_selection_multiple(qt_driver, library):
|
||||
@@ -32,8 +30,7 @@ def test_update_selection_multiple(qt_driver, library):
|
||||
# Select the multiple entries
|
||||
qt_driver.toggle_item_selection(1, append=False, bridge=False)
|
||||
qt_driver.toggle_item_selection(2, append=True, bridge=False)
|
||||
panel.update_widgets()
|
||||
panel.set_selection(qt_driver.selected)
|
||||
|
||||
# Panel should enable UI that allows for entry modification
|
||||
assert panel.add_tag_button.isEnabled()
|
||||
assert panel.add_field_button.isEnabled()
|
||||
assert panel.add_buttons_enabled
|
||||
|
||||
Reference in New Issue
Block a user