diff --git a/src/calibre/gui2/viewer/ui.py b/src/calibre/gui2/viewer/ui.py index 19549f30ee..e9879a736a 100644 --- a/src/calibre/gui2/viewer/ui.py +++ b/src/calibre/gui2/viewer/ui.py @@ -14,7 +14,7 @@ from threading import Thread from PyQt5.Qt import ( QApplication, QCursor, QDockWidget, QEvent, QMenu, QMimeData, QModelIndex, - QPixmap, Qt, QToolBar, QUrl, QVBoxLayout, QWidget, pyqtSignal + QPixmap, Qt, QTimer, QToolBar, QUrl, QVBoxLayout, QWidget, pyqtSignal ) from calibre import prints @@ -87,7 +87,7 @@ class EbookViewer(MainWindow): def __init__(self, open_at=None, continue_reading=None, force_reload=False): MainWindow.__init__(self, None) - self.shutting_down = False + self.shutting_down = self.close_forced = False self.force_reload = force_reload connect_lambda(self.book_preparation_started, self, lambda self: self.loading_overlay(_( 'Preparing book for first read, please wait')), type=Qt.QueuedConnection) @@ -172,6 +172,7 @@ class EbookViewer(MainWindow): self.web_view.quit.connect(self.quit, type=Qt.QueuedConnection) self.web_view.shortcuts_changed.connect(self.shortcuts_changed) self.web_view.scrollbar_context_menu.connect(self.scrollbar_context_menu) + self.web_view.close_prep_finished.connect(self.close_prep_finished) self.actions_toolbar.initialize(self.web_view, self.search_dock.toggleViewAction()) self.setCentralWidget(self.web_view) self.loading_overlay = LoadingOverlay(self) @@ -568,7 +569,24 @@ class EbookViewer(MainWindow): def quit(self): self.close() + def force_close(self): + if not self.close_forced: + self.close_forced = True + self.quit() + + def close_prep_finished(self, cfi): + if cfi: + self.cfi_changed(cfi) + self.force_close() + def closeEvent(self, ev): + if self.current_book_data and self.web_view.view_is_ready and not self.close_forced: + ev.ignore() + if not self.shutting_down: + self.shutting_down = True + QTimer.singleShot(2000, self.force_close) + self.web_view.prepare_for_close() + return self.shutting_down = True self.search_widget.shutdown() try: diff --git a/src/calibre/gui2/viewer/web_view.py b/src/calibre/gui2/viewer/web_view.py index 62ddc7b0c7..77f64dfeb1 100644 --- a/src/calibre/gui2/viewer/web_view.py +++ b/src/calibre/gui2/viewer/web_view.py @@ -273,6 +273,7 @@ class ViewerBridge(Bridge): quit = from_js() customize_toolbar = from_js() scrollbar_context_menu = from_js(object, object, object) + close_prep_finished = from_js(object) create_view = to_js() start_book_load = to_js() @@ -286,6 +287,7 @@ class ViewerBridge(Bridge): trigger_shortcut = to_js() set_system_palette = to_js() show_search_result = to_js() + prepare_for_close = to_js() def apply_font_settings(page_or_view): @@ -445,6 +447,7 @@ class WebView(RestartingWebEngineView): quit = pyqtSignal() customize_toolbar = pyqtSignal() scrollbar_context_menu = pyqtSignal(object, object, object) + close_prep_finished = pyqtSignal(object) shortcuts_changed = pyqtSignal(object) paged_mode_changed = pyqtSignal() standalone_misc_settings_changed = pyqtSignal(object) @@ -463,6 +466,7 @@ class WebView(RestartingWebEngineView): self.show_home_page_on_ready = True self._size_hint = QSize(int(w/3), int(w/2)) self._page = WebPage(self) + self.view_is_ready = False self.bridge.bridge_ready.connect(self.on_bridge_ready) self.bridge.view_created.connect(self.on_view_created) self.bridge.content_file_changed.connect(self.on_content_file_changed) @@ -494,6 +498,7 @@ class WebView(RestartingWebEngineView): self.bridge.quit.connect(self.quit) self.bridge.customize_toolbar.connect(self.customize_toolbar) self.bridge.scrollbar_context_menu.connect(self.scrollbar_context_menu) + self.bridge.close_prep_finished.connect(self.close_prep_finished) self.bridge.export_shortcut_map.connect(self.set_shortcut_map) self.shortcut_map = {} self.bridge.report_cfi.connect(self.call_callback) @@ -578,6 +583,7 @@ class WebView(RestartingWebEngineView): def on_view_created(self, data): self.view_created.emit(data) + self.view_is_ready = True def on_content_file_changed(self, data): self.current_content_file = data @@ -669,3 +675,6 @@ class WebView(RestartingWebEngineView): def palette_changed(self): self.execute_when_ready('set_system_palette', system_colors()) + + def prepare_for_close(self): + self.execute_when_ready('prepare_for_close') diff --git a/src/pyj/read_book/view.pyj b/src/pyj/read_book/view.pyj index 90573e4c1d..4dc7d98133 100644 --- a/src/pyj/read_book/view.pyj +++ b/src/pyj/read_book/view.pyj @@ -172,7 +172,7 @@ class View: self.current_progress_frac = self.current_file_progress_frac = 0 self.current_toc_node = self.current_toc_toplevel_node = None self.report_cfi_callbacks = {} - self.show_chrome_counter = 0 + self.get_cfi_counter = 0 self.show_loading_callback_timer = None self.timer_ids = {'clock': 0} self.book_scrollbar = BookScrollbar(self) @@ -521,12 +521,11 @@ class View: self.iframe.contentWindow.focus() def show_chrome(self, data): - self.show_chrome_counter += 1 elements = {} if data and data.elements: elements = data.elements initial_panel = data?.initial_panel or None - self.get_current_cfi('show-chrome-' + self.show_chrome_counter, self.do_show_chrome.bind(None, elements, initial_panel)) + self.get_current_cfi('show-chrome', self.do_show_chrome.bind(None, elements, initial_panel)) def do_show_chrome(self, elements, initial_panel, request_id, cfi_data): self.hide_overlays() @@ -536,6 +535,13 @@ class View: else: self.overlay.show(elements) + def prepare_for_close(self): + + def close_prepared(request_id, cfi_data): + ui_operations.close_prep_finished(cfi_data.cfi) + + self.get_current_cfi('prepare-close', close_prepared) + def show_search(self): self.hide_overlays() if runtime.is_standalone_viewer: @@ -903,6 +909,8 @@ class View: self.goto_named_destination(toc_node.dest, toc_node.frag) def get_current_cfi(self, request_id, callback): + self.get_cfi_counter += 1 + request_id += ':' + self.get_cfi_counter self.report_cfi_callbacks[request_id] = callback self.iframe_wrapper.send_message('get_current_cfi', request_id=request_id) @@ -923,7 +931,7 @@ class View: def on_report_cfi(self, data): cb = self.report_cfi_callbacks[data.request_id] if cb: - cb(data.request_id, { + cb(data.request_id.rpartition(':')[0], { 'cfi': data.cfi, 'progress_frac': data.progress_frac, 'file_progress_frac': data.file_progress_frac, diff --git a/src/pyj/viewer-main.pyj b/src/pyj/viewer-main.pyj index 6d4119f1b0..adab0bef94 100644 --- a/src/pyj/viewer-main.pyj +++ b/src/pyj/viewer-main.pyj @@ -293,6 +293,12 @@ def show_search_result(sr): if view: view.show_search_result(sr) +@from_python +def prepare_for_close(): + if view: + view.prepare_for_close() + else: + ui_operations.close_prep_finished(None) def onerror(msg, script_url, line_number, column_number, error_object): if not error_object: @@ -405,6 +411,8 @@ if window is window.top: to_python.search_result_not_found(sr) ui_operations.scrollbar_context_menu = def(x, y, frac): to_python.scrollbar_context_menu(x, y, frac) + ui_operations.close_prep_finished = def(cfi): + to_python.close_prep_finished(cfi) document.body.appendChild(E.div(id='view')) window.onerror = onerror