diff --git a/src/calibre/gui2/viewer/__init__.py b/src/calibre/gui2/viewer/__init__.py index 3d60292729..2872bb84b8 100644 --- a/src/calibre/gui2/viewer/__init__.py +++ b/src/calibre/gui2/viewer/__init__.py @@ -14,6 +14,12 @@ def get_current_book_data(set_val=False): return getattr(get_current_book_data, 'ans', {}) +def get_boss(set_val=False): + if set_val: + get_boss.ans = set_val + return get_boss.ans + + def link_prefix_for_location_links(add_open_at=True): cbd = get_current_book_data() link_prefix = library_id = None diff --git a/src/calibre/gui2/viewer/highlights.py b/src/calibre/gui2/viewer/highlights.py index e654d711c1..89db12c75f 100644 --- a/src/calibre/gui2/viewer/highlights.py +++ b/src/calibre/gui2/viewer/highlights.py @@ -23,7 +23,7 @@ from calibre.gui2.gestures import GestureManager from calibre.gui2.library.annotations import ( ChapterGroup, Details, Export as ExportBase, render_notes, ) -from calibre.gui2.viewer import link_prefix_for_location_links +from calibre.gui2.viewer import get_boss, link_prefix_for_location_links from calibre.gui2.viewer.config import vprefs from calibre.gui2.viewer.search import SearchInput from calibre.gui2.viewer.shortcuts import get_shortcut_for, index_to_key_sequence @@ -453,7 +453,6 @@ class NotesDisplay(Details): class HighlightsPanel(QWidget): - jump_to_cfi = pyqtSignal(object) request_highlight_action = pyqtSignal(object, object) web_action = pyqtSignal(object, object) toggle_requested = pyqtSignal() @@ -531,6 +530,9 @@ class HighlightsPanel(QWidget): self.highlights.setFocus(Qt.FocusReason.OtherFocusReason) def jump_to_highlight(self, highlight): + boss = get_boss() + if boss.check_for_read_aloud(_('highlight location')): + return self.request_highlight_action.emit(highlight['uuid'], 'goto') def current_highlight_changed(self, highlight): @@ -545,6 +547,9 @@ class HighlightsPanel(QWidget): 'No highlight is currently selected'), show=True) def edit_highlight(self): + boss = get_boss() + if boss.check_for_read_aloud(_('highlight location')): + return h = self.highlights.current_highlight if h is None: return self.no_selected_highlight() diff --git a/src/calibre/gui2/viewer/search.py b/src/calibre/gui2/viewer/search.py index 694a169133..0980db5c4d 100644 --- a/src/calibre/gui2/viewer/search.py +++ b/src/calibre/gui2/viewer/search.py @@ -15,6 +15,7 @@ from calibre.ebooks.conversion.search_replace import REGEX_FLAGS from calibre.gui2 import warning_dialog from calibre.gui2.gestures import GestureManager from calibre.gui2.progress_indicator import ProgressIndicator +from calibre.gui2.viewer import get_boss from calibre.gui2.viewer.config import vprefs from calibre.gui2.viewer.web_view import get_data, get_manifest from calibre.gui2.viewer.widgets import ResultsDelegate, SearchBox @@ -505,6 +506,9 @@ class SearchInput(QWidget): # {{{ ) def emit_search(self, backwards=False): + boss = get_boss() + if boss.check_for_read_aloud(_('search result location')): + return vprefs[f'viewer-{self.panel_name}-case-sensitive'] = self.case_sensitive.isChecked() vprefs[f'viewer-{self.panel_name}-mode'] = self.query_type.currentData() sq = self.search_query(backwards) @@ -632,6 +636,9 @@ class Results(QTreeWidget): # {{{ self.count_changed.emit(n) def item_activated(self): + boss = get_boss() + if boss.check_for_read_aloud(_('search result location')): + return i = self.currentItem() if i: sr = i.data(0, SEARCH_RESULT_ROLE) diff --git a/src/calibre/gui2/viewer/ui.py b/src/calibre/gui2/viewer/ui.py index 3e9c76f35a..312d21bdcf 100644 --- a/src/calibre/gui2/viewer/ui.py +++ b/src/calibre/gui2/viewer/ui.py @@ -25,7 +25,7 @@ from calibre.gui2 import ( from calibre.gui2.dialogs.drm_error import DRMErrorMessage from calibre.gui2.image_popup import ImagePopup from calibre.gui2.main_window import MainWindow -from calibre.gui2.viewer import get_current_book_data, performance_monitor +from calibre.gui2.viewer import get_boss, get_current_book_data, performance_monitor from calibre.gui2.viewer.annotations import ( AnnotationsSaveWorker, annotations_dir, parse_annotations, ) @@ -90,6 +90,7 @@ class EbookViewer(MainWindow): def __init__(self, open_at=None, continue_reading=None, force_reload=False, calibre_book_data=None): MainWindow.__init__(self, None) + get_boss(self) self.annotations_saver = None self.calibre_book_data_for_first_book = calibre_book_data self.shutting_down = self.close_forced = self.shutdown_done = False @@ -171,7 +172,7 @@ class EbookViewer(MainWindow): self.web_view.toggle_toc.connect(self.toggle_toc) self.web_view.show_search.connect(self.show_search) self.web_view.find_next.connect(self.search_widget.find_next_requested) - self.search_widget.show_search_result.connect(self.web_view.show_search_result) + self.search_widget.show_search_result.connect(self.show_search_result) self.web_view.search_result_not_found.connect(self.search_widget.search_result_not_found) self.web_view.search_result_discovered.connect(self.search_widget.search_result_discovered) self.web_view.toggle_bookmarks.connect(self.toggle_bookmarks) @@ -314,6 +315,9 @@ class EbookViewer(MainWindow): if not is_visible: self.toc.scroll_to_current_toc_node() + def show_search_result(self, sr): + self.web_view.show_search_result(sr) + def show_search(self, text, trigger=False, search_type=None, case_sensitive=None): self.search_dock.setVisible(True) self.search_dock.activateWindow() @@ -364,7 +368,16 @@ class EbookViewer(MainWindow): if force_show and self.lookup_dock.isVisible(): self.lookup_widget.on_forced_show() + def check_for_read_aloud(self, where: str): + if self.actions_toolbar.toggle_read_aloud_action.isChecked(): + error_dialog(self, _('Cannot jump to location'), _( + 'The Read aloud feature is active, cannot jump to {}. Close it first.').format(where), show=True) + return True + return False + def toc_clicked(self, index): + if self.check_for_read_aloud(_('Table of Contents locations')): + return item = self.toc_model.itemFromIndex(index) self.web_view.goto_toc_node(item.node_id) self.force_focus_on_web_view() @@ -386,6 +399,8 @@ class EbookViewer(MainWindow): self.web_view.goto_cfi(cfi, add_to_history=add_to_history) def bookmark_activated(self, cfi): + if self.check_for_read_aloud(_('bookmark')): + return self.goto_cfi(cfi, add_to_history=True) def view_image(self, name): diff --git a/src/pyj/read_book/read_aloud.pyj b/src/pyj/read_book/read_aloud.pyj index 3c60a77734..e458106cea 100644 --- a/src/pyj/read_book/read_aloud.pyj +++ b/src/pyj/read_book/read_aloud.pyj @@ -29,6 +29,7 @@ def is_flow_mode(): class ReadAloud: dont_hide_on_content_loaded = True + prevent_navigation = True def __init__(self, view): self.view = view diff --git a/src/pyj/read_book/read_audio_ebook.pyj b/src/pyj/read_book/read_audio_ebook.pyj index 07da8d9854..f8617bb53d 100644 --- a/src/pyj/read_book/read_audio_ebook.pyj +++ b/src/pyj/read_book/read_audio_ebook.pyj @@ -37,6 +37,7 @@ def seconds_to_ms(seconds): class ReadAudioEbook: dont_hide_on_content_loaded = True + prevent_navigation = True CONTAINER_DISPLAY = 'flex' def __init__(self, view): diff --git a/src/pyj/read_book/view.pyj b/src/pyj/read_book/view.pyj index cffa9be047..81b245eca2 100644 --- a/src/pyj/read_book/view.pyj +++ b/src/pyj/read_book/view.pyj @@ -673,6 +673,13 @@ class View: self.content_popup_overlay.hide() self.focus_iframe() + @property + def overlay_prevents_navigation(self): + for x in self.modal_overlays: + if x.is_visible and x.prevent_navigation: + return True + return False + def focus_iframe(self): for x in self.modal_overlays: if x.is_visible: @@ -1159,6 +1166,8 @@ class View: return True def goto_toc_node(self, node_id): + if self.overlay_prevents_navigation: + return toc = self.book.manifest.toc found = False