Implement basic settings storage for new viewer

This commit is contained in:
Kovid Goyal 2018-09-24 10:34:32 +05:30
parent b862af3844
commit 783ff58129
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
4 changed files with 99 additions and 28 deletions

View File

@ -22,12 +22,17 @@ from calibre.gui2.webengine import (
Bridge, RestartingWebEngineView, create_script, from_js, insert_scripts, Bridge, RestartingWebEngineView, create_script, from_js, insert_scripts,
secure_webengine, to_js secure_webengine, to_js
) )
from calibre.utils.config import JSONConfig
try: try:
from PyQt5 import sip from PyQt5 import sip
except ImportError: except ImportError:
import sip import sip
vprefs = JSONConfig('viewer-webengine')
vprefs.defaults['session_data'] = {}
# Override network access to load data from the book {{{ # Override network access to load data from the book {{{
@ -123,7 +128,7 @@ def create_profile():
class ViewerBridge(Bridge): class ViewerBridge(Bridge):
live_css_data = from_js(object) set_session_data = from_js(object, object)
start_book_load = to_js() start_book_load = to_js()
@ -166,7 +171,8 @@ class WebView(RestartingWebEngineView):
self._size_hint = QSize(int(w/3), int(w/2)) self._size_hint = QSize(int(w/3), int(w/2))
self._page = WebPage(self) self._page = WebPage(self)
self.bridge.bridge_ready.connect(self.on_bridge_ready) 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.setPage(self._page)
self.setAcceptDrops(False) self.setAcceptDrops(False)
self.clear() self.clear()
@ -193,11 +199,20 @@ class WebView(RestartingWebEngineView):
return self._page.bridge return self._page.bridge
def on_bridge_ready(self): 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) getattr(self.bridge, func)(*args)
def start_book_load(self): def start_book_load(self):
key = (set_book_path.path,)
if self.bridge.ready: if self.bridge.ready:
self.bridge.start_book_load() self.bridge.start_book_load(key, vprefs['session_data'])
else: 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

View File

@ -44,6 +44,24 @@ def get_error_details(event):
desc = desc.name desc = desc.name
return desc or 'Unknown Error' 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_NAME = 'calibre'
DB_VERSION = 1 DB_VERSION = 1
@ -170,20 +188,7 @@ class DB:
book_id = int(book_id) book_id = int(book_id)
key = v'[library_id, book_id, fmt]' key = v'[library_id, book_id, fmt]'
self.do_op(['books'], key, _('Failed to read from the books database'), def(result): self.do_op(['books'], key, _('Failed to read from the books database'), def(result):
proceed(result or { proceed(result or new_book(key, metadata))
'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': {},
})
) )
def get_mathjax_info(self, proceed): def get_mathjax_info(self, proceed):

View File

@ -58,6 +58,10 @@ is_local_setting = {
} }
def session_defaults():
return defaults
def storage_available(which): def storage_available(which):
which = which or 'localStorage' which = which or 'localStorage'
try: try:

View File

@ -6,17 +6,23 @@ import traceback
from elementmaker import E from elementmaker import E
from gettext import gettext as _ from gettext import gettext as _
import initialize # noqa: unused-import
from ajax import ajax from ajax import ajax
from book_list.globals import set_session_data
from modals import error_dialog 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.globals import runtime, ui_operations
from read_book.view import View
from session import session_defaults
def container_div(id): def container_div(id):
return E.div(id=id, style='margin: 0; padding: 0; display: none') return E.div(id=id, style='margin: 0; padding: 0; display: none')
runtime.is_standalone_viewer = True runtime.is_standalone_viewer = True
book_manifest = None book = None
view = None
def get_file(book, name, proceed): def get_file(book, name, proceed):
@ -32,22 +38,64 @@ def update_url_state(replace):
def show_error(title, msg, details): def show_error(title, msg, details):
pass # TODO: Implement this error_dialog(title, msg, details)
def manifest_received(end_type, xhr, ev): def manifest_received(key, end_type, xhr, ev):
nonlocal book_manifest nonlocal book
if end_type is 'load': 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: else:
error_dialog(_('Could not open book'), _( error_dialog(_('Could not open book'), _(
'Failed to load book manifest, click "Show details" for more info'), 'Failed to load book manifest, click "Show details" for more info'),
xhr.error_html or None) 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 @from_python
def start_book_load(): def start_book_load(key, prefs):
ajax('book/calibre-book-manifest.json', manifest_received, ok_code=0).send() 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): 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.get_mathjax_files = get_mathjax_files
ui_operations.update_url_state = update_url_state ui_operations.update_url_state = update_url_state
ui_operations.show_error = show_error ui_operations.show_error = show_error
document.body.appendChild(E.div(id='loading'))
document.body.appendChild(E.div(id='view')) document.body.appendChild(E.div(id='view'))
window.onerror = onerror window.onerror = onerror
else: else: