def selection(self, callback): # Not using selectedText() as WORKAROUND for # https://bugreports.qt.io/browse/QTBUG-53134 # Even on Qt 5.10 selectedText() seems to work poorly, see # https://github.com/qutebrowser/qutebrowser/issues/3523 self._tab.run_js_async(javascript.assemble('caret', 'getSelection'), callback)
def _js_call(self, name: str, *args: webelem.JsValueType, callback: typing.Callable[[typing.Any], None] = None) -> None: """Wrapper to run stuff from webelem.js.""" if self._tab.is_deleted(): raise webelem.OrphanedError("Tab containing element vanished") js_code = javascript.assemble('webelem', name, self._id, *args) self._tab.run_js_async(js_code, callback=callback)
def _update_pos(self): """Update the scroll position attributes when it changed.""" def update_pos_cb(jsret): """Callback after getting scroll position via JS.""" if jsret is None: # This can happen when the callback would get called after # shutting down a tab return log.webview.vdebug(jsret) assert isinstance(jsret, dict), jsret self._pos_px = QPoint(jsret['px']['x'], jsret['px']['y']) dx = jsret['scroll']['width'] - jsret['inner']['width'] if dx == 0: perc_x = 0 else: perc_x = min(100, round(100 / dx * jsret['px']['x'])) dy = jsret['scroll']['height'] - jsret['inner']['height'] if dy == 0: perc_y = 0 else: perc_y = min(100, round(100 / dy * jsret['px']['y'])) self._at_bottom = dy >= jsret['px']['y'] self._pos_perc = perc_x, perc_y self.perc_changed.emit(*self._pos_perc) js_code = javascript.assemble('scroll', 'pos') self._tab.run_js_async(js_code, update_pos_cb)
def find_at_pos(self, pos, callback): assert pos.x() >= 0 assert pos.y() >= 0 js_code = javascript.assemble('webelem', 'element_at_pos', pos.x(), pos.y()) js_cb = functools.partial(self._js_cb_single, callback) self._tab.run_js_async(js_code, js_cb)
def _init_stylesheet(profile): """Initialize custom stylesheets. Partially inspired by QupZilla: https://github.com/QupZilla/qupzilla/blob/v2.0/src/lib/app/mainapplication.cpp#L1063-L1101 """ old_script = profile.scripts().findScript('_qute_stylesheet') if not old_script.isNull(): profile.scripts().remove(old_script) css = shared.get_user_stylesheet() source = '\n'.join([ '"use strict";', 'window._qutebrowser = window._qutebrowser || {};', utils.read_file('javascript/stylesheet.js'), javascript.assemble('stylesheet', 'set_css', css), ]) script = QWebEngineScript() script.setName('_qute_stylesheet') script.setInjectionPoint(QWebEngineScript.DocumentCreation) script.setWorldId(QWebEngineScript.ApplicationWorld) script.setRunsOnSubFrames(True) script.setSourceCode(source) profile.scripts().insert(script)
def set_text(self, text, *, use_js=False): """Set the given plain text. Args: use_js: Whether to use javascript if the element isn't content-editable. """ # FIXME:qtwebengine what to do about use_js with WebEngine? js_code = javascript.assemble('webelem', 'set_text', self._id, text) self._tab.run_js_async(js_code)
def _update_stylesheet(): """Update the custom stylesheet in existing tabs.""" css = shared.get_user_stylesheet() code = javascript.assemble('stylesheet', 'set_css', css) for win_id, window in objreg.window_registry.items(): # We could be in the middle of destroying a window here if sip.isdeleted(window): continue tab_registry = objreg.get('tab-registry', scope='window', window=win_id) for tab in tab_registry.values(): tab.run_js_async(code)
def _on_mode_entered(self, mode): if mode != usertypes.KeyMode.caret: return if self._tab.search.search_displayed: # We are currently in search mode. # convert the search to a blue selection so we can operate on it # https://bugreports.qt.io/browse/QTBUG-60673 self._tab.search.clear() self._tab.run_js_async( javascript.assemble('caret', 'setPlatform', sys.platform)) self._js_call('setInitialCursor')
def _update_pos(self): """Update the scroll position attributes when it changed.""" def update_pos_cb(jsret): """Callback after getting scroll position via JS.""" if jsret is None: # This can happen when the callback would get called after # shutting down a tab return assert isinstance(jsret, dict), jsret self._pos_perc = (jsret['perc']['x'], jsret['perc']['y']) self._pos_px = QPoint(jsret['px']['x'], jsret['px']['y']) self.perc_changed.emit(*self._pos_perc) js_code = javascript.assemble('scroll', 'pos') self._tab.run_js_async(js_code, update_pos_cb)
def follow_selected(self, *, tab=False): if self._tab.search.search_displayed: # We are currently in search mode. # let's click the link via a fake-click # https://bugreports.qt.io/browse/QTBUG-60673 self._tab.search.clear() log.webview.debug("Clicking a searched link via fake key press.") # send a fake enter, clicking the orange selection box if tab: self._tab.key_press(Qt.Key_Enter, modifier=Qt.ControlModifier) else: self._tab.key_press(Qt.Key_Enter) else: # click an existing blue selection js_code = javascript.assemble('webelem', 'find_selected_link') self._tab.run_js_async(js_code, lambda jsret: self._follow_selected_cb(jsret, tab))
def find_focused(self, callback): js_code = javascript.assemble('webelem', 'find_focused') js_cb = functools.partial(self._js_cb_single, callback) self._tab.run_js_async(js_code, js_cb)
def delta_page(self, x=0, y=0): js_code = javascript.assemble('scroll', 'delta_page', x, y) self._tab.run_js_async(js_code)
def __setitem__(self, key, val): self._js_dict['attributes'][key] = val js_code = javascript.assemble('webelem', 'set_attribute', self._id, key, val) self._tab.run_js_async(js_code)
def insert_text(self, text): if not self.is_editable(strict=True): raise webelem.Error("Element is not editable!") log.webelem.debug("Inserting text into element {!r}".format(self)) js_code = javascript.assemble('webelem', 'insert_text', self._id, text) self._tab.run_js_async(js_code)
def _js_call(self, name, *args, callback=None): """Wrapper to run stuff from webelem.js.""" js_code = javascript.assemble('webelem', name, self._id, *args) self._tab.run_js_async(js_code, callback=callback)
def _js_call(self, name, *args, callback=None): """Wrapper to run stuff from webelem.js.""" if self._tab.is_deleted(): raise webelem.OrphanedError("Tab containing element vanished") js_code = javascript.assemble('webelem', name, self._id, *args) self._tab.run_js_async(js_code, callback=callback)
def to_point(self, point): js_code = javascript.assemble('window', 'scroll', point.x(), point.y()) self._tab.run_js_async(js_code)
def find_focused(self, callback): js_code = javascript.assemble('webelem', 'focus_element') js_cb = functools.partial(self._js_cb_single, callback) self._tab.run_js_async(js_code, js_cb)
def delta_page(self, x=0, y=0): js_code = javascript.assemble('scroll', 'delta_page', x, y) self._tab.run_js_async(js_code)
def delta(self, x=0, y=0): self._tab.run_js_async(javascript.assemble('window', 'scrollBy', x, y))
def find_css(self, selector, callback, *, only_visible=False): js_code = javascript.assemble('webelem', 'find_css', selector, only_visible) js_cb = functools.partial(self._js_cb_multiple, callback) self._tab.run_js_async(js_code, js_cb)
def set_css(self, css): """Set document style to `css` via stylesheet.js.""" code = javascript.assemble('stylesheet', 'set_css', css) self.js.run(code, None)
def find_all_elements(self, selector, callback, *, only_visible=False): js_code = javascript.assemble('webelem', 'find_all', selector) js_cb = functools.partial(self._find_all_elements_js_cb, callback) self.run_js_async(js_code, js_cb)
def find_css(self, selector, callback, *, only_visible=False): js_code = javascript.assemble('webelem', 'find_all', selector, only_visible) js_cb = functools.partial(self._js_cb_multiple, callback) self._tab.run_js_async(js_code, js_cb)
def _js_call(self, name, *args, callback=None): """Wrapper to run stuff from webelem.js.""" js_code = javascript.assemble('webelem', name, self._id, *args) self._tab.run_js_async(js_code, callback=callback)
def find_id(self, elem_id, callback): js_code = javascript.assemble('webelem', 'element_by_id', elem_id) js_cb = functools.partial(self._js_cb_single, callback) self._tab.run_js_async(js_code, js_cb)
def _js_call(self, command): self._tab.run_js_async( javascript.assemble('caret', command))
def _js_call(self, command, callback=None): self._tab.run_js_async(javascript.assemble('caret', command), callback)
def to_perc(self, x=None, y=None): js_code = javascript.assemble('scroll', 'to_perc', x, y) self._tab.run_js_async(js_code)
def test_assemble(base, expected_base): expected = '"use strict";\n{}.func(23);'.format(expected_base) assert javascript.assemble(base, 'func', 23) == expected
def to_perc(self, x=None, y=None): js_code = javascript.assemble('scroll', 'to_perc', x, y) self._tab.run_js_async(js_code)
def remove_blank_target(self): js_code = javascript.assemble('webelem', 'remove_blank_target', self._id) self._tab.run_js_async(js_code)
def to_point(self, point): js_code = javascript.assemble('window', 'scroll', point.x(), point.y()) self._tab.run_js_async(js_code)
def set_value(self, value): js_code = javascript.assemble('webelem', 'set_value', self._id, value) self._tab.run_js_async(js_code)
def delta(self, x=0, y=0): self._tab.run_js_async(javascript.assemble('window', 'scrollBy', x, y))
def test_assemble(base, expected_base): expected = '"use strict";\n{}.func(23);'.format(expected_base) assert javascript.assemble(base, 'func', 23) == expected
def _update_stylesheet(self): """Update the custom stylesheet in existing tabs.""" css = shared.get_user_stylesheet() code = javascript.assemble('stylesheet', 'set_css', css) self.run_js_async(code)