Permalink
Browse files

Add a hints -> find-implementation setting

This makes it possible to switch to an alternative implementation if
there are weird issues like #1568. Some users might also prefer the
slightly better performance over more accurate hints.
  • Loading branch information...
The-Compiler committed Jun 9, 2016
1 parent 2d54c92 commit 035526848eb40cb95f70926667911f5bc5f8e393
View
@@ -35,6 +35,9 @@ Added
- New `hints -> auto-follow-timeout` setting to ignore keypresses after
following a hint when filtering in number mode.
- New `:history-clear` command to clear the entire history
+- New `hints -> find-implementation` to select which implementation (JS/Python)
+ should be used to find hints on a page. The `javascript` implementation is
+ better, but slower.
Changed
~~~~~~~
View
@@ -186,6 +186,7 @@
|<<hints-auto-follow-timeout,auto-follow-timeout>>|A timeout to inhibit normal-mode key bindings after a successfulauto-follow.
|<<hints-next-regexes,next-regexes>>|A comma-separated list of regexes to use for 'next' links.
|<<hints-prev-regexes,prev-regexes>>|A comma-separated list of regexes to use for 'prev' links.
+|<<hints-find-implementation,find-implementation>>|Which implementation to use to find elements to hint.
|==============
.Quick reference for section ``colors''
@@ -1637,6 +1638,17 @@ A comma-separated list of regexes to use for 'prev' links.
Default: +pass:[\bprev(ious)?\b,\bback\b,\bolder\b,\b[&lt;←≪]\b,\b(&lt;&lt;|«)\b]+
+[[hints-find-implementation]]
+=== find-implementation
+Which implementation to use to find elements to hint.
+
+Valid values:
+
+ * +javascript+: Better but slower
+ * +python+: Slightly worse but faster
+
+Default: +pass:[javascript]+
+
== searchengines
Definitions of search engines which can be used via the address bar.
The searchengine named `DEFAULT` is used when `general -> auto-search` is true and something else than a URL was entered to be opened. Other search engines can be used by prepending the search engine name to the search term, e.g. `:open google qutebrowser`. The string `{}` will be replaced by the search term, use `{{` and `}}` for literal `{`/`}` signs.
@@ -381,11 +381,12 @@ def _set_style_position(self, elem, label):
elem: The QWebElement to set the style attributes for.
label: The label QWebElement.
"""
- rect = elem.rect_on_view(adjust_zoom=False)
+ no_js = config.get('hints', 'find-implementation') != 'javascript'
+ rect = elem.rect_on_view(adjust_zoom=False, no_js=no_js)
left = rect.x()
top = rect.y()
- log.hints.vdebug("Drawing label '{!r}' at {}/{} for element '{!r}'"
- .format(label, left, top, elem))
+ log.hints.vdebug("Drawing label '{!r}' at {}/{} for element '{!r}' "
+ "(no_js: {})".format(label, left, top, elem, no_js))
label.setStyleProperty('left', '{}px !important'.format(left))
label.setStyleProperty('top', '{}px !important'.format(top))
@@ -173,14 +173,9 @@ def is_visible(self, mainframe):
"""
return is_visible(self._elem, mainframe)
- def rect_on_view(self, *, adjust_zoom=True):
- """Get the geometry of the element relative to the webview.
-
- Args:
- adjust_zoom: Whether to adjust the element position based on the
- current zoom level.
- """
- return rect_on_view(self._elem, adjust_zoom=adjust_zoom)
+ def rect_on_view(self, **kwargs):
+ """Get the geometry of the element relative to the webview."""
+ return rect_on_view(self._elem, **kwargs)
def is_writable(self):
"""Check whether an element is writable."""
@@ -368,7 +363,7 @@ def focus_elem(frame):
return WebElementWrapper(elem)
-def rect_on_view(elem, *, elem_geometry=None, adjust_zoom=True):
+def rect_on_view(elem, *, elem_geometry=None, adjust_zoom=True, no_js=False):
"""Get the geometry of the element relative to the webview.
We need this as a standalone function (as opposed to a WebElementWrapper
@@ -391,13 +386,14 @@ def rect_on_view(elem, *, elem_geometry=None, adjust_zoom=True):
want to avoid doing it twice.
adjust_zoom: Whether to adjust the element position based on the
current zoom level.
+ no_js: Fall back to the Python implementation
"""
if elem.isNull():
raise IsNullError("Got called on a null element!")
# First try getting the element rect via JS, as that's usually more
# accurate
- if elem_geometry is None:
+ if elem_geometry is None and not no_js:
rects = elem.evaluateJavaScript("this.getClientRects()")
text = utils.compact_text(elem.toOuterXml(), 500)
log.hints.vdebug("Client rectangles of element '{}': {}".format(text,
@@ -930,6 +930,14 @@ def data(readonly=False):
r'\b(<<|«)\b'),
"A comma-separated list of regexes to use for 'prev' links."),
+ ('find-implementation',
+ SettingValue(typ.String(
+ valid_values=typ.ValidValues(
+ ('javascript', "Better but slower"),
+ ('python', "Slightly worse but faster"),
+ )), 'javascript'),
+ "Which implementation to use to find elements to hint."),
+
readonly=readonly
)),
@@ -232,4 +232,3 @@ Feature: Using hints
And I press the key "2"
And I wait for "Leaving mode KeyMode.hint (reason: all filtered)" in the log
Then no crash should happen
-
@@ -38,7 +38,9 @@ def collect_tests():
@pytest.mark.parametrize('test_name', collect_tests())
@pytest.mark.parametrize('zoom_text_only', [True, False])
@pytest.mark.parametrize('zoom_level', [100, 66, 33])
-def test_hints(test_name, zoom_text_only, zoom_level, quteproc):
+@pytest.mark.parametrize('find_implementation', ['javascript', 'python'])
+def test_hints(test_name, zoom_text_only, zoom_level, find_implementation,
+ quteproc):
file_path = os.path.join(os.path.abspath(os.path.dirname(__file__)),
'data', 'hints', 'html', test_name)
url_path = 'data/hints/html/{}'.format(test_name)
@@ -69,6 +71,7 @@ def test_hints(test_name, zoom_text_only, zoom_level, quteproc):
# setup
quteproc.send_cmd(':set ui zoom-text-only {}'.format(zoom_text_only))
+ quteproc.set_setting('hints', 'find-implementation', find_implementation)
quteproc.send_cmd(':zoom {}'.format(zoom_level))
# follow hint
quteproc.send_cmd(':hint links normal')
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Different hint implementations</title>
+ </head>
+ <body>
+ <p>When setting hints -> find-implementation to python, the label for the wrapped hint should be drawn at the wrong position.</p>
+ <div style="width: 20em;">
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis <a href="/data/hello.txt">nostrud exercitation</a> ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
+ </div>
+ </body>
+</html>

0 comments on commit 0355268

Please sign in to comment.