From f6235a1845313b79cb31cefcc5d54a7145e86be3 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 22 Feb 2021 09:53:46 +0530 Subject: [PATCH] E-book viewer: Have the Table of Contents view automatically scroll to keep the chapter being read currently visible. Fixes #1916411 [Enhancement Request: ToC Behavior - Default to Current Chapter](https://bugs.launchpad.net/calibre/+bug/1916411) --- src/calibre/gui2/viewer/toc.py | 24 ++++++++++++++++++++---- src/calibre/gui2/viewer/ui.py | 5 ++++- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/calibre/gui2/viewer/toc.py b/src/calibre/gui2/viewer/toc.py index 9289d6362b..ad6f26755e 100644 --- a/src/calibre/gui2/viewer/toc.py +++ b/src/calibre/gui2/viewer/toc.py @@ -52,7 +52,13 @@ class TOCView(QTreeView): def setModel(self, model): QTreeView.setModel(self, model) - model.auto_expand_nodes.connect(self.auto_expand_indices, type=Qt.ConnectionType.QueuedConnection) + model.current_toc_nodes_changed.connect(self.current_toc_nodes_changed, type=Qt.ConnectionType.QueuedConnection) + + def current_toc_nodes_changed(self, ancestors, nodes): + if ancestors: + self.auto_expand_indices(ancestors) + if nodes: + self.scrollTo(nodes[-1].index()) def auto_expand_indices(self, indices): for idx in indices: @@ -116,6 +122,11 @@ class TOCView(QTreeView): def update_current_toc_nodes(self, families): self.model().update_current_toc_nodes(families) + def scroll_to_current_toc_node(self): + nodes = self.model().viewed_nodes() + if nodes: + self.scrollTo(nodes[-1].index()) + class TOCSearch(QWidget): @@ -202,7 +213,7 @@ class TOCItem(QStandardItem): class TOC(QStandardItemModel): - auto_expand_nodes = pyqtSignal(object) + current_toc_nodes_changed = pyqtSignal(object, object) def __init__(self, toc=None): QStandardItemModel.__init__(self) @@ -259,12 +270,17 @@ class TOC(QStandardItemModel): viewed_nodes |= {x.node_id for x in ansc} for x in ansc: ancestors[x.node_id] = x.index() - if ancestors: - self.auto_expand_nodes.emit(tuple(ancestors.values())) + nodes = [] for node in self.all_items: is_being_viewed = node.node_id in viewed_nodes + if is_being_viewed: + nodes.append(node) if is_being_viewed != node.is_being_viewed: node.set_being_viewed(is_being_viewed) + self.current_toc_nodes_changed.emit(tuple(ancestors.values()), nodes) + + def viewed_nodes(self): + return tuple(node for node in self.all_items if node.is_being_viewed) @property def as_plain_text(self): diff --git a/src/calibre/gui2/viewer/ui.py b/src/calibre/gui2/viewer/ui.py index af302b7719..d09974a49d 100644 --- a/src/calibre/gui2/viewer/ui.py +++ b/src/calibre/gui2/viewer/ui.py @@ -297,7 +297,10 @@ class EbookViewer(MainWindow): self.inspector_dock.setVisible(not visible) def toggle_toc(self): - self.toc_dock.setVisible(not self.toc_dock.isVisible()) + is_visible = self.toc_dock.isVisible() + self.toc_dock.setVisible(not is_visible) + if not is_visible: + self.toc.scroll_to_current_toc_node() def show_search(self, text, trigger=False): self.search_dock.setVisible(True)