From 1b95f02f2a76d3a26f073eb235f4f04e187dcb49 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 2 Dec 2025 06:10:52 +0530 Subject: [PATCH] Add a item to the similar books menu to ask ai for what to read next --- src/calibre/gui2/actions/similar_books.py | 26 ++++++++++++++++++----- src/calibre/gui2/dialogs/llm_book.py | 7 ++++++ 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/src/calibre/gui2/actions/similar_books.py b/src/calibre/gui2/actions/similar_books.py index 21345fa260..c881ad550e 100644 --- a/src/calibre/gui2/actions/similar_books.py +++ b/src/calibre/gui2/actions/similar_books.py @@ -24,18 +24,34 @@ class SimilarBooksAction(InterfaceAction): def genesis(self): m = self.qaction.menu() for text, icon, target, shortcut in [ - (_('Books by same author'), 'user_profile.png', 'authors', 'Alt+A'), - (_('Books in this series'), 'books_in_series.png', 'series', - 'Alt+Shift+S'), - (_('Books by this publisher'), 'publisher.png', 'publisher', 'Alt+P'), - (_('Books with the same tags'), 'tags.png', 'tags', 'Alt+T'),]: + (_('Books by same author'), 'user_profile.png', 'authors', 'Alt+A'), + (_('Books in this series'), 'books_in_series.png', 'series', + 'Alt+Shift+S'), + (_('Books by this publisher'), 'publisher.png', 'publisher', 'Alt+P'), + (_('Books with the same tags'), 'tags.png', 'tags', 'Alt+T'), + ]: ac = self.create_action(spec=(text, icon, None, shortcut), attr=target) ac.setObjectName(target) m.addAction(ac) connect_lambda(ac.triggered, self, lambda self: self.show_similar_books(self.gui.sender().objectName())) + ac = self.create_action(spec=(_('Ask AI for what to read next'), 'ai.png', None, 'Ctrl+Shift+A'), attr='ai') + ac.setObjectName('ai') + m.addAction(ac) + ac.triggered.connect(self.ask_ai) self.qaction.setMenu(m) + def ask_ai(self): + idx = self.gui.library_view.currentIndex() + if not idx.isValid(): + return + db = idx.model().db + mi = db.new_api.get_metadata(db.id(idx.row())) + from calibre.gui2.dialogs.llm_book import LLMBookDialog, read_next_action + d = LLMBookDialog([mi], parent=self.gui) + d.llm.activate_action(read_next_action()) + d.exec() + def show_similar_books(self, typ, *args): idx = self.gui.library_view.currentIndex() if not idx.isValid(): diff --git a/src/calibre/gui2/dialogs/llm_book.py b/src/calibre/gui2/dialogs/llm_book.py index 2cd5af6b1d..ba409c02ae 100644 --- a/src/calibre/gui2/dialogs/llm_book.py +++ b/src/calibre/gui2/dialogs/llm_book.py @@ -85,6 +85,13 @@ def default_actions() -> tuple[Action, ...]: ) +def read_next_action() -> Action: + for ac in default_actions(): + if ac.name == 'read_next': + return ac + raise KeyError('No read next action could be found') + + def current_actions(include_disabled=False) -> Iterator[Action]: p = gprefs.get('llm_book_quick_actions') or {} return Action.unserialize(p, default_actions(), include_disabled)