diff --git a/src/calibre/gui2/viewer2/web_view.py b/src/calibre/gui2/viewer2/web_view.py index 9c114ed10a..070c1fd6f1 100644 --- a/src/calibre/gui2/viewer2/web_view.py +++ b/src/calibre/gui2/viewer2/web_view.py @@ -22,12 +22,17 @@ from calibre.gui2.webengine import ( Bridge, RestartingWebEngineView, create_script, from_js, insert_scripts, secure_webengine, to_js ) +from calibre.utils.config import JSONConfig try: from PyQt5 import sip except ImportError: import sip +vprefs = JSONConfig('viewer-webengine') +vprefs.defaults['session_data'] = {} + + # Override network access to load data from the book {{{ @@ -123,7 +128,7 @@ def create_profile(): class ViewerBridge(Bridge): - live_css_data = from_js(object) + set_session_data = from_js(object, object) start_book_load = to_js() @@ -166,7 +171,8 @@ class WebView(RestartingWebEngineView): self._size_hint = QSize(int(w/3), int(w/2)) self._page = WebPage(self) self.bridge.bridge_ready.connect(self.on_bridge_ready) - self.pending_bridge_ready_actions = set() + self.bridge.set_session_data.connect(self.set_session_data) + self.pending_bridge_ready_actions = {} self.setPage(self._page) self.setAcceptDrops(False) self.clear() @@ -193,11 +199,20 @@ class WebView(RestartingWebEngineView): return self._page.bridge def on_bridge_ready(self): - for func, args in self.pending_bridge_ready_actions: + for func, args in self.pending_bridge_ready_actions.iteritems(): getattr(self.bridge, func)(*args) def start_book_load(self): + key = (set_book_path.path,) if self.bridge.ready: - self.bridge.start_book_load() + self.bridge.start_book_load(key, vprefs['session_data']) else: - self.pending_bridge_ready_actions.add(('start_book_load', ())) + self.pending_bridge_ready_actions['start_book_load'] = key, vprefs['session_data'] + + def set_session_data(self, key, val): + if key == '*' and val is None: + vprefs['session_data'] = {} + else: + sd = vprefs['session_data'] + sd[key] = val + vprefs['session_data'] = sd diff --git a/src/pyj/read_book/db.pyj b/src/pyj/read_book/db.pyj index b7f691c965..342687ff9a 100644 --- a/src/pyj/read_book/db.pyj +++ b/src/pyj/read_book/db.pyj @@ -44,6 +44,24 @@ def get_error_details(event): desc = desc.name return desc or 'Unknown Error' + +def new_book(key, metadata): + return { + 'key':key, + 'is_complete':False, + 'stored_files': {}, + 'book_hash':None, + 'metadata': metadata, + 'manifest': None, + 'cover_width': None, + 'cover_height': None, + 'cover_name': None, + 'recent_date': new Date(), + 'last_read': {}, + 'last_read_position': {}, + } + + DB_NAME = 'calibre' DB_VERSION = 1 @@ -170,20 +188,7 @@ class DB: book_id = int(book_id) key = v'[library_id, book_id, fmt]' self.do_op(['books'], key, _('Failed to read from the books database'), def(result): - proceed(result or { - 'key':key, - 'is_complete':False, - 'stored_files': {}, - 'book_hash':None, - 'metadata': metadata, - 'manifest': None, - 'cover_width': None, - 'cover_height': None, - 'cover_name': None, - 'recent_date': new Date(), - 'last_read': {}, - 'last_read_position': {}, - }) + proceed(result or new_book(key, metadata)) ) def get_mathjax_info(self, proceed): diff --git a/src/pyj/session.pyj b/src/pyj/session.pyj index a7f33b4a43..fbaf0c79ed 100644 --- a/src/pyj/session.pyj +++ b/src/pyj/session.pyj @@ -58,6 +58,10 @@ is_local_setting = { } +def session_defaults(): + return defaults + + def storage_available(which): which = which or 'localStorage' try: diff --git a/src/pyj/viewer-main.pyj b/src/pyj/viewer-main.pyj index 0a28c0fce3..ffe5195d80 100644 --- a/src/pyj/viewer-main.pyj +++ b/src/pyj/viewer-main.pyj @@ -6,17 +6,23 @@ import traceback from elementmaker import E from gettext import gettext as _ +import initialize # noqa: unused-import from ajax import ajax +from book_list.globals import set_session_data from modals import error_dialog -from qt import from_python +from qt import from_python, to_python +from read_book.db import new_book from read_book.globals import runtime, ui_operations +from read_book.view import View +from session import session_defaults def container_div(id): return E.div(id=id, style='margin: 0; padding: 0; display: none') runtime.is_standalone_viewer = True -book_manifest = None +book = None +view = None def get_file(book, name, proceed): @@ -32,22 +38,64 @@ def update_url_state(replace): def show_error(title, msg, details): - pass # TODO: Implement this + error_dialog(title, msg, details) -def manifest_received(end_type, xhr, ev): - nonlocal book_manifest +def manifest_received(key, end_type, xhr, ev): + nonlocal book if end_type is 'load': - book_manifest = xhr.response + book = new_book(key, {}) + book.manifest = xhr.response + book.metadata = book.manifest.metadata + book.stored_files = {} + book.is_complete = True + v'delete book.manifest["metadata"]' + v'delete book.manifest["last_read_positions"]' else: error_dialog(_('Could not open book'), _( 'Failed to load book manifest, click "Show details" for more info'), xhr.error_html or None) +class SessionData: + + def __init__(self, prefs): + defaults = session_defaults() + self.data = {k: defaults[k] if prefs[k] is undefined else prefs[k] for k in defaults} + + def get(self, key, defval): + ans = self.data[key] + if ans is undefined or ans is None: + if defval is undefined: + defval = None + return defval + return ans + + def set(self, key, val): + if val is None: + self.data[key] = session_defaults()[key] + else: + self.data[key] = val + to_python.set_session_data(key, val) + + def clear(self): + defaults = session_defaults() + self.data = {k: defaults[k] for k in defaults} + to_python.set_session_data('*', None) + + +def create_session_data(prefs): + sd = SessionData(prefs) + set_session_data(sd) + + @from_python -def start_book_load(): - ajax('book/calibre-book-manifest.json', manifest_received, ok_code=0).send() +def start_book_load(key, prefs): + nonlocal view + if view is None: + create_session_data(prefs) + view = View(document.getElementById('view')) + ajax('book/calibre-book-manifest.json', manifest_received.bind(None, key), ok_code=0).send() def onerror(msg, script_url, line_number, column_number, error_object): @@ -76,7 +124,6 @@ if window is window.top: ui_operations.get_mathjax_files = get_mathjax_files ui_operations.update_url_state = update_url_state ui_operations.show_error = show_error - document.body.appendChild(E.div(id='loading')) document.body.appendChild(E.div(id='view')) window.onerror = onerror else: