diff --git a/src/calibre/gui2/images/books_in_series.svg b/src/calibre/gui2/images/books_in_series.svg
new file mode 100644
index 0000000000..a9f39ca982
--- /dev/null
+++ b/src/calibre/gui2/images/books_in_series.svg
@@ -0,0 +1,581 @@
+
+
+
\ No newline at end of file
diff --git a/src/calibre/gui2/library.py b/src/calibre/gui2/library.py
index f2571c5de7..75d2aade59 100644
--- a/src/calibre/gui2/library.py
+++ b/src/calibre/gui2/library.py
@@ -575,7 +575,7 @@ class BooksView(TableView):
self.setItemDelegateForColumn(col, self.rating_delegate)
def set_context_menu(self, edit_metadata, send_to_device, convert, view,
- save, open_folder, book_details):
+ save, open_folder, book_details, similar_menu=None):
self.setContextMenuPolicy(Qt.DefaultContextMenu)
self.context_menu = QMenu(self)
if edit_metadata is not None:
@@ -590,6 +590,8 @@ class BooksView(TableView):
self.context_menu.addAction(open_folder)
if book_details is not None:
self.context_menu.addAction(book_details)
+ if similar_menu is not None:
+ self.context_menu.addMenu(similar_menu)
def contextMenuEvent(self, event):
self.context_menu.popup(event.globalPos())
diff --git a/src/calibre/gui2/main.py b/src/calibre/gui2/main.py
index 200ebcc225..f0a0ad1d40 100644
--- a/src/calibre/gui2/main.py
+++ b/src/calibre/gui2/main.py
@@ -234,10 +234,33 @@ class Main(MainWindow, Ui_MainWindow):
QObject.connect(self.advanced_search_button, SIGNAL('clicked(bool)'), self.do_advanced_search)
####################### Library view ########################
+ similar_menu = QMenu(_('Similar books...'))
+ similar_menu.addAction(self.action_books_by_same_author)
+ similar_menu.addAction(self.action_books_in_this_series)
+ similar_menu.addAction(self.action_books_with_the_same_tags)
+ similar_menu.addAction(self.action_books_by_this_publisher)
+ self.action_books_by_same_author.setShortcut(Qt.ALT + Qt.Key_A)
+ self.action_books_in_this_series.setShortcut(Qt.ALT + Qt.Key_S)
+ self.action_books_by_this_publisher.setShortcut(Qt.ALT + Qt.Key_P)
+ self.action_books_with_the_same_tags.setShortcut(Qt.ALT+Qt.Key_T)
+ self.addAction(self.action_books_by_same_author)
+ self.addAction(self.action_books_by_this_publisher)
+ self.addAction(self.action_books_in_this_series)
+ self.addAction(self.action_books_with_the_same_tags)
+ self.similar_menu = similar_menu
+ self.connect(self.action_books_by_same_author, SIGNAL('triggered()'),
+ lambda : self.show_similar_books('author'))
+ self.connect(self.action_books_in_this_series, SIGNAL('triggered()'),
+ lambda : self.show_similar_books('series'))
+ self.connect(self.action_books_with_the_same_tags, SIGNAL('triggered()'),
+ lambda : self.show_similar_books('tag'))
+ self.connect(self.action_books_by_this_publisher, SIGNAL('triggered()'),
+ lambda : self.show_similar_books('publisher'))
self.library_view.set_context_menu(self.action_edit, self.action_sync,
self.action_convert, self.action_view,
self.action_save, self.action_open_containing_folder,
- self.action_show_book_details)
+ self.action_show_book_details,
+ similar_menu=similar_menu)
self.memory_view.set_context_menu(None, None, None, self.action_view, self.action_save, None, None)
self.card_view.set_context_menu(None, None, None, self.action_view, self.action_save, None, None)
QObject.connect(self.library_view, SIGNAL('files_dropped(PyQt_PyObject)'),
@@ -341,6 +364,34 @@ class Main(MainWindow, Ui_MainWindow):
error_dialog(self, _('Failed to start content server'),
unicode(self.content_server.exception)).exec_()
+ def show_similar_books(self, type):
+ search, join = [], ' '
+ idx = self.library_view.currentIndex()
+ if not idx.isValid():
+ return
+ row = idx.row()
+ if type == 'series':
+ series = idx.model().db.series(row)
+ if series:
+ search = ['series:'+series]
+ elif type == 'publisher':
+ publisher = idx.model().db.publisher(row)
+ if publisher:
+ search = ['publisher:'+publisher]
+ elif type == 'tag':
+ tags = idx.model().db.tags(row)
+ if tags:
+ search = ['tag:'+t for t in tags.split(',')]
+ elif type == 'author':
+ authors = idx.model().db.authors(row)
+ if authors:
+ search = ['author:'+a.strip().replace('|', ',') for a in authors.split(',')]
+ join = ' or '
+ if search:
+ self.search.set_search_string(join.join(search))
+
+
+
def toggle_cover_flow(self, show):
if show:
self.library_view.setCurrentIndex(self.library_view.currentIndex())
diff --git a/src/calibre/gui2/main.ui b/src/calibre/gui2/main.ui
index 18d6f5228d..1833789f61 100644
--- a/src/calibre/gui2/main.ui
+++ b/src/calibre/gui2/main.ui
@@ -581,6 +581,42 @@
Show book details
+
+
+
+ :/images/user_profile.svg:/images/user_profile.svg
+
+
+ Books by same author
+
+
+
+
+
+ :/images/books_in_series.svg:/images/books_in_series.svg
+
+
+ Books in this series
+
+
+
+
+
+ :/images/publisher.png:/images/publisher.png
+
+
+ Books by this publisher
+
+
+
+
+
+ :/images/tags.svg:/images/tags.svg
+
+
+ Books with the same tags
+
+