Skip to content

Commit

Permalink
ui: shortcut to add tags to selected entries; change click behavior o…
Browse files Browse the repository at this point in the history
…f tags to edit (#749)

* ui: change on_click behavior of tags to edit

* fix: pass library to tag_widget

* feat: add `add_tag_to_selected` shortcut

* fix: only enable `add_tag_to_selected` shortcut when usable
  • Loading branch information
CyanVoxel authored Jan 30, 2025
1 parent d1b006a commit 82edbee
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 8 deletions.
1 change: 1 addition & 0 deletions tagstudio/resources/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@
"menu.view": "&View",
"menu.window": "Window",
"preview.no_selection": "No Items Selected",
"select.add_tag_to_selected": "Add Tag to Selected",
"select.all": "Select All",
"select.clear": "Clear Selection",
"settings.clear_thumb_cache.title": "Clear Thumbnail Cache",
Expand Down
59 changes: 58 additions & 1 deletion tagstudio/src/qt/ts_qt.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
from src.qt.modals.fix_unlinked import FixUnlinkedEntriesModal
from src.qt.modals.folders_to_tags import FoldersToTagsModal
from src.qt.modals.tag_database import TagDatabasePanel
from src.qt.modals.tag_search import TagSearchPanel
from src.qt.resource_manager import ResourceManager
from src.qt.splash import Splash
from src.qt.translations import Translations
Expand Down Expand Up @@ -132,6 +133,9 @@ class QtDriver(DriverMixin, QObject):
SIGTERM = Signal()

preview_panel: PreviewPanel
tag_search_panel: TagSearchPanel
add_tag_modal: PanelModal

lib: Library

def __init__(self, backend, args):
Expand Down Expand Up @@ -199,6 +203,8 @@ def __init__(self, backend, args):
f"[Config] Thumbnail cache size limit: {format_size(CacheManager.size_limit)}",
)

self.add_tag_to_selected_action: QAction | None = None

def init_workers(self):
"""Init workers for rendering thumbnails."""
if not self.thumb_threads:
Expand Down Expand Up @@ -270,6 +276,18 @@ def start(self) -> None:
icon.addFile(str(icon_path))
app.setWindowIcon(icon)

# Initialize the main window's tag search panel
self.tag_search_panel = TagSearchPanel(self.lib, is_tag_chooser=True)
self.add_tag_modal = PanelModal(
self.tag_search_panel, Translations.translate_formatted("tag.add.plural")
)
self.tag_search_panel.tag_chosen.connect(
lambda t: (
self.add_tags_to_selected_callback(t),
self.preview_panel.update_widgets(),
)
)

menu_bar = QMenuBar(self.main_window)
self.main_window.setMenuBar(menu_bar)
menu_bar.setNativeMenuBar(True)
Expand Down Expand Up @@ -394,6 +412,24 @@ def start(self) -> None:
clear_select_action.setToolTip("Esc")
edit_menu.addAction(clear_select_action)

self.add_tag_to_selected_action = QAction(menu_bar)
Translations.translate_qobject(
self.add_tag_to_selected_action, "select.add_tag_to_selected"
)
self.add_tag_to_selected_action.triggered.connect(self.add_tag_modal.show)
self.add_tag_to_selected_action.setShortcut(
QtCore.QKeyCombination(
QtCore.Qt.KeyboardModifier(
QtCore.Qt.KeyboardModifier.ControlModifier
^ QtCore.Qt.KeyboardModifier.ShiftModifier
),
QtCore.Qt.Key.Key_T,
)
)
self.add_tag_to_selected_action.setToolTip("Ctrl+Shift+T")
self.add_tag_to_selected_action.setEnabled(False)
edit_menu.addAction(self.add_tag_to_selected_action)

edit_menu.addSeparator()

manage_file_extensions_action = QAction(menu_bar)
Expand Down Expand Up @@ -551,6 +587,7 @@ def create_about_modal():
self.open_library(path_result.library_path)

# check ffmpeg and show warning if not
# NOTE: Does this need to use self?
self.ffmpeg_checker = FfmpegChecker()
if not self.ffmpeg_checker.installed():
self.ffmpeg_checker.show_warning()
Expand Down Expand Up @@ -705,9 +742,12 @@ def close_library(self, is_shutdown: bool = False):

self.preview_panel.update_widgets()
self.main_window.toggle_landing_page(enabled=True)

self.main_window.pagination.setHidden(True)

# NOTE: Doesn't try to disable during tests
if self.add_tag_to_selected_action:
self.add_tag_to_selected_action.setEnabled(False)

end_time = time.time()
self.main_window.statusbar.showMessage(
Translations.translate_formatted(
Expand Down Expand Up @@ -760,16 +800,22 @@ def select_all_action_callback(self):
item.thumb_button.set_selected(True)

self.set_macro_menu_viability()
self.set_add_to_selected_visibility()
self.preview_panel.update_widgets(update_preview=False)

def clear_select_action_callback(self):
self.selected.clear()
self.set_add_to_selected_visibility()
for item in self.item_thumbs:
item.thumb_button.set_selected(False)

self.set_macro_menu_viability()
self.preview_panel.update_widgets()

def add_tags_to_selected_callback(self, tag_ids: list[int]):
for entry_id in self.selected:
self.lib.add_tags_to_entry(entry_id, tag_ids)

def show_tag_database(self):
self.modal = PanelModal(
widget=TagDatabasePanel(self.lib),
Expand Down Expand Up @@ -1110,11 +1156,21 @@ def toggle_item_selection(self, item_id: int, append: bool, bridge: bool):
it.thumb_button.set_selected(False)

self.set_macro_menu_viability()
self.set_add_to_selected_visibility()
self.preview_panel.update_widgets()

def set_macro_menu_viability(self):
self.autofill_action.setDisabled(not self.selected)

def set_add_to_selected_visibility(self):
if not self.add_tag_to_selected_action:
return

if self.selected:
self.add_tag_to_selected_action.setEnabled(True)
else:
self.add_tag_to_selected_action.setEnabled(False)

def update_completions_list(self, text: str) -> None:
matches = re.search(
r"((?:.* )?)(mediatype|filetype|path|tag|tag_id):(\"?[A-Za-z0-9\ \t]+\"?)?", text
Expand Down Expand Up @@ -1478,6 +1534,7 @@ def init_library(self, path: Path, open_status: LibraryStatus):
self.main_window.setAcceptDrops(True)

self.selected.clear()
self.set_add_to_selected_visibility()
self.preview_panel.update_widgets()

# page (re)rendering, extract eventually
Expand Down
8 changes: 1 addition & 7 deletions tagstudio/src/qt/widgets/tag_box.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import structlog
from PySide6.QtCore import Signal
from src.core.library import Tag
from src.core.library.alchemy.enums import FilterState
from src.qt.flowlayout import FlowLayout
from src.qt.modals.build_tag import BuildTagPanel
from src.qt.widgets.fields import FieldWidget
Expand Down Expand Up @@ -53,12 +52,7 @@ def set_tags(self, tags: typing.Iterable[Tag]):

for tag in tags_:
tag_widget = TagWidget(tag, library=self.driver.lib, has_edit=True, has_remove=True)
tag_widget.on_click.connect(
lambda tag_id=tag.id: (
self.driver.main_window.searchField.setText(f"tag_id:{tag_id}"),
self.driver.filter_items(FilterState.from_tag_id(tag_id)),
)
)
tag_widget.on_click.connect(lambda t=tag: self.edit_tag(t))

tag_widget.on_remove.connect(
lambda tag_id=tag.id: (
Expand Down

0 comments on commit 82edbee

Please sign in to comment.