self.render_process_failed.emit() prints('The Qt WebEngine Render process crashed too often') else: self._last_reload_at = monotonic() self.render_process_restarted.emit() prints('Restarting Qt WebEngine') if __name__ == '__main__': from calibre.gui2 import Application from calibre.gui2.tweak_book.preview import WebPage from qt.core import QMainWindow app = Application([]) view = QWebEngineView() page = WebPage(view) view.setPage(page) w = QMainWindow() w.setCentralWidget(view) class Test(Bridge): s1 = from_js(object) j1 = to_js() t = Test(view.page()) t.s1.connect(print) w.show() view.setHtml(''' <p>hello</p> ''') app.exec() del t del page
class Lookup(QWidget): def __init__(self, parent): QWidget.__init__(self, parent) self.is_visible = False self.selected_text = '' self.current_query = '' self.current_source = '' self.l = l = QVBoxLayout(self) self.h = h = QHBoxLayout() l.addLayout(h) self.debounce_timer = t = QTimer(self) t.setInterval(150), t.timeout.connect(self.update_query) self.source_box = sb = QComboBox(self) self.label = la = QLabel(_('Lookup &in:')) h.addWidget(la), h.addWidget(sb), la.setBuddy(sb) self.view = View(self) self.view.inspect_element.connect(self.show_devtools) self._page = Page(create_profile(), self.view) apply_font_settings(self._page) secure_webengine(self._page, for_viewer=True) self.view.setPage(self._page) l.addWidget(self.view) self.populate_sources() self.source_box.currentIndexChanged.connect(self.source_changed) self.view.setHtml('<p>' + _('Double click on a word in the book\'s text' ' to look it up.')) self.add_button = b = QPushButton(QIcon(I('plus.png')), _('Add sources')) b.setToolTip(_('Add more sources at which to lookup words')) b.clicked.connect(self.add_sources) self.refresh_button = rb = QPushButton(QIcon(I('view-refresh.png')), _('Refresh')) rb.setToolTip( _('Refresh the result to match the currently selected text')) rb.clicked.connect(self.update_query) h = QHBoxLayout() l.addLayout(h) h.addWidget(b), h.addWidget(rb) self.auto_update_query = a = QCheckBox(_('Update on selection change'), self) a.setToolTip( textwrap.fill( _('Automatically update the displayed result when selected text in the book changes. With this disabled' ' the lookup is changed only when clicking the Refresh button.' ))) a.setChecked(vprefs['auto_update_lookup']) a.stateChanged.connect(self.auto_update_state_changed) l.addWidget(a) self.update_refresh_button_status() def auto_update_state_changed(self, state): vprefs['auto_update_lookup'] = self.auto_update_query.isChecked() self.update_refresh_button_status() def show_devtools(self): if not hasattr(self, '_devtools_page'): self._devtools_page = QWebEnginePage() self._devtools_view = QWebEngineView(self) self._devtools_view.setPage(self._devtools_page) self._page.setDevToolsPage(self._devtools_page) self._devtools_dialog = d = QDialog(self) d.setWindowTitle('Inspect Lookup page') v = QVBoxLayout(d) v.addWidget(self._devtools_view) d.bb = QDialogButtonBox(QDialogButtonBox.StandardButton.Close) d.bb.rejected.connect(d.reject) v.addWidget(d.bb) d.resize(QSize(800, 600)) d.setAttribute(Qt.WidgetAttribute.WA_DeleteOnClose, False) self._devtools_dialog.show() self._page.triggerAction(QWebEnginePage.WebAction.InspectElement) def add_sources(self): if SourcesEditor(self).exec() == QDialog.DialogCode.Accepted: self.populate_sources() self.source_box.setCurrentIndex(0) self.update_query() def source_changed(self): s = self.source if s is not None: vprefs['lookup_location'] = s['name'] self.update_query() def populate_sources(self): sb = self.source_box sb.clear() sb.blockSignals(True) for item in vprefs['lookup_locations']: sb.addItem(item['name'], item) idx = sb.findText(vprefs['lookup_location'], Qt.MatchFlag.MatchExactly) if idx > -1: sb.setCurrentIndex(idx) sb.blockSignals(False) def visibility_changed(self, is_visible): self.is_visible = is_visible self.update_query() @property def source(self): idx = self.source_box.currentIndex() if idx > -1: return self.source_box.itemData(idx) @property def url_template(self): idx = self.source_box.currentIndex() if idx > -1: return self.source_box.itemData(idx)['url'] @property def query_is_up_to_date(self): query = self.selected_text or self.current_query return self.current_query == query and self.current_source == self.url_template def update_refresh_button_status(self): b = self.refresh_button b.setVisible(not self.auto_update_query.isChecked()) b.setEnabled(not self.query_is_up_to_date) def update_query(self): self.debounce_timer.stop() query = self.selected_text or self.current_query if self.query_is_up_to_date: return if not self.is_visible or not query: return self.current_source = self.url_template url = self.current_source.format(word=query) self.view.load(QUrl(url)) self.current_query = query self.update_refresh_button_status() def selected_text_changed(self, text, annot_id): already_has_text = bool(self.current_query) self.selected_text = text or '' if self.auto_update_query.isChecked() or not already_has_text: self.debounce_timer.start() self.update_refresh_button_status() def on_forced_show(self): self.update_query()