Add support for follow_selected via fake-clicks

This commit is contained in:
Jay Kamat 2017-05-08 22:31:29 -07:00
parent e07a1045a8
commit c9953b9f0d
No known key found for this signature in database
GPG Key ID: 5D2E399600F4F7B5
4 changed files with 71 additions and 4 deletions

View File

@ -196,6 +196,10 @@ class AbstractSearch(QObject):
"""
raise NotImplementedError
def searching(self):
"""Return True if we are currently searching or not."""
raise NotImplementedError
class AbstractZoom(QObject):

View File

@ -127,9 +127,12 @@ class WebEngineSearch(browsertab.AbstractSearch):
def __init__(self, parent=None):
super().__init__(parent)
self._flags = QWebEnginePage.FindFlags(0)
self._searching = False
def _find(self, text, flags, callback, caller):
"""Call findText on the widget."""
self._searching = True
def wrapped_callback(found):
"""Wrap the callback to do debug logging."""
found_text = 'found' if found else "didn't find"
@ -160,8 +163,12 @@ class WebEngineSearch(browsertab.AbstractSearch):
self._find(text, flags, result_cb, 'search')
def clear(self):
self._searching = False
self._widget.findText('')
def searching(self):
return self._searching
def prev_result(self, *, result_cb=None):
# The int() here makes sure we get a copy of the flags.
flags = QWebEnginePage.FindFlags(int(self._flags))
@ -246,8 +253,47 @@ class WebEngineCaret(browsertab.AbstractCaret):
raise browsertab.UnsupportedOperationError
return self._widget.selectedText()
def _follow_selected_cb(self, js_elem, tab=False):
"""Callback for javascript which clicks the selected element.
Args:
js_elems: The elements serialized from javascript.
tab: Open in a new tab or not.
"""
if js_elem is None:
return
assert isinstance(js_elem, dict), js_elem
elem = webengineelem.WebEngineElement(js_elem, tab=self._tab)
if tab:
click_type = usertypes.ClickTarget.tab
else:
click_type = usertypes.ClickTarget.normal
# Only click if we see a link
if elem.is_link():
log.webview.debug("Found link in selection, clicking. Tab: " +
str(click_type) + "Link: " + str(elem))
elem.click(click_type)
def follow_selected(self, *, tab=False):
log.stub()
if self._tab.search.searching():
# 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 not tab:
self._tab.scroller._key_press(Qt.Key_Enter)
else:
self._tab.scroller._key_press(Qt.Key_Enter, modifier=Qt.ControlModifier)
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))
class WebEngineScroller(browsertab.AbstractScroller):
@ -265,10 +311,10 @@ class WebEngineScroller(browsertab.AbstractScroller):
page = widget.page()
page.scrollPositionChanged.connect(self._update_pos)
def _key_press(self, key, count=1):
def _key_press(self, key, count=1, modifier=Qt.NoModifier):
for _ in range(min(count, 5000)):
press_evt = QKeyEvent(QEvent.KeyPress, key, Qt.NoModifier, 0, 0, 0)
release_evt = QKeyEvent(QEvent.KeyRelease, key, Qt.NoModifier,
press_evt = QKeyEvent(QEvent.KeyPress, key, modifier, 0, 0, 0)
release_evt = QKeyEvent(QEvent.KeyRelease, key, modifier,
0, 0, 0)
self._tab.send_event(press_evt)
self._tab.send_event(release_evt)

View File

@ -103,6 +103,7 @@ class WebKitSearch(browsertab.AbstractSearch):
def __init__(self, parent=None):
super().__init__(parent)
self._flags = QWebPage.FindFlags(0)
self._searching = True
def _call_cb(self, callback, found, text, flags, caller):
"""Call the given callback if it's non-None.
@ -132,12 +133,14 @@ class WebKitSearch(browsertab.AbstractSearch):
QTimer.singleShot(0, functools.partial(callback, found))
def clear(self):
self._searching = False
# We first clear the marked text, then the highlights
self._widget.findText('')
self._widget.findText('', QWebPage.HighlightAllOccurrences)
def search(self, text, *, ignore_case=False, reverse=False,
result_cb=None):
self._searching = True
flags = QWebPage.FindWrapsAroundDocument
if ignore_case == 'smart':
if not text.islower():
@ -155,10 +158,12 @@ class WebKitSearch(browsertab.AbstractSearch):
self._call_cb(result_cb, found, text, flags, 'search')
def next_result(self, *, result_cb=None):
self._searching = True
found = self._widget.findText(self.text, self._flags)
self._call_cb(result_cb, found, self.text, self._flags, 'next_result')
def prev_result(self, *, result_cb=None):
self._searching = True
# The int() here makes sure we get a copy of the flags.
flags = QWebPage.FindFlags(int(self._flags))
if flags & QWebPage.FindBackward:
@ -168,6 +173,9 @@ class WebKitSearch(browsertab.AbstractSearch):
found = self._widget.findText(self.text, flags)
self._call_cb(result_cb, found, self.text, flags, 'prev_result')
def searching(self):
return self._searching
class WebKitCaret(browsertab.AbstractCaret):

View File

@ -169,6 +169,15 @@ window._qutebrowser.webelem = (function() {
return serialize_elem(elem);
};
// Function for returning a selection to python (so we can click it)
funcs.find_selected_link = function() {
var elem = window.getSelection().anchorNode;
if (!elem) {
return null;
}
return serialize_elem(elem.parentNode);
};
funcs.set_value = function(id, value) {
elements[id].value = value;
};