Skip to content

Commit 192af25

Browse files
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
1 parent 7176908 commit 192af25

18 files changed

+355
-287
lines changed

pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,8 @@ qt_api = "pyside6"
8484

8585
[tool.pyright]
8686
ignore = [".venv/**"]
87-
include = ["src/tagstudio/**"]
87+
include = ["src/tagstudio", "tests"]
88+
extraPaths = ["src/tagstudio", "tests"]
8889
reportAny = false
8990
reportIgnoreCommentWithoutRule = false
9091
reportImplicitStringConcatenation = false

src/tagstudio/core/library/alchemy/library.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -674,7 +674,7 @@ def get_entry_full(
674674
start_time = time.time()
675675
entry = session.scalar(entry_stmt)
676676
if with_tags:
677-
tags = set(session.scalars(tag_stmt)) # pyright: ignore [reportPossiblyUnboundVariable]
677+
tags = set(session.scalars(tag_stmt)) # pyright: ignore[reportPossiblyUnboundVariable]
678678
end_time = time.time()
679679
logger.info(
680680
f"[Library] Time it took to get entry: "
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import typing
2+
from warnings import catch_warnings
3+
4+
from PySide6.QtWidgets import QListWidgetItem
5+
6+
from tagstudio.core.library.alchemy.library import Library
7+
from tagstudio.qt.modals.add_field import AddFieldModal
8+
from tagstudio.qt.modals.tag_search import TagSearchModal
9+
from tagstudio.qt.view.widgets.preview_panel_view import PreviewPanelView
10+
11+
if typing.TYPE_CHECKING:
12+
from tagstudio.qt.ts_qt import QtDriver
13+
14+
15+
class PreviewPanel(PreviewPanelView):
16+
def __init__(self, library: Library, driver: "QtDriver"):
17+
super().__init__(library, driver)
18+
19+
self.__add_field_modal = AddFieldModal(self.lib)
20+
self.__add_tag_modal = TagSearchModal(self.lib, is_tag_chooser=True)
21+
22+
def _add_field_button_callback(self):
23+
self.__add_field_modal.show()
24+
25+
def _add_tag_button_callback(self):
26+
self.__add_tag_modal.show()
27+
28+
def _set_selection_callback(self):
29+
with catch_warnings(record=True):
30+
self.__add_field_modal.done.disconnect()
31+
self.__add_tag_modal.tsp.tag_chosen.disconnect()
32+
33+
self.__add_field_modal.done.connect(self._add_field_to_selected)
34+
self.__add_tag_modal.tsp.tag_chosen.connect(self._add_tag_to_selected)
35+
36+
def _add_field_to_selected(self, field_list: list[QListWidgetItem]):
37+
self._fields.add_field_to_selected(field_list)
38+
if len(self._selected) == 1:
39+
self._fields.update_from_entry(self._selected[0])
40+
41+
def _add_tag_to_selected(self, tag_id: int):
42+
self._fields.add_tags_to_selected(tag_id)
43+
if len(self._selected) == 1:
44+
self._fields.update_from_entry(self._selected[0])

src/tagstudio/qt/main_window.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,12 @@
3333

3434
from tagstudio.core.enums import ShowFilepathOption
3535
from tagstudio.core.library.alchemy.enums import SortingModeEnum
36+
from tagstudio.qt.controller.widgets.preview_panel_controller import PreviewPanel
3637
from tagstudio.qt.flowlayout import FlowLayout
3738
from tagstudio.qt.pagination import Pagination
3839
from tagstudio.qt.platform_strings import trash_term
3940
from tagstudio.qt.translations import Translations
4041
from tagstudio.qt.widgets.landing import LandingWidget
41-
from tagstudio.qt.widgets.preview_panel import PreviewPanel
4242

4343
# Only import for type checking/autocompletion, will not be imported at runtime.
4444
if typing.TYPE_CHECKING:

src/tagstudio/qt/modals/build_tag.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
from tagstudio.core.library.alchemy.models import Tag, TagColorGroup
3131
from tagstudio.core.palette import ColorType, UiColor, get_tag_color, get_ui_color
3232
from tagstudio.qt.modals.tag_color_selection import TagColorSelection
33-
from tagstudio.qt.modals.tag_search import TagSearchPanel
33+
from tagstudio.qt.modals.tag_search import TagSearchModal
3434
from tagstudio.qt.translations import Translations
3535
from tagstudio.qt.widgets.panel import PanelModal, PanelWidget
3636
from tagstudio.qt.widgets.tag import (
@@ -166,9 +166,8 @@ def __init__(self, library: Library, tag: Tag | None = None) -> None:
166166
if tag is not None:
167167
exclude_ids.append(tag.id)
168168

169-
tsp = TagSearchPanel(self.lib, exclude_ids)
170-
tsp.tag_chosen.connect(lambda x: self.add_parent_tag_callback(x))
171-
self.add_tag_modal = PanelModal(tsp, Translations["tag.parent_tags.add"])
169+
self.add_tag_modal = TagSearchModal(self.lib, exclude_ids)
170+
self.add_tag_modal.tsp.tag_chosen.connect(lambda x: self.add_parent_tag_callback(x))
172171
self.parent_tags_add_button.clicked.connect(self.add_tag_modal.show)
173172

174173
# Color ----------------------------------------------------------------

src/tagstudio/qt/modals/folders_to_tags.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,9 @@ def __init__(self, library: "Library", driver: "QtDriver"):
227227
def on_apply(self):
228228
folders_to_tags(self.library)
229229
self.close()
230-
self.driver.main_window.preview_panel.update_widgets(update_preview=False)
230+
self.driver.main_window.preview_panel.set_selection(
231+
self.driver.selected, update_preview=False
232+
)
231233

232234
@override
233235
def showEvent(self, event: QtGui.QShowEvent):

src/tagstudio/qt/modals/mirror_entities.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ def displayed_text(x):
8787
pw.from_iterable_function(
8888
self.mirror_entries_runnable,
8989
displayed_text,
90-
self.driver.main_window.preview_panel.update_widgets,
90+
lambda s=self.driver.selected: self.driver.main_window.preview_panel.set_selection(s),
9191
self.done.emit,
9292
)
9393

src/tagstudio/qt/modals/settings_panel.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ def update_settings(self, driver: "QtDriver"):
263263
# Apply changes
264264
# Show File Path
265265
driver.update_recent_lib_menu()
266-
driver.main_window.preview_panel.update_widgets()
266+
driver.main_window.preview_panel.set_selection(self.driver.selected)
267267
library_directory = driver.lib.library_dir
268268
if settings["show_filepath"] == ShowFilepathOption.SHOW_FULL_PATHS:
269269
display_path = library_directory or ""

src/tagstudio/qt/modals/tag_color_manager.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ def setup_color_groups(self):
124124
self.setup_color_groups(),
125125
()
126126
if len(self.driver.selected) < 1
127-
else self.driver.main_window.preview_panel.fields.update_from_entry(
127+
else self.driver.main_window.preview_panel.field_containers_widget.update_from_entry( # noqa: E501
128128
self.driver.selected[0], update_badges=False
129129
),
130130
)
@@ -141,7 +141,7 @@ def setup_color_groups(self):
141141
self.setup_color_groups(),
142142
()
143143
if len(self.driver.selected) < 1
144-
else self.driver.main_window.preview_panel.fields.update_from_entry(
144+
else self.driver.main_window.preview_panel.field_containers_widget.update_from_entry( # noqa: E501
145145
self.driver.selected[0], update_badges=False
146146
),
147147
),

src/tagstudio/qt/modals/tag_search.py

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55

66
import contextlib
7-
from typing import TYPE_CHECKING
7+
from typing import TYPE_CHECKING, Union
88
from warnings import catch_warnings
99

1010
import structlog
@@ -39,10 +39,32 @@
3939
from tagstudio.qt.ts_qt import QtDriver
4040

4141

42+
class TagSearchModal(PanelModal):
43+
tsp: "TagSearchPanel"
44+
45+
def __init__(
46+
self,
47+
library: Library,
48+
exclude: list[int] | None = None,
49+
is_tag_chooser: bool = True,
50+
done_callback=None,
51+
save_callback=None,
52+
has_save=False,
53+
):
54+
self.tsp = TagSearchPanel(library, exclude, is_tag_chooser)
55+
super().__init__(
56+
self.tsp,
57+
Translations["tag.add.plural"],
58+
done_callback=done_callback,
59+
save_callback=save_callback,
60+
has_save=has_save,
61+
)
62+
63+
4264
class TagSearchPanel(PanelWidget):
4365
tag_chosen = Signal(int)
4466
lib: Library
45-
driver: "QtDriver"
67+
driver: Union["QtDriver", None]
4668
is_initialized: bool = False
4769
first_tag_id: int | None = None
4870
is_tag_chooser: bool
@@ -56,7 +78,7 @@ class TagSearchPanel(PanelWidget):
5678
def __init__(
5779
self,
5880
library: Library,
59-
exclude: list[int] = None,
81+
exclude: list[int] | None = None,
6082
is_tag_chooser: bool = True,
6183
):
6284
super().__init__()
@@ -194,6 +216,7 @@ def update_tags(self, query: str | None = None):
194216
create_button: QPushButton | None = None
195217
if self.create_button_in_layout and self.scroll_layout.count():
196218
create_button = self.scroll_layout.takeAt(self.scroll_layout.count() - 1).widget() # type: ignore
219+
assert create_button is not None
197220
create_button.deleteLater()
198221
self.create_button_in_layout = False
199222

@@ -264,7 +287,8 @@ def set_tag_widget(self, tag: Tag | None, index: int):
264287
self.scroll_layout.addWidget(new_tw)
265288

266289
# Assign the tag to the widget at the given index.
267-
tag_widget: TagWidget = self.scroll_layout.itemAt(index).widget()
290+
tag_widget: TagWidget = self.scroll_layout.itemAt(index).widget() # pyright: ignore[reportAssignmentType]
291+
assert isinstance(tag_widget, TagWidget)
268292
tag_widget.set_tag(tag)
269293

270294
# Set tag widget viability and potentially return early
@@ -288,11 +312,11 @@ def set_tag_widget(self, tag: Tag | None, index: int):
288312
tag_widget.on_remove.connect(lambda t=tag: self.delete_tag(t))
289313
tag_widget.bg_button.clicked.connect(lambda: self.tag_chosen.emit(tag_id))
290314

291-
if self.driver:
315+
if self.driver is not None:
292316
tag_widget.search_for_tag_action.triggered.connect(
293-
lambda checked=False, tag_id=tag.id: (
294-
self.driver.main_window.search_field.setText(f"tag_id:{tag_id}"),
295-
self.driver.update_browsing_state(BrowsingState.from_tag_id(tag_id)),
317+
lambda checked=False, tag_id=tag.id, driver=self.driver: (
318+
driver.main_window.search_field.setText(f"tag_id:{tag_id}"),
319+
driver.update_browsing_state(BrowsingState.from_tag_id(tag_id)),
296320
)
297321
)
298322
tag_widget.search_for_tag_action.setEnabled(True)

0 commit comments

Comments
 (0)