Do not use the pyqtProperty technique to pass data between JS and Qt as it fails with newer versions of QtWebKit

This commit is contained in:
Kovid Goyal 2017-05-04 11:39:24 +05:30
parent 56915f8bf5
commit 650ce8aebc
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
6 changed files with 23 additions and 60 deletions

Binary file not shown.

View File

@ -163,8 +163,8 @@ class CalibreExtract
cnode = inline_styles(node)
return cnode.outerHTML
is_footnote_link: (a, prefix) ->
return is_footnote_link(a, a.href, py_bridge.value, prefix)
is_footnote_link: (a, prefix, linked_to_anchors) ->
return is_footnote_link(a, a.href, linked_to_anchors, prefix)
show_footnote: (target, known_targets) ->
if not target

View File

@ -13,7 +13,7 @@ from math import floor
from collections import defaultdict
from PyQt5.Qt import (
QObject, QPainter, Qt, QSize, QTimer, pyqtProperty, QEventLoop, QPixmap, QRect, pyqtSlot)
QObject, QPainter, Qt, QSize, QTimer, QEventLoop, QPixmap, QRect, pyqtSlot)
from PyQt5.QtWebKit import QWebSettings
from PyQt5.QtWebKitWidgets import QWebView, QWebPage
@ -127,16 +127,6 @@ def draw_image_page(page_rect, painter, p, preserve_aspect_ratio=True):
class PDFWriter(QObject):
def _pass_json_value_getter(self):
val = json.dumps(self.bridge_value)
return val
def _pass_json_value_setter(self, value):
self.bridge_value = json.loads(unicode(value))
_pass_json_value = pyqtProperty(str, fget=_pass_json_value_getter,
fset=_pass_json_value_setter)
@pyqtSlot(result=unicode)
def title(self):
return self.doc_title
@ -361,33 +351,32 @@ class PDFWriter(QObject):
evaljs(self.paged_js)
self.load_mathjax()
evaljs('''
Object.defineProperty(py_bridge, 'value', {
get : function() { return JSON.parse(this._pass_json_value); },
set : function(val) { this._pass_json_value = JSON.stringify(val); }
});
amap = evaljs('''
document.body.style.backgroundColor = "white";
paged_display.set_geometry(1, %d, %d, %d);
paged_display.layout();
paged_display.fit_images();
py_bridge.value = book_indexing.all_links_and_anchors();
ret = book_indexing.all_links_and_anchors();
window.scrollTo(0, 0); // This is needed as getting anchor positions could have caused the viewport to scroll
ret;
'''%(self.margin_top, 0, self.margin_bottom))
amap = self.bridge_value
if not isinstance(amap, dict):
amap = {'links':[], 'anchors':{}} # Some javascript error occurred
for val in amap['anchors'].itervalues():
if isinstance(val, dict) and 'column' in val:
val['column'] = int(val['column'])
for href, val in amap['links']:
if isinstance(val, dict) and 'column' in val:
val['column'] = int(val['column'])
sections = self.get_sections(amap['anchors'])
tl_sections = self.get_sections(amap['anchors'], True)
col = 0
if self.header:
self.bridge_value = self.header
evaljs('paged_display.header_template = py_bridge.value')
evaljs('paged_display.header_template = ' + json.dumps(self.header))
if self.footer:
self.bridge_value = self.footer
evaljs('paged_display.footer_template = py_bridge.value')
evaljs('paged_display.footer_template = ' + json.dumps(self.footer))
if self.header or self.footer:
evaljs('paged_display.create_header_footer("%s");'%self.hf_uuid)

View File

@ -31,7 +31,6 @@ class Page(QWebPage): # {{{
secure_web_page(self.settings())
self.js = None
self.evaljs = self.mainFrame().evaluateJavaScript
self.bridge_value = None
nam = self.networkAccessManager()
nam.setNetworkAccessible(nam.NotAccessible)
self.setLinkDelegationPolicy(self.DelegateAllLinks)

View File

@ -10,7 +10,7 @@ from functools import partial
from future_builtins import map
from PyQt5.Qt import (
QSize, QSizePolicy, QUrl, Qt, pyqtProperty, QPainter, QPalette, QBrush,
QSize, QSizePolicy, QUrl, Qt, QPainter, QPalette, QBrush,
QDialog, QColor, QPoint, QImage, QRegion, QIcon, QAction, QMenu,
pyqtSignal, QApplication, pyqtSlot, QKeySequence, QMimeData)
from PyQt5.QtWebKitWidgets import QWebPage, QWebView
@ -89,10 +89,6 @@ class Document(QWebPage): # {{{
self.setNetworkAccessManager(self.nam)
self.setObjectName("py_bridge")
self.in_paged_mode = False
# Use this to pass arbitrary JSON encodable objects between python and
# javascript. In python get/set the value as: self.bridge_value. In
# javascript, get/set the value as: py_bridge.value
self.bridge_value = None
self.first_load = True
self.jump_to_cfi_listeners = set()
@ -197,12 +193,6 @@ class Document(QWebPage): # {{{
def add_window_objects(self):
self.mainFrame().addToJavaScriptWindowObject("py_bridge", self)
self.javascript('''
Object.defineProperty(py_bridge, 'value', {
get : function() { return JSON.parse(this._pass_json_value); },
set : function(val) { this._pass_json_value = JSON.stringify(val); }
});
''')
self.loaded_javascript = False
def load_javascript_libraries(self):
@ -238,16 +228,6 @@ class Document(QWebPage): # {{{
def page_turn_requested(self, backwards):
self.page_turn.emit(bool(backwards))
def _pass_json_value_getter(self):
val = json.dumps(self.bridge_value)
return val
def _pass_json_value_setter(self, value):
self.bridge_value = json.loads(unicode(value))
_pass_json_value = pyqtProperty(str, fget=_pass_json_value_getter,
fset=_pass_json_value_setter)
def after_load(self, last_loaded_path=None):
self.javascript('window.paged_display.read_document_margins()')
self.set_bottom_padding(0)
@ -267,19 +247,15 @@ class Document(QWebPage): # {{{
self.first_load = False
def colors(self):
self.javascript('''
ans = self.javascript('''
bs = getComputedStyle(document.body);
py_bridge.value = [bs.backgroundColor, bs.color]
[bs.backgroundColor, bs.color]
''')
ans = self.bridge_value
return (ans if isinstance(ans, list) else ['white', 'black'])
return ans if isinstance(ans, list) else ['white', 'black']
def read_anchor_positions(self, use_cache=True):
self.bridge_value = tuple(self.index_anchors)
self.javascript(u'''
py_bridge.value = book_indexing.anchor_positions(py_bridge.value, %s);
'''%('true' if use_cache else 'false'))
self.anchor_positions = self.bridge_value
self.anchor_positions = self.javascript('book_indexing.anchor_positions(%s, %s);' % (
json.dumps(tuple(self.index_anchors)), 'true' if use_cache else 'false'))
if not isinstance(self.anchor_positions, dict):
# Some weird javascript error happened
self.anchor_positions = {}
@ -323,8 +299,8 @@ class Document(QWebPage): # {{{
def column_boundaries(self):
if not self.loaded_javascript:
return (0, 1)
self.javascript(u'py_bridge.value = paged_display.column_boundaries()')
return tuple(self.bridge_value)
ans = self.javascript(u'paged_display.column_boundaries()')
return tuple(int(x) for x in ans)
def after_resize(self):
if self.in_paged_mode:

View File

@ -137,8 +137,7 @@ class Footnotes(object):
linked_to_anchors = {}
else:
linked_to_anchors = {anchor:0 for path, anchor in dest_path.verified_links if path == current_path}
self.view.document.bridge_value = linked_to_anchors
if a.evaluateJavaScript('calibre_extract.is_footnote_link(this, "%s://%s")' % (FAKE_PROTOCOL, FAKE_HOST)):
if a.evaluateJavaScript('calibre_extract.is_footnote_link(this, "%s://%s", %s)' % (FAKE_PROTOCOL, FAKE_HOST, json.dumps(linked_to_anchors))):
if dest_path not in self.known_footnote_targets:
self.known_footnote_targets[dest_path] = s = set()
for item in self.view.manager.iterator.spine: