def __init__(self): super(HTMLWidget, self).__init__() self.settings().setAttribute( QWebSettings.LocalContentCanAccessRemoteUrls, True) self.settings().setAttribute(QWebSettings.DeveloperExtrasEnabled, True) self.setPage(WebPage()) self._obj = None self._styles = [_DEFAULT_STYLES] self._header = '' self._body = '' self.add_to_js('widget', self) self._event = EventEmitter() self.add_header('''<script> var emit = function (name, arg) { widget._emit_from_js(name, JSON.stringify(arg)); }; </script>''') self._pending_js_eval = []
def __init__(self): super(HTMLWidget, self).__init__() self.settings().setAttribute( QWebSettings.LocalContentCanAccessRemoteUrls, True) self.settings().setAttribute( QWebSettings.DeveloperExtrasEnabled, True) self.setPage(WebPage()) self._obj = None self._styles = [_DEFAULT_STYLES] self._header = '' self._body = '' self.add_to_js('widget', self) self._event = EventEmitter() self.add_header('''<script> var emit = function (name, arg) { widget._emit_from_js(name, JSON.stringify(arg)); }; </script>''') self._pending_js_eval = []
class HTMLWidget(QWebView): """An HTML widget that is displayed with Qt. Python methods can be called from Javascript with `widget.the_method()`. They must be decorated with `pyqtSlot(str)` or similar, depending on the parameters. """ title = 'Widget' body = '' def __init__(self): super(HTMLWidget, self).__init__() self.settings().setAttribute( QWebSettings.LocalContentCanAccessRemoteUrls, True) self.settings().setAttribute(QWebSettings.DeveloperExtrasEnabled, True) self.setPage(WebPage()) self._obj = None self._styles = [_DEFAULT_STYLES] self._header = '' self._body = '' self.add_to_js('widget', self) self._event = EventEmitter() self.add_header('''<script> var emit = function (name, arg) { widget._emit_from_js(name, JSON.stringify(arg)); }; </script>''') self._pending_js_eval = [] self._built = None # Events # ------------------------------------------------------------------------- def emit(self, *args, **kwargs): return self._event.emit(*args, **kwargs) def connect_(self, *args, **kwargs): self._event.connect(*args, **kwargs) def unconnect_(self, *args, **kwargs): self._event.unconnect(*args, **kwargs) # Headers # ------------------------------------------------------------------------- def add_styles(self, s): """Add CSS styles.""" self._styles.append(s) def add_style_src(self, filename): """Link a CSS file.""" self.add_header(('<link rel="stylesheet" type="text/css" ' 'href="{}" />').format(filename)) def add_script_src(self, filename): """Link a JS script.""" self.add_header('<script src="{}"></script>'.format(filename)) def add_header(self, h): """Add HTML code to the header.""" self._header += (h + '\n') # HTML methods # ------------------------------------------------------------------------- def set_body(self, s): """Set the HTML body.""" self._body = s def add_body(self, s): """Add HTML code to the body.""" self._body += '\n' + s + '\n' def html(self): """Return the full HTML source of the widget.""" return self.page().mainFrame().toHtml() def rebuild(self): styles = '\n\n'.join(self._styles) html = _PAGE_TEMPLATE.format( title=self.title, styles=styles, header=self._header, body=self._body, ) logger.log(5, "Set HTML: %s", html) static_dir = op.join(op.realpath(op.dirname(__file__)), 'static/') base_url = QUrl().fromLocalFile(static_dir) self.setHtml(html, base_url) def build(self): """Build the full HTML source.""" if self.is_built(): # pragma: no cover return with _wait_signal(self.loadFinished, 20): self.rebuild() self._built = True def is_built(self): return self._built # Javascript methods # ------------------------------------------------------------------------- def add_to_js(self, name, var): """Add an object to Javascript.""" frame = self.page().mainFrame() frame.addToJavaScriptWindowObject(name, var) def eval_js(self, expr): """Evaluate a Javascript expression.""" if not self.is_built(): self._pending_js_eval.append(expr) return logger.log(5, "Evaluate Javascript: `%s`.", expr) out = self.page().mainFrame().evaluateJavaScript(expr) return _to_py(out) @pyqtSlot(str, str) def _emit_from_js(self, name, arg_json): self.emit(text_type(name), json.loads(text_type(arg_json))) def show(self): self.build() super(HTMLWidget, self).show() # Call the pending JS eval calls after the page has been built. assert self.is_built() for expr in self._pending_js_eval: self.eval_js(expr) self._pending_js_eval = []
class HTMLWidget(QWebView): """An HTML widget that is displayed with Qt. Python methods can be called from Javascript with `widget.the_method()`. They must be decorated with `pyqtSlot(str)` or similar, depending on the parameters. """ title = 'Widget' body = '' def __init__(self): super(HTMLWidget, self).__init__() self.settings().setAttribute( QWebSettings.LocalContentCanAccessRemoteUrls, True) self.settings().setAttribute( QWebSettings.DeveloperExtrasEnabled, True) self.setPage(WebPage()) self._obj = None self._styles = [_DEFAULT_STYLES] self._header = '' self._body = '' self.add_to_js('widget', self) self._event = EventEmitter() self.add_header('''<script> var emit = function (name, arg) { widget._emit_from_js(name, JSON.stringify(arg)); }; </script>''') self._pending_js_eval = [] self._built = None # Events # ------------------------------------------------------------------------- def emit(self, *args, **kwargs): return self._event.emit(*args, **kwargs) def connect_(self, *args, **kwargs): self._event.connect(*args, **kwargs) def unconnect_(self, *args, **kwargs): self._event.unconnect(*args, **kwargs) # Headers # ------------------------------------------------------------------------- def add_styles(self, s): """Add CSS styles.""" self._styles.append(s) def add_style_src(self, filename): """Link a CSS file.""" self.add_header(('<link rel="stylesheet" type="text/css" ' 'href="{}" />').format(filename)) def add_script_src(self, filename): """Link a JS script.""" self.add_header('<script src="{}"></script>'.format(filename)) def add_header(self, h): """Add HTML code to the header.""" self._header += (h + '\n') # HTML methods # ------------------------------------------------------------------------- def set_body(self, s): """Set the HTML body.""" self._body = s def add_body(self, s): """Add HTML code to the body.""" self._body += '\n' + s + '\n' def html(self): """Return the full HTML source of the widget.""" return self.page().mainFrame().toHtml() def rebuild(self): styles = '\n\n'.join(self._styles) html = _PAGE_TEMPLATE.format(title=self.title, styles=styles, header=self._header, body=self._body, ) logger.log(5, "Set HTML: %s", html) static_dir = op.join(op.realpath(op.dirname(__file__)), 'static/') base_url = QUrl().fromLocalFile(static_dir) self.setHtml(html, base_url) def build(self): """Build the full HTML source.""" if self.is_built(): # pragma: no cover return with _wait_signal(self.loadFinished, 20): self.rebuild() self._built = True def is_built(self): return self._built # Javascript methods # ------------------------------------------------------------------------- def add_to_js(self, name, var): """Add an object to Javascript.""" frame = self.page().mainFrame() frame.addToJavaScriptWindowObject(name, var) def eval_js(self, expr): """Evaluate a Javascript expression.""" if not self.is_built(): self._pending_js_eval.append(expr) return logger.log(5, "Evaluate Javascript: `%s`.", expr) out = self.page().mainFrame().evaluateJavaScript(expr) return _to_py(out) @pyqtSlot(str, str) def _emit_from_js(self, name, arg_json): self.emit(text_type(name), json.loads(text_type(arg_json))) def show(self): self.build() super(HTMLWidget, self).show() # Call the pending JS eval calls after the page has been built. assert self.is_built() for expr in self._pending_js_eval: self.eval_js(expr) self._pending_js_eval = []