Permalink
Browse files

Start getting :open-editor to work with WebEngine

It doesn't actually work yet (as it claims the field is not editable),
but at least does not crash when the backend limitation for the command
is removed.
  • Loading branch information...
The-Compiler committed Aug 8, 2016
1 parent 58fb41a commit 9a17591fb7761bbe31c853ca01d22f1c82037944
@@ -613,6 +613,15 @@ def find_all_elements(self, selector, callback, *, only_visible=False):
"""
raise NotImplementedError
+ def find_focus_element(self, callback):
+ """Find the focused element on the page async.
+
+ Args:
+ callback: The callback to be called when the search finished.
+ Called with a WebEngineElement or None.
+ """
+ raise NotImplementedError
+
def __repr__(self):
try:
url = utils.elide(self.url().toDisplayString(QUrl.EncodeUnicode),
@@ -1408,6 +1408,21 @@ def messages(self, level='error', plain=False, tab=False, bg=False,
url = QUrl('qute://log?level={}'.format(level))
self._open(url, tab, bg, window)
+ def _open_editor_cb(self, elem):
+ """Open editor after the focus elem was found in open_editor."""
+ if elem is None:
+ message.error(self._win_id, "No element focused!")
+ return
+ if not elem.is_editable(strict=True):
+ message.error(self._win_id, "Focused element is not editable!")
+ return
+
+ text = elem.text(use_js=True)
+ ed = editor.ExternalEditor(self._win_id, self._tabbed_browser)
+ ed.editing_finished.connect(functools.partial(
+ self.on_editing_finished, elem))
+ ed.edit(text)
+
@cmdutils.register(instance='command-dispatcher',
modes=[KeyMode.insert], hide=True, scope='window',
backend=usertypes.Backend.QtWebKit)
@@ -1417,20 +1432,8 @@ def open_editor(self):
The editor which should be launched can be configured via the
`general -> editor` config option.
"""
- # FIXME:qtwebengine have a proper API for this
tab = self._current_widget()
- page = tab._widget.page() # pylint: disable=protected-access
- try:
- elem = webkitelem.focus_elem(page.currentFrame())
- except webkitelem.IsNullError:
- raise cmdexc.CommandError("No element focused!")
- if not elem.is_editable(strict=True):
- raise cmdexc.CommandError("Focused element is not editable!")
- text = elem.text(use_js=True)
- ed = editor.ExternalEditor(self._win_id, self._tabbed_browser)
- ed.editing_finished.connect(functools.partial(
- self.on_editing_finished, elem))
- ed.edit(text)
+ tab.find_focus_element(self._open_editor_cb)
def on_editing_finished(self, elem, text):
"""Write the editor text into the form field and clean up tempfile.
@@ -431,6 +431,25 @@ def find_all_elements(self, selector, callback, *, only_visible=False):
js_cb = functools.partial(self._find_all_elements_js_cb, callback)
self.run_js_async(js_code, js_cb)
+ def _find_focus_element_js_cb(self, callback, js_elem):
+ """Handle a found focus elem coming from JS and call the real callback.
+
+ Args:
+ callback: The callback originally passed to find_focus_element.
+ Called with a WebEngineElement or None.
+ js_elem: The element serialized from javascript.
+ """
+ log.webview.debug("Got focus element from JS: {!r}".format(js_elem))
+ if js_elem is None:
+ callback(None)
+ else:
+ callback(webengineelem.WebEngineElement(js_elem))
+
+ def find_focus_element(self, callback):
+ js_code = javascript.assemble('webelem', 'focus_element')
+ js_cb = functools.partial(self._find_focus_element_js_cb, callback)
+ self.run_js_async(js_code, js_cb)
+
def _connect_signals(self):
view = self._widget
page = view.page()
@@ -574,6 +574,18 @@ def find_all_elements(self, selector, callback, *, only_visible=False):
callback(elems)
+ def find_focus_element(self, callback):
+ frame = self._widget.page().currentFrame()
+ if frame is None:
+ callback(None)
+ return
+
+ elem = frame.findFirstElement('*:focus')
+ if elem.isNull():
+ callback(None)
+ else:
+ callback(webkitelem.WebKitElement(elem))
+
@pyqtSlot()
def _on_frame_load_finished(self):
"""Make sure we emit an appropriate status when loading finished.
@@ -223,6 +223,7 @@ def _mousepress_insertmode(self, e):
def mouserelease_insertmode(self):
"""If we have an insertmode check scheduled, handle it."""
+ # FIXME:qtwebengine Use tab.find_focus_element here
if not self._check_insertmode:
return
self._check_insertmode = False
@@ -22,7 +22,12 @@ document._qutebrowser_elements = [];
function _qutebrowser_serialize_elem(elem, id) {
- var out = {};
+ var out = {
+ "id": id,
+ "text": elem.text,
+ "tag_name": elem.tagName,
+ "outer_xml": elem.outerHTML
+ };
var attributes = {};
for (var i = 0; i < elem.attributes.length; ++i) {
@@ -31,11 +36,6 @@ function _qutebrowser_serialize_elem(elem, id) {
}
out["attributes"] = attributes;
- out["text"] = elem.text;
- out["tag_name"] = elem.tagName;
- out["outer_xml"] = elem.outerHTML;
- out["id"] = id;
-
// console.log(JSON.stringify(out));
return out;
@@ -58,6 +58,19 @@ function _qutebrowser_find_all_elements(selector) {
}
+function _qutebrowser_focus_element() {
+ var elem = document.activeElement;
+ if (!elem || elem === document.body) {
+ // "When there is no selection, the active element is the page's <body>
+ // or null."
+ return null;
+ }
+
+ var id = document._qutebrowser_elements.length;
+ return _qutebrowser_serialize_elem(elem, id);
+}
+
+
function _qutebrowser_get_element(id) {
return document._qutebrowser_elements[id];
}

0 comments on commit 9a17591

Please sign in to comment.