mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Viewer: Ensure last read position is fully accurate
This is particularly important when quitting while autoscroll is active as CFI is not updated during autoscroll.
This commit is contained in:
parent
9730226f6e
commit
2be73652a6
@ -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:
|
||||
|
@ -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')
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user