diff --git a/src/calibre/gui2/viewer/toc.py b/src/calibre/gui2/viewer/toc.py index 031ff2745f..e786f0b9c7 100644 --- a/src/calibre/gui2/viewer/toc.py +++ b/src/calibre/gui2/viewer/toc.py @@ -101,6 +101,9 @@ class TOCView(QTreeView): m = self.model() QApplication.clipboard().setText(getattr(m, 'as_plain_text', '')) + def update_current_toc_nodes(self, current_node_id, toplevel_node_id): + self.model().update_current_toc_nodes(current_node_id, toplevel_node_id) + class TOCSearch(QWidget): @@ -134,7 +137,7 @@ class TOCSearch(QWidget): class TOCItem(QStandardItem): - def __init__(self, toc, depth, all_items, parent=None): + def __init__(self, toc, depth, all_items, normal_font, emphasis_font, parent=None): text = toc.get('title') or '' if text: text = re.sub(r'\s', ' ', text) @@ -143,16 +146,18 @@ class TOCItem(QStandardItem): self.node_id = toc['id'] QStandardItem.__init__(self, text) all_items.append(self) - self.emphasis_font = QFont(self.font()) - self.emphasis_font.setBold(True), self.emphasis_font.setItalic(True) - self.normal_font = self.font() + self.normal_font, self.emphasis_font = normal_font, emphasis_font for t in toc['children']: - self.appendRow(TOCItem(t, depth+1, all_items, parent=self)) + self.appendRow(TOCItem(t, depth+1, all_items, normal_font, emphasis_font, parent=self)) self.setFlags(Qt.ItemIsEnabled) self.is_current_search_result = False self.depth = depth self.is_being_viewed = False + def set_being_viewed(self, is_being_viewed): + self.is_being_viewed = is_being_viewed + self.setFont(self.emphasis_font if is_being_viewed else self.normal_font) + @property def ancestors(self): parent = self.parent @@ -186,9 +191,13 @@ class TOC(QStandardItemModel): QStandardItemModel.__init__(self) self.current_query = {'text':'', 'index':-1, 'items':()} self.all_items = depth_first = [] + normal_font = QApplication.instance().font() + emphasis_font = QFont(normal_font) + emphasis_font.setBold(True), emphasis_font.setItalic(True) if toc: for t in toc['children']: - self.appendRow(TOCItem(t, 0, depth_first)) + self.appendRow(TOCItem(t, 0, depth_first, normal_font, emphasis_font)) + self.node_id_map = {x.node_id: x for x in self.all_items} self.currently_viewed_entry = None def find_items(self, query): @@ -211,6 +220,17 @@ class TOC(QStandardItemModel): return index return QModelIndex() + def update_current_toc_nodes(self, current_node_id, top_level_node_id): + node = self.node_id_map.get(current_node_id) + viewed_nodes = set() + if node is not None: + viewed_nodes |= {x.node_id for x in node.ancestors} + viewed_nodes.add(node.node_id) + for node in self.all_items: + is_being_viewed = node.node_id in viewed_nodes + if is_being_viewed != node.is_being_viewed: + node.set_being_viewed(is_being_viewed) + @property def as_plain_text(self): lines = [] diff --git a/src/calibre/gui2/viewer/ui.py b/src/calibre/gui2/viewer/ui.py index d7a61cfa08..e59d2c3c1c 100644 --- a/src/calibre/gui2/viewer/ui.py +++ b/src/calibre/gui2/viewer/ui.py @@ -72,6 +72,7 @@ class EbookViewer(MainWindow): self.web_view.cfi_changed.connect(self.cfi_changed) self.web_view.reload_book.connect(self.reload_book) self.web_view.toggle_toc.connect(self.toggle_toc) + self.web_view.update_current_toc_nodes.connect(self.toc.update_current_toc_nodes) self.setCentralWidget(self.web_view) state = vprefs['main_window_state'] if state: diff --git a/src/calibre/gui2/viewer/web_view.py b/src/calibre/gui2/viewer/web_view.py index 54d8135f8d..3608af430b 100644 --- a/src/calibre/gui2/viewer/web_view.py +++ b/src/calibre/gui2/viewer/web_view.py @@ -170,6 +170,7 @@ class ViewerBridge(Bridge): set_session_data = from_js(object, object) reload_book = from_js() toggle_toc = from_js() + update_current_toc_nodes = from_js(object, object) create_view = to_js() show_preparing_message = to_js() @@ -250,6 +251,7 @@ class WebView(RestartingWebEngineView): cfi_changed = pyqtSignal(object) reload_book = pyqtSignal() toggle_toc = pyqtSignal() + update_current_toc_nodes = pyqtSignal(object, object) def __init__(self, parent=None): self._host_widget = None @@ -264,6 +266,7 @@ class WebView(RestartingWebEngineView): self.bridge.set_session_data.connect(self.set_session_data) self.bridge.reload_book.connect(self.reload_book) self.bridge.toggle_toc.connect(self.toggle_toc) + self.bridge.update_current_toc_nodes.connect(self.update_current_toc_nodes) self.pending_bridge_ready_actions = {} self.setPage(self._page) self.setAcceptDrops(False) diff --git a/src/pyj/read_book/view.pyj b/src/pyj/read_book/view.pyj index a09140dcb4..2223b0afa1 100644 --- a/src/pyj/read_book/view.pyj +++ b/src/pyj/read_book/view.pyj @@ -582,10 +582,11 @@ class View: window.clearInterval(self.clock_timer_id) self.clock_timer_id = 0 - def on_update_toc_position(self, data): update_visible_toc_nodes(data.visible_anchors) self.current_toc_node, self.current_toc_toplevel_node = get_current_toc_nodes() + if runtime.is_standalone_viewer: + ui_operations.update_current_toc_nodes(self.current_toc_node?.id, self.current_toc_toplevel_node?.id) self.update_header_footer() def show_spine_item(self, resource_data): diff --git a/src/pyj/viewer-main.pyj b/src/pyj/viewer-main.pyj index 9f74142042..53eedf09b6 100644 --- a/src/pyj/viewer-main.pyj +++ b/src/pyj/viewer-main.pyj @@ -244,6 +244,8 @@ if window is window.top: ui_operations.update_font_size = update_font_size ui_operations.toggle_toc = def(): to_python.toggle_toc() + ui_operations.update_current_toc_nodes = def(current_node_id, top_level_node_id): + to_python.update_current_toc_nodes(current_node_id, top_level_node_id) document.body.appendChild(E.div(id='view')) window.onerror = onerror create_modal_container()