diff --git a/src/calibre/customize/builtins.py b/src/calibre/customize/builtins.py index b542593a79..008aa8a106 100644 --- a/src/calibre/customize/builtins.py +++ b/src/calibre/customize/builtins.py @@ -1022,6 +1022,12 @@ class ActionMatchBooks(InterfaceActionBase): description = _('Match book on the devices to books in the library') +class ActionShowMatchedBooks(InterfaceActionBase): + name = 'Show Matched Book In Library' + actual_plugin = 'calibre.gui2.actions.match_books:ShowMatchedBookAction' + description = _('Show the book in the calibre library that matches this book') + + class ActionCopyToLibrary(InterfaceActionBase): name = 'Copy To Library' actual_plugin = 'calibre.gui2.actions.copy_to_library:CopyToLibraryAction' @@ -1101,7 +1107,7 @@ plugins += [ActionAdd, ActionFetchAnnotations, ActionGenerateCatalog, ActionFetchNews, ActionSaveToDisk, ActionQuickview, ActionPolish, ActionShowBookDetails,ActionRestart, ActionOpenFolder, ActionConnectShare, ActionSendToDevice, ActionHelp, ActionPreferences, ActionSimilarBooks, - ActionAddToLibrary, ActionEditCollections, ActionMatchBooks, ActionChooseLibrary, + ActionAddToLibrary, ActionEditCollections, ActionMatchBooks, ActionShowMatchedBooks, ActionChooseLibrary, ActionCopyToLibrary, ActionTweakEpub, ActionUnpackBook, ActionNextMatch, ActionStore, ActionPluginUpdater, ActionPickRandom, ActionEditToC, ActionSortBy, ActionMarkBooks, ActionEmbed, ActionTemplateTester, ActionTagMapper, ActionAuthorMapper, diff --git a/src/calibre/db/cache.py b/src/calibre/db/cache.py index e0a19330d6..04f6428a75 100644 --- a/src/calibre/db/cache.py +++ b/src/calibre/db/cache.py @@ -1905,6 +1905,14 @@ class Cache(object): self.clear_search_caches() self.clear_composite_caches() + @read_api + def books_matching_device_book(self, lpath): + ans = set() + for book_id, (_, _, _, _, lpaths) in self.fields['ondevice'].cache.items(): + if lpath in lpaths: + ans.add(book_id) + return ans + @read_api def tags_older_than(self, tag, delta=None, must_have_tag=None, must_have_authors=None): ''' diff --git a/src/calibre/gui2/__init__.py b/src/calibre/gui2/__init__.py index 35629a5185..51a2687e34 100644 --- a/src/calibre/gui2/__init__.py +++ b/src/calibre/gui2/__init__.py @@ -117,7 +117,8 @@ def create_defs(): defs['action-layout-context-menu-device'] = ( 'View', 'Save To Disk', None, 'Remove Books', None, - 'Add To Library', 'Edit Collections', 'Match Books' + 'Add To Library', 'Edit Collections', 'Match Books', + 'Show Matched Book In Library' ) defs['action-layout-context-menu-cover-browser'] = ( diff --git a/src/calibre/gui2/actions/match_books.py b/src/calibre/gui2/actions/match_books.py index cff2add270..eb8507905f 100644 --- a/src/calibre/gui2/actions/match_books.py +++ b/src/calibre/gui2/actions/match_books.py @@ -6,7 +6,7 @@ __license__ = 'GPL v3' __copyright__ = '2013, Kovid Goyal ' __docformat__ = 'restructuredtext en' -from calibre.gui2 import error_dialog +from calibre.gui2 import error_dialog, question_dialog from calibre.gui2.actions import InterfaceAction from calibre.gui2.dialogs.match_books import MatchBooks @@ -38,3 +38,45 @@ class MatchBookAction(InterfaceAction): id_ = view.model().indices(rows)[0] MatchBooks(self.gui, view, id_, rows[0]).exec_() + + +class ShowMatchedBookAction(InterfaceAction): + + name = 'Show Matched Book In Library' + action_spec = (_('Show matched book in library'), 'lt.png', + _('Show the book in the calibre library that matches this book'), + ()) + dont_add_to = frozenset(('menubar', 'toolbar', 'context-menu', 'toolbar-child', 'context-menu-cover-browser')) + action_type = 'current' + + def genesis(self): + self.qaction.triggered.connect(self.show_matched_books_in_library) + + def location_selected(self, loc): + enabled = loc != 'library' + self.qaction.setEnabled(enabled) + self.menuless_qaction.setEnabled(enabled) + + def show_matched_books_in_library(self, *args): + view = self.gui.current_view() + rows = view.selectionModel().selectedRows() + if not rows or len(rows) != 1: + d = error_dialog(self.gui, _('Match books'), _('You must select one book')) + d.exec_() + return + + device_book_index = view.model().indices(rows)[0] + device_db = view.model().db + db = self.gui.current_db.new_api + book = device_db[device_book_index] + matching_book_ids = db.books_matching_device_book(book.lpath) + if not matching_book_ids: + if question_dialog(self.gui, _('No matching books'), _( + 'No matching books found in the calibre library. Do you want to specify the' + ' matching book manually?')): + MatchBooks(self.gui, view, device_book_index, rows[0]).exec_() + return + ids = tuple(sorted(matching_book_ids, reverse=True)) + self.gui.library_view.select_rows(ids) + self.gui.show_library_view() + self.gui.iactions['Edit Metadata'].refresh_books_after_metadata_edit(ids) diff --git a/src/calibre/gui2/ui.py b/src/calibre/gui2/ui.py index c92283c0f6..f07fee9f31 100644 --- a/src/calibre/gui2/ui.py +++ b/src/calibre/gui2/ui.py @@ -808,6 +808,9 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{ if idx == 3: return self.card_b_view + def show_library_view(self): + self.location_manager.library_action.trigger() + def booklists(self): return self.memory_view.model().db, self.card_a_view.model().db, self.card_b_view.model().db