From 3b6dfdeaa5ea444aec2f5bc0c4759a95a092f804 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 30 Oct 2024 09:03:32 +0530 Subject: [PATCH] Edit metadata dialog: Add an action to open the book's folder to the context menu of the formats list. Fixes #2083583 [[Enhancement] Action to open the Book folder when you right click the format in Edit metadata window](https://bugs.launchpad.net/calibre/+bug/2083583) --- src/calibre/gui2/extra_files_watcher.py | 7 +++- src/calibre/gui2/metadata/basic_widgets.py | 43 +++++++++++++--------- src/calibre/gui2/metadata/single.py | 8 ++++ 3 files changed, 38 insertions(+), 20 deletions(-) diff --git a/src/calibre/gui2/extra_files_watcher.py b/src/calibre/gui2/extra_files_watcher.py index 0a933679cf..9843570860 100644 --- a/src/calibre/gui2/extra_files_watcher.py +++ b/src/calibre/gui2/extra_files_watcher.py @@ -5,7 +5,7 @@ from time import monotonic from typing import NamedTuple, Tuple -from qt.core import QObject, QTimer +from qt.core import QObject, QTimer, pyqtSignal from calibre.db.constants import DATA_FILE_PATTERN @@ -23,6 +23,7 @@ class ExtraFiles(NamedTuple): class ExtraFilesWatcher(QObject): + books_changed = pyqtSignal(object) WATCH_FOR = 300 # seconds TICK_INTERVAL = 1 # seconds @@ -86,4 +87,6 @@ class ExtraFilesWatcher(QObject): def refresh_gui(self, book_ids): lv = self.gui.library_view - lv.model().refresh_ids(frozenset(book_ids), current_row=lv.currentIndex().row()) + book_ids = frozenset(book_ids) + lv.model().refresh_ids(book_ids, current_row=lv.currentIndex().row()) + self.books_changed.emit(book_ids) diff --git a/src/calibre/gui2/metadata/basic_widgets.py b/src/calibre/gui2/metadata/basic_widgets.py index b16df395f3..4d1602e163 100644 --- a/src/calibre/gui2/metadata/basic_widgets.py +++ b/src/calibre/gui2/metadata/basic_widgets.py @@ -858,6 +858,7 @@ class FormatList(_FormatList): restore_fmt = pyqtSignal(object) view_fmt = pyqtSignal(object) edit_fmt = pyqtSignal(object) + open_book_folder = pyqtSignal() def __init__(self, parent): _FormatList.__init__(self, parent) @@ -873,28 +874,30 @@ class FormatList(_FormatList): originals = [self.item(x).ext.upper() for x in range(self.count())] originals = [x for x in originals if x.startswith('ORIGINAL_')] - if item or originals: - self.cm = cm = QMenu(self) + self.cm = cm = QMenu(self) - if item: - action = ViewAction(item, cm) - action.view_fmt.connect(self.view_fmt, type=Qt.ConnectionType.QueuedConnection) + if item: + action = ViewAction(item, cm) + action.view_fmt.connect(self.view_fmt, type=Qt.ConnectionType.QueuedConnection) + cm.addAction(action) + + if item.ext.upper() in EDIT_SUPPORTED: + action = EditAction(item, cm) + action.edit_fmt.connect(self.edit_fmt, type=Qt.ConnectionType.QueuedConnection) cm.addAction(action) - if item.ext.upper() in EDIT_SUPPORTED: - action = EditAction(item, cm) - action.edit_fmt.connect(self.edit_fmt, type=Qt.ConnectionType.QueuedConnection) - cm.addAction(action) + if item and originals: + cm.addSeparator() - if item and originals: - cm.addSeparator() - - for fmt in originals: - action = OrigAction(fmt, cm) - action.restore_fmt.connect(self.restore_fmt) - cm.addAction(action) - cm.popup(event.globalPos()) - event.accept() + for fmt in originals: + action = OrigAction(fmt, cm) + action.restore_fmt.connect(self.restore_fmt) + cm.addAction(action) + ac = QAction(_('Open book folder'), cm) + ac.triggered.connect(self.open_book_folder) + cm.addAction(ac) + cm.popup(event.globalPos()) + event.accept() def remove_format(self, fmt): for i in range(self.count()): @@ -959,6 +962,7 @@ class FormatsManager(QWidget): self.formats.formats_dropped.connect(self.formats_dropped) self.formats.restore_fmt.connect(self.restore_fmt) self.formats.view_fmt.connect(self.show_format) + self.formats.open_book_folder.connect(self.open_book_folder) self.formats.edit_fmt.connect(self.edit_format) self.formats.delete_format.connect(self.remove_format) self.formats.itemDoubleClicked.connect(self.show_format) @@ -1093,6 +1097,9 @@ class FormatsManager(QWidget): def show_format(self, item, *args): self.dialog.do_view_format(item.path, item.ext) + def open_book_folder(self, *a): + self.dialog.do_open_book_folder() + def edit_format(self, item, *args): from calibre.gui2.widgets import BusyCursor with BusyCursor(): diff --git a/src/calibre/gui2/metadata/single.py b/src/calibre/gui2/metadata/single.py index c408e52595..9367ddf228 100644 --- a/src/calibre/gui2/metadata/single.py +++ b/src/calibre/gui2/metadata/single.py @@ -399,6 +399,10 @@ class MetadataSingleDialogBase(QDialog): else: self.view_format.emit(self.book_id, fmt) + def do_open_book_folder(self): + from calibre.gui2.ui import get_gui + get_gui().iactions['View'].view_folder_for_id(self.book_id) + def do_edit_format(self, path, fmt): if self.was_data_edited: from calibre.gui2.tweak_book import tprefs @@ -1330,11 +1334,15 @@ def edit_metadata(db, row_list, current_row, parent=None, view_slot=None, edit_s if cls not in editors: cls = 'default' d = editors[cls](db, parent, editing_multiple=editing_multiple) + if hasattr(parent, 'extra_files_watcher'): + conn = parent.extra_files_watcher.books_changed.connect(d.update_data_files_button) try: d.start(row_list, current_row, view_slot=view_slot, edit_slot=edit_slot, set_current_callback=set_current_callback) return d.changed, d.rows_to_refresh finally: + if hasattr(parent, 'extra_files_watcher'): + parent.extra_files_watcher.disconnect(conn) # possible workaround for bug reports of occasional ghost edit metadata dialog on windows d.deleteLater()