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.
This commit is contained in:
parent
58fb41ab9d
commit
9a17591fb7
@ -613,6 +613,15 @@ class AbstractTab(QWidget):
|
||||
"""
|
||||
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 @@ class CommandDispatcher:
|
||||
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 @@ class CommandDispatcher:
|
||||
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 @@ class WebEngineTab(browsertab.AbstractTab):
|
||||
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 @@ class WebKitTab(browsertab.AbstractTab):
|
||||
|
||||
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 @@ class WebView(QWebView):
|
||||
|
||||
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];
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user