Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ui: shortcut to add tags to selected entries; change click behavior of tags to edit #749

Merged
merged 4 commits into from
Jan 30, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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