Skip to content

Commit f7f4da8

Browse files
refactor: port #455 functionality to main
Co-Authored-By: Tyrannicodin <[email protected]>
1 parent 9858ad1 commit f7f4da8

File tree

4 files changed

+93
-7
lines changed

4 files changed

+93
-7
lines changed

src/tagstudio/qt/ts_qt.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import sys
1818
import time
1919
from pathlib import Path
20+
from platform import system
2021
from queue import Queue
2122
from warnings import catch_warnings
2223

@@ -97,6 +98,7 @@
9798
from tagstudio.qt.widgets.panel import PanelModal
9899
from tagstudio.qt.widgets.preview_panel import PreviewPanel
99100
from tagstudio.qt.widgets.progress import ProgressWidget
101+
from tagstudio.qt.widgets.thumb_button import ThumbButton
100102
from tagstudio.qt.widgets.thumb_renderer import ThumbRenderer
101103

102104
BADGE_TAGS = {
@@ -406,6 +408,21 @@ def start(self) -> None:
406408
file_menu.addAction(self.refresh_dir_action)
407409
file_menu.addSeparator()
408410

411+
self.open_selected_action = QAction(Translations["file.open_files.title.plural"], self)
412+
self.open_selected_action.triggered.connect(self.open_selected_files)
413+
if system() == "Darwin":
414+
shortcut: QtCore.QKeyCombination | Qt.Key = QtCore.QKeyCombination(
415+
QtCore.Qt.KeyboardModifier(QtCore.Qt.KeyboardModifier.ControlModifier),
416+
QtCore.Qt.Key.Key_Down,
417+
)
418+
else:
419+
shortcut = Qt.Key.Key_Return
420+
421+
self.open_selected_action.setShortcut(shortcut)
422+
self.open_selected_action.setEnabled(False)
423+
file_menu.addAction(self.open_selected_action)
424+
file_menu.addSeparator()
425+
409426
self.close_library_action = QAction(Translations["menu.file.close_library"], menu_bar)
410427
self.close_library_action.triggered.connect(self.close_library)
411428
self.close_library_action.setEnabled(False)
@@ -1426,6 +1443,40 @@ def toggle_item_selection(self, item_id: int, append: bool, bridge: bool):
14261443

14271444
self.preview_panel.update_widgets()
14281445

1446+
def open_selected_files(self):
1447+
if not (
1448+
QApplication.focusWidget() == self.main_window.scrollArea
1449+
or isinstance(QApplication.focusWidget(), ThumbButton)
1450+
):
1451+
return
1452+
count = len(self.selected)
1453+
result = QMessageBox.ButtonRole.ActionRole
1454+
1455+
if count >= 5: # Only confirm if we have lots of files
1456+
confirm_open = QMessageBox()
1457+
confirm_open.setText(Translations.format("file.open_files.warning", count=count))
1458+
confirm_open.setWindowTitle(Translations["file.open_files.title"])
1459+
confirm_open.setIcon(QMessageBox.Icon.Question)
1460+
1461+
cancel_button = confirm_open.addButton(
1462+
Translations["generic.cancel_alt"], QMessageBox.ButtonRole.RejectRole
1463+
)
1464+
confirm_open.setEscapeButton(cancel_button)
1465+
1466+
open_button = confirm_open.addButton(
1467+
Translations["generic.open"], QMessageBox.ButtonRole.ActionRole
1468+
)
1469+
confirm_open.setDefaultButton(open_button)
1470+
1471+
result = QMessageBox.ButtonRole(confirm_open.exec())
1472+
1473+
if result == QMessageBox.ButtonRole.ActionRole:
1474+
opened = []
1475+
for it in self.item_thumbs:
1476+
if it.item_id in self.selected and it.item_id not in opened:
1477+
it.opener.open_file()
1478+
opened.append(it.item_id)
1479+
14291480
def set_macro_menu_viability(self):
14301481
# self.autofill_action.setDisabled(not self.selected)
14311482
pass
@@ -1453,11 +1504,20 @@ def set_select_actions_visibility(self):
14531504
self.add_tag_to_selected_action.setEnabled(True)
14541505
self.clear_select_action.setEnabled(True)
14551506
self.delete_file_action.setEnabled(True)
1507+
1508+
self.open_selected_action.setEnabled(True)
1509+
if len(self.selected) == 1:
1510+
self.open_selected_action.setText(Translations["file.open_files.title.singular"])
1511+
else:
1512+
self.open_selected_action.setText(Translations["file.open_files.title.plural"])
14561513
else:
14571514
self.add_tag_to_selected_action.setEnabled(False)
14581515
self.clear_select_action.setEnabled(False)
14591516
self.delete_file_action.setEnabled(False)
14601517

1518+
self.open_selected_action.setEnabled(False)
1519+
self.open_selected_action.setText(Translations["file.open_files.title.plural"])
1520+
14611521
def update_completions_list(self, text: str) -> None:
14621522
matches = re.search(
14631523
r"((?:.* )?)(mediatype|filetype|path|tag|tag_id):(\"?[A-Za-z0-9\ \t]+\"?)?", text

src/tagstudio/qt/widgets/item_thumb.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@ def __init__(
230230
self.thumb_button.addAction(open_file_action)
231231
self.thumb_button.addAction(open_explorer_action)
232232
self.thumb_button.addAction(self.delete_action)
233+
self.thumb_button.double_clicked.connect(self.opener.open_file)
233234

234235
# Static Badges ========================================================
235236

src/tagstudio/qt/widgets/thumb_button.py

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,35 @@
1-
# Copyright (C) 2024 Travis Abendshien (CyanVoxel).
1+
# Copyright (C) 2025 Travis Abendshien (CyanVoxel).
22
# Licensed under the GPL-3.0 License.
33
# Created for TagStudio: https://github.com/CyanVoxel/TagStudio
44

55

66
import sys
7+
from typing import override
78

89
from PySide6 import QtCore
9-
from PySide6.QtCore import QEvent
10+
from PySide6.QtCore import QEvent, Signal
1011
from PySide6.QtGui import (
1112
QColor,
1213
QEnterEvent,
14+
QMouseEvent,
1315
QPainter,
1416
QPainterPath,
1517
QPaintEvent,
1618
QPalette,
1719
QPen,
1820
)
19-
from PySide6.QtWidgets import QWidget
21+
from PySide6.QtWidgets import QPushButton, QWidget
2022

21-
from tagstudio.qt.helpers.qbutton_wrapper import QPushButtonWrapper
2223

24+
class ThumbButton(QPushButton):
25+
double_clicked = Signal()
2326

24-
class ThumbButton(QPushButtonWrapper):
2527
def __init__(self, parent: QWidget, thumb_size: tuple[int, int]) -> None: # noqa: N802
2628
super().__init__(parent)
2729
self.thumb_size: tuple[int, int] = thumb_size
2830
self.hovered = False
2931
self.selected = False
32+
self.double_click = False
3033

3134
# NOTE: As of PySide 6.8.0.1, the QPalette.ColorRole.Accent role no longer works on Windows.
3235
# The QPalette.ColorRole.AlternateBase does for some reason, but not on macOS.
@@ -85,8 +88,9 @@ def __init__(self, parent: QWidget, thumb_size: tuple[int, int]) -> None: # noq
8588
self.hover_color.alpha(),
8689
)
8790

88-
def paintEvent(self, event: QPaintEvent) -> None: # noqa: N802
89-
super().paintEvent(event)
91+
@override
92+
def paintEvent(self, arg__1: QPaintEvent) -> None: # noqa: N802
93+
super().paintEvent(arg__1)
9094
if self.hovered or self.selected:
9195
painter = QPainter()
9296
painter.begin(self)
@@ -125,11 +129,13 @@ def paintEvent(self, event: QPaintEvent) -> None: # noqa: N802
125129

126130
painter.end()
127131

132+
@override
128133
def enterEvent(self, event: QEnterEvent) -> None: # noqa: N802
129134
self.hovered = True
130135
self.repaint()
131136
return super().enterEvent(event)
132137

138+
@override
133139
def leaveEvent(self, event: QEvent) -> None: # noqa: N802
134140
self.hovered = False
135141
self.repaint()
@@ -138,3 +144,18 @@ def leaveEvent(self, event: QEvent) -> None: # noqa: N802
138144
def set_selected(self, value: bool) -> None: # noqa: N802
139145
self.selected = value
140146
self.repaint()
147+
148+
@override
149+
def mousePressEvent(self, e: QMouseEvent) -> None: # noqa: N802
150+
self.double_click = False
151+
152+
@override
153+
def mouseDoubleClickEvent(self, event: QMouseEvent) -> None: # noqa: N802
154+
self.double_click = True
155+
156+
@override
157+
def mouseReleaseEvent(self, e: QMouseEvent) -> None: # noqa: N802
158+
if self.double_click:
159+
self.double_clicked.emit()
160+
else:
161+
self.clicked.emit()

src/tagstudio/resources/translations/en.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,9 @@
8484
"file.not_found": "File Not Found",
8585
"file.open_file_with": "Open file with",
8686
"file.open_file": "Open file",
87+
"file.open_files.title.plural": "Open Selected Files",
88+
"file.open_files.title.singular": "Open Selected File",
89+
"file.open_files.warning": "Are you sure you want to open {count} files?",
8790
"file.open_location.generic": "Show file in file explorer",
8891
"file.open_location.mac": "Reveal in Finder",
8992
"file.open_location.windows": "Show in File Explorer",
@@ -112,6 +115,7 @@
112115
"generic.navigation.back": "Back",
113116
"generic.navigation.next": "Next",
114117
"generic.none": "None",
118+
"generic.open": "Open",
115119
"generic.overwrite_alt": "&Overwrite",
116120
"generic.overwrite": "Overwrite",
117121
"generic.paste": "Paste",

0 commit comments

Comments
 (0)