From cdae060f475b7c3b2fb6e82b0ccd188242a5d857 Mon Sep 17 00:00:00 2001 From: Charles Haley Date: Sun, 16 Aug 2020 16:02:11 +0100 Subject: [PATCH] Enhancement #1891765: Add operations to quickview's context menu. Added several operations to the quickview book and item list context menus. As a result the search button became superfluous and was removed. --- src/calibre/gui2/actions/show_quickview.py | 8 -- src/calibre/gui2/dialogs/quickview.py | 140 +++++++++++++++------ src/calibre/gui2/dialogs/quickview.ui | 80 ++++-------- 3 files changed, 128 insertions(+), 100 deletions(-) diff --git a/src/calibre/gui2/actions/show_quickview.py b/src/calibre/gui2/actions/show_quickview.py index 5a9a45f2c2..4e9e0e681e 100644 --- a/src/calibre/gui2/actions/show_quickview.py +++ b/src/calibre/gui2/actions/show_quickview.py @@ -104,8 +104,6 @@ class ShowQuickviewAction(InterfaceAction): default_keys=('Shift+S',), action=self.search_action, group=self.action_spec[0]) self.search_action.triggered.connect(self.search_quickview) - self.search_action.changed.connect(self.set_search_shortcut_tooltip) - self.menuless_qaction.changed.connect(self.set_search_shortcut_tooltip) self.qv_button = QuickviewButton(self.gui, self) @@ -139,15 +137,9 @@ class ShowQuickviewAction(InterfaceAction): self.current_instance = Quickview(self.gui, index, self.qaction.shortcut()) self.current_instance.reopen_after_dock_change.connect(self.open_quickview) - self.set_search_shortcut_tooltip() self.current_instance.show() self.current_instance.quickview_closed.connect(self.qv_button.set_state_to_show) - def set_search_shortcut_tooltip(self): - if self.current_instance and not self.current_instance.is_closed: - self.current_instance.addAction(self.focus_bl_action) - self.current_instance.set_search_shortcut_tooltip(self.search_action.shortcut().toString()) - def open_quickview(self): ''' QV moved from/to dock. Close and reopen the pane/window. diff --git a/src/calibre/gui2/dialogs/quickview.py b/src/calibre/gui2/dialogs/quickview.py index a7c1d76e3a..04a6aa604c 100644 --- a/src/calibre/gui2/dialogs/quickview.py +++ b/src/calibre/gui2/dialogs/quickview.py @@ -173,6 +173,7 @@ class Quickview(QDialog, Ui_Quickview): self.current_key = None # current lookup key in books list self.last_search = None self.no_valid_items = False + self.follow_library_view = True self.apply_vls.setCheckState(Qt.Checked if gprefs['qv_respects_vls'] else Qt.Unchecked) @@ -184,6 +185,8 @@ class Quickview(QDialog, Ui_Quickview): self.items.currentTextChanged.connect(self.item_selected) self.items.setProperty('highlight_current_item', 150) self.items.itemDoubleClicked.connect(self.item_doubleclicked) + self.items.setContextMenuPolicy(Qt.CustomContextMenu) + self.items.customContextMenuRequested.connect(self.show_item_context_menu) focus_filter = WidgetFocusFilter(self.items) focus_filter.focus_entered_signal.connect(self.focus_entered) @@ -202,7 +205,7 @@ class Quickview(QDialog, Ui_Quickview): self.refresh_button.clicked.connect(self.refill) self.tab_order_widgets = [self.items, self.books_table, self.lock_qv, - self.dock_button, self.search_button, self.refresh_button, + self.dock_button, self.refresh_button, self.close_button] for idx,widget in enumerate(self.tab_order_widgets): widget.installEventFilter(WidgetTabFilter(widget, idx, self.tab_pressed_signal)) @@ -236,20 +239,16 @@ class Quickview(QDialog, Ui_Quickview): self.view.clicked.connect(self.slave) self.view.selectionModel().currentColumnChanged.connect(self.column_slave) QCoreApplication.instance().aboutToQuit.connect(self.save_state) - self.search_button.clicked.connect(self.do_search) self.view.model().new_bookdisplay_data.connect(self.book_was_changed) self.close_button.setDefault(False) self.close_button_tooltip = _('The Quickview shortcut ({0}) shows/hides the Quickview panel') - self.search_button_tooltip = _('Search in the library view for the currently highlighted selection') - self.search_button.setToolTip(self.search_button_tooltip) if self.is_pane: self.dock_button.setText(_('Undock')) self.dock_button.setToolTip(_('Pop up the quickview panel into its own floating window')) self.dock_button.setIcon(QIcon(I('arrow-up.png'))) # Remove the ampersands from the buttons because shortcuts exist. self.lock_qv.setText(_('Lock Quickview contents')) - self.search_button.setText(_('Search')) self.refresh_button.setText(_('Refresh')) self.gui.quickview_splitter.add_quickview_dialog(self) self.close_button.setVisible(False) @@ -268,6 +267,10 @@ class Quickview(QDialog, Ui_Quickview): self.view_icon = QIcon(I('view.png')) self.view_plugin = self.gui.iactions['View'] + self.edit_metadata_icon = QIcon(I('edit_input.png')) + self.quickview_icon = QIcon(I('quickview.png')) + self.select_book_icon = QIcon(I('library.png')) + self.search_icon = QIcon(I('search.png')) self.books_table.setContextMenuPolicy(Qt.CustomContextMenu) self.books_table.customContextMenuRequested.connect(self.show_context_menu) @@ -288,15 +291,41 @@ class Quickview(QDialog, Ui_Quickview): tb.item_search.lineEdit().setText(self.current_key + ':=' + item.text()) tb.do_find() + def show_item_context_menu(self, point): + item = self.items.currentItem() + self.context_menu = QMenu(self) + self.context_menu.addAction(self.search_icon, _('Search for item in tag browser'), + partial(self.item_doubleclicked, item)) + self.context_menu.addAction(self.search_icon, _('Search for item in library'), + partial(self.do_search, follow_library_view=False)) + self.context_menu.popup(self.items.mapToGlobal(point)) + self.context_menu = QMenu(self) + def show_context_menu(self, point): index = self.books_table.indexAt(point) + row = index.row() + column = index.column() item = self.books_table.item(index.row(), 0) if item is None: return False book_id = int(item.data(Qt.UserRole)) - self.context_menu = QMenu(self) - self.context_menu.addAction(self.view_icon, _('View'), - partial(self.view_plugin._view_calibre_books, [book_id])) + book_displayed = self.book_displayed_in_library_view(book_id) + m = self.context_menu = QMenu(self) + a = m.addAction(self.select_book_icon, _('Select book in library'), + partial(self.select_book, book_id)) + a.setEnabled(book_displayed) + m.addAction(self.search_icon, _('Search for item in library'), + partial(self.do_search, follow_library_view=False)) + a = m.addAction(self.edit_metadata_icon, _('Edit book metadata'), + partial(self.edit_metadata, book_id, follow_library_view=False)) + a.setEnabled(book_displayed) + a = m.addAction(self.quickview_icon, _('Quickview this cell'), + partial(self.quickview_item, row, column)) + a.setEnabled(self.is_category(self.column_order[column]) and + book_displayed and not self.lock_qv.isChecked()) + m.addSeparator() + m.addAction(self.view_icon, _('Open book in viewer'), + partial(self.view_plugin._view_calibre_books, [book_id])) self.context_menu.popup(self.books_table.mapToGlobal(point)) return True @@ -324,16 +353,8 @@ class Quickview(QDialog, Ui_Quickview): self._refresh(self.current_book_id, self.current_key) def set_search_text(self, txt): - if txt: - self.search_button.setEnabled(True) - else: - self.search_button.setEnabled(False) self.last_search = txt - def set_search_shortcut_tooltip(self, search_sc): - if self.is_pane: - self.search_button.setToolTip(self.search_button_tooltip + ' (' + search_sc + ')') - def focus_entered(self, obj): if obj == self.books_table: self.books_table_set_search_string(self.books_table.currentRow(), @@ -400,11 +421,15 @@ class Quickview(QDialog, Ui_Quickview): self.reopen_after_dock_change.emit() # search button - def do_search(self): + def do_search(self, follow_library_view=True): if self.no_valid_items: return if self.last_search is not None: - self.gui.search.set_search_string(self.last_search) + try: + self.follow_library_view = follow_library_view + self.gui.search.set_search_string(self.last_search) + finally: + self.follow_library_view = True def book_was_changed(self, mi): ''' @@ -412,7 +437,7 @@ class Quickview(QDialog, Ui_Quickview): book info current. This means that prev and next in edit metadata will move the current book and change quickview ''' - if self.is_closed or self.current_column is None: + if self.is_closed or self.current_column is None or not self.follow_library_view: return # There is an ordering problem when libraries are changed. The library # view is changed, triggering a book_was_changed signal. Unfortunately @@ -457,13 +482,16 @@ class Quickview(QDialog, Ui_Quickview): traceback.print_exc() self.indicate_no_items() + def is_category(self, key): + return key is not None and self.fm[key]['is_category'] + def _refresh(self, book_id, key): ''' Actually fill in the left-hand panel from the information in the selected column of the selected book ''' # Only show items for categories - if key is None or not self.fm[key]['is_category']: + if not self.is_category(key): if self.current_key is None: self.indicate_no_items() return @@ -557,7 +585,7 @@ class Quickview(QDialog, Ui_Quickview): self.books_table.setSortingEnabled(False) self.books_table.blockSignals(True) tt = ('

' + _( - 'Double click on a book to change the selection in the library view or ' + 'Double click on a book to change the selection in the library view or ' 'change the column shown in the left-hand panel. ' 'Shift- or Control- double click to edit the metadata of a book, ' 'which also changes the selected book.' @@ -643,28 +671,62 @@ class Quickview(QDialog, Ui_Quickview): def return_pressed(self): row = self.books_table.currentRow() if gprefs['qv_retkey_changes_column']: - self.select_book(row, self.books_table.currentColumn()) + self.select_book_and_qv(row, self.books_table.currentColumn()) else: - self.select_book(row, self.key_to_table_widget_column(self.current_key)) + self.select_book_and_qv(row, self.key_to_table_widget_column(self.current_key)) + + def book_not_in_view_error(self): + from calibre.gui2 import error_dialog + error_dialog(self, _('Quickview: Book not in library view'), + _('The book you selected is not currently displayed in ' + 'the library view, perhaps because of a search or a ' + 'virtual library, so Quickview cannot select it.'), + show=True, + show_copy_button=False) + + def book_displayed_in_library_view(self, book_id): + try: + self.db.data.index(book_id) + return True + except: + return False + + def quickview_item(self, row, column): + self.select_book_and_qv(row, column) def book_doubleclicked(self, row, column): if self.no_valid_items: return try: if gprefs['qv_dclick_changes_column']: - self.select_book(row, column) + self.quickview_item(row, column) else: - self.select_book(row, self.key_to_table_widget_column(self.current_key)) + self.quickview_item(row, self.key_to_table_widget_column(self.current_key)) except: - from calibre.gui2 import error_dialog - error_dialog(self, _('Quickview: Book not in library view'), - _('The book you selected is not currently displayed in ' - 'the library view, perhaps because of a search, so ' - 'Quickview cannot select it.'), - show=True, - show_copy_button=False) + self.book_not_in_view_error() - def select_book(self, row, column): + def edit_metadata(self, book_id, follow_library_view=True): + try: + self.follow_library_view = follow_library_view + self.view.select_rows([book_id]) + em = find_plugin('Edit Metadata') + if em and em.actual_plugin_: + em.actual_plugin_.edit_metadata(None) + finally: + self.follow_library_view = True + + def select_book(self, book_id): + ''' + Select a book in the library view without changing the QV lists + ''' + try: + self.follow_library_view = False + self.view.select_cell(self.db.data.id_to_index(book_id), + self.current_column) + finally: + self.follow_library_view = True + + def select_book_and_qv(self, row, column): ''' row and column both refer the qv table. In particular, column is not the logical column in the book list. @@ -673,13 +735,13 @@ class Quickview(QDialog, Ui_Quickview): if item is None: return book_id = int(self.books_table.item(row, column).data(Qt.UserRole)) + if not self.book_displayed_in_library_view(book_id): + self.book_not_in_view_error() + return key = self.column_order[column] modifiers = int(QApplication.keyboardModifiers()) if modifiers in (Qt.CTRL, Qt.SHIFT): - self.view.select_rows([book_id]) - em = find_plugin('Edit Metadata') - if em and em.actual_plugin_: - em.actual_plugin_.edit_metadata(None) + self.edit_metadata(book_id) else: self.view.select_cell(self.db.data.id_to_index(book_id), self.view.column_map.index(key)) @@ -692,14 +754,14 @@ class Quickview(QDialog, Ui_Quickview): ''' called when the column is changed on the booklist ''' - if gprefs['qv_follows_column']: + if self.follow_library_view and gprefs['qv_follows_column']: self.slave(current) def slave(self, current): ''' called when a book is clicked on the library view ''' - if self.is_closed: + if self.is_closed or not self.follow_library_view: return self.refresh(current) self.view.activateWindow() diff --git a/src/calibre/gui2/dialogs/quickview.ui b/src/calibre/gui2/dialogs/quickview.ui index 0747b34c5b..8d71dd6f6f 100644 --- a/src/calibre/gui2/dialogs/quickview.ui +++ b/src/calibre/gui2/dialogs/quickview.ui @@ -86,17 +86,6 @@ - - - - &Lock Quickview contents - - - <p>Select to prevent Quickview from changing content when the - selection on the library view is changed</p> - - - @@ -111,54 +100,16 @@ - + - &Dock - - - false - - - - - - - Qt::Horizontal - - - - 0 - 0 - - - - - - - - &Search + &Lock Quickview contents - Search in the library view for the currently highlighted selection - - - false + <p>Select to prevent Quickview from changing content when the + selection on the library view is changed</p> - - - - Qt::Horizontal - - - - 0 - 0 - - - - @@ -185,6 +136,29 @@ + + + + &Dock + + + false + + + + + + + Qt::Horizontal + + + + 0 + 0 + + + +