From 650ce8aebc026a3fd162971d47867f0a0298668f Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 4 May 2017 11:39:24 +0530 Subject: [PATCH] Do not use the pyqtProperty technique to pass data between JS and Qt as it fails with newer versions of QtWebKit --- resources/compiled_coffeescript.zip | Bin 102004 -> 102025 bytes src/calibre/ebooks/oeb/display/extract.coffee | 4 +- src/calibre/ebooks/pdf/render/from_html.py | 35 ++++++--------- src/calibre/gui2/toc/location.py | 1 - src/calibre/gui2/viewer/documentview.py | 40 ++++-------------- src/calibre/gui2/viewer/footnote.py | 3 +- 6 files changed, 23 insertions(+), 60 deletions(-) diff --git a/resources/compiled_coffeescript.zip b/resources/compiled_coffeescript.zip index 6918ebe9f3ce2862fc6324e4f6da22516bb68627..e6f5ad224229d60b1875ba74611e887c6c781345 100644 GIT binary patch delta 288 zcmew|hplri+XlBpK7*JgUL{wiR-DjeU^t;U`Tc6i&AExZijxa-g(p`v=}s=rm71*B zsNVdnY5TJ##(Fkh6b;jhIvHaa?WdpbWb|V?JazhoPDatm_os4Cx9?)qVtTV0EHJ&H zi_wJX#6Aeeu8)yp`emRrbEz)l^oyO0BGW~>8I72>IZvP14dldhGa55WPoL1usL!ZA z{XjRP)O4U0)9HdejAGMQ^)fn7-`B$!3^J2z`jc)(=gHCCeAAnI7_Fzv_b_ry&Q0Xf zQL<7{GBPx@G%!mxNl7wENi#GtNwi3_G&V@KNHH-sO*Kq1H?}ZOHcmA%oG#GAm^%Gy RFQX&KT=wa)y^Q9JwE&NCXKMfe delta 336 zcmeC2%l2gs+XlBp!B4d_JT(sSZrZHLzyQLs(8W~Ui8-aI&8M5TpKfAY&&G>l!u0k|#uz58?&%YC8AT@-bn{K;=wj4j zS~nFeFnxC~Blq+WkjVAb5RnT#j9k;_gG4s(gNQunVl-k-&}E$7*u^L^U9+3fh;iZc zm~KW77B*i-hUxZwj55=YbTbNY2z4?ttY@lLn*4C8@N}R#z98fMz?N$FGFnfs?O_ZC zdqhXcNW_*wWI%z#`Sy+$1s4+}zka$;j9^%_1qq(!zLpUJua! r-o8L*MfWl4GV3TnEU@Zfbe{ZXD#vurK1N3{1L#nW>EF8 - 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 diff --git a/src/calibre/ebooks/pdf/render/from_html.py b/src/calibre/ebooks/pdf/render/from_html.py index beac4f8e26..01f74dffdc 100644 --- a/src/calibre/ebooks/pdf/render/from_html.py +++ b/src/calibre/ebooks/pdf/render/from_html.py @@ -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) diff --git a/src/calibre/gui2/toc/location.py b/src/calibre/gui2/toc/location.py index b850259b35..4602c87613 100644 --- a/src/calibre/gui2/toc/location.py +++ b/src/calibre/gui2/toc/location.py @@ -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) diff --git a/src/calibre/gui2/viewer/documentview.py b/src/calibre/gui2/viewer/documentview.py index cd9fd2b500..7f462cc149 100644 --- a/src/calibre/gui2/viewer/documentview.py +++ b/src/calibre/gui2/viewer/documentview.py @@ -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: diff --git a/src/calibre/gui2/viewer/footnote.py b/src/calibre/gui2/viewer/footnote.py index ab0fb71bef..9f57c2b9ea 100644 --- a/src/calibre/gui2/viewer/footnote.py +++ b/src/calibre/gui2/viewer/footnote.py @@ -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: