diff options
author | Florian Bruhin <git@the-compiler.org> | 2016-04-01 06:13:08 +0200 |
---|---|---|
committer | Florian Bruhin <git@the-compiler.org> | 2016-04-01 06:13:08 +0200 |
commit | aad2407de17b835df583f4b6604c250ec21617c7 (patch) | |
tree | 81c91512c53a9383bc7139578677c9cbe1da199f | |
parent | 451ea05393742a14c64a827ac9d3a819af46fa46 (diff) | |
parent | 0652637fbe08adb1c066a7e846be02e3c9ef025f (diff) | |
download | qutebrowser-aad2407de17b835df583f4b6604c250ec21617c7.tar.gz qutebrowser-aad2407de17b835df583f4b6604c250ec21617c7.zip |
Merge branch 'force-current-tab' of https://github.com/paretje/qutebrowser into paretje-force-current-tab
-rw-r--r-- | README.asciidoc | 2 | ||||
-rw-r--r-- | doc/help/commands.asciidoc | 3 | ||||
-rw-r--r-- | qutebrowser/browser/hints.py | 19 | ||||
-rw-r--r-- | qutebrowser/browser/webelem.py | 13 | ||||
-rw-r--r-- | tests/integration/data/hints/link_blank.html | 10 | ||||
-rw-r--r-- | tests/integration/data/hints/link_span.html | 10 | ||||
-rw-r--r-- | tests/integration/features/hints.feature | 26 | ||||
-rw-r--r-- | tests/unit/browser/test_webelem.py | 45 |
8 files changed, 119 insertions, 9 deletions
diff --git a/README.asciidoc b/README.asciidoc index 6cb17e248..11c0783b9 100644 --- a/README.asciidoc +++ b/README.asciidoc @@ -165,6 +165,7 @@ Contributors, sorted by the number of commits in descending order: * Thorsten Wißmann * Philipp Hansch * Austin Anderson +* Kevin Velghe * Alexey "Averrin" Nabrodov * avk * ZDarian @@ -216,7 +217,6 @@ Contributors, sorted by the number of commits in descending order: * Samuel Loury * Matthias Lisin * Marcel Schilling -* Kevin Velghe * Jean-Christophe Petkovich * Helen Sherwood-Taylor * HalosGhost diff --git a/doc/help/commands.asciidoc b/doc/help/commands.asciidoc index ae7b597d3..d3819741e 100644 --- a/doc/help/commands.asciidoc +++ b/doc/help/commands.asciidoc @@ -290,7 +290,8 @@ Start hinting. * +'target'+: What to do with the selected element. - - `normal`: Open the link in the current tab. + - `normal`: Open the link. + - `current`: Open the link in the current tab. - `tab`: Open the link in a new tab (honoring the background-tabs setting). - `tab-fg`: Open the link in a new foreground tab. diff --git a/qutebrowser/browser/hints.py b/qutebrowser/browser/hints.py index 26fd02fbc..3b71c0266 100644 --- a/qutebrowser/browser/hints.py +++ b/qutebrowser/browser/hints.py @@ -42,10 +42,10 @@ from qutebrowser.misc import guiprocess ElemTuple = collections.namedtuple('ElemTuple', ['elem', 'label']) -Target = usertypes.enum('Target', ['normal', 'tab', 'tab_fg', 'tab_bg', - 'window', 'yank', 'yank_primary', 'run', - 'fill', 'hover', 'download', 'userscript', - 'spawn']) +Target = usertypes.enum('Target', ['normal', 'current', 'tab', 'tab_fg', + 'tab_bg', 'window', 'yank', 'yank_primary', + 'run', 'fill', 'hover', 'download', + 'userscript', 'spawn']) class WordHintingError(Exception): @@ -71,7 +71,8 @@ class HintContext: elems: A mapping from key strings to (elem, label) namedtuples. baseurl: The URL of the current page. target: What to do with the opened links. - normal/tab/tab_fg/tab_bg/window: Get passed to BrowserTab. + normal/current/tab/tab_fg/tab_bg/window: Get passed to + BrowserTab. yank/yank_primary: Yank to clipboard/primary selection. run: Run a command. fill: Fill commandline with link. @@ -128,6 +129,7 @@ class HintManager(QObject): HINT_TEXTS = { Target.normal: "Follow hint", + Target.current: "Follow hint in current tab", Target.tab: "Follow hint in new tab", Target.tab_fg: "Follow hint in foreground tab", Target.tab_bg: "Follow hint in background tab", @@ -429,6 +431,7 @@ class HintManager(QObject): """ target_mapping = { Target.normal: usertypes.ClickTarget.normal, + Target.current: usertypes.ClickTarget.normal, Target.tab_fg: usertypes.ClickTarget.tab, Target.tab_bg: usertypes.ClickTarget.tab_bg, Target.window: usertypes.ClickTarget.window, @@ -463,6 +466,8 @@ class HintManager(QObject): QMouseEvent(QEvent.MouseButtonRelease, pos, Qt.LeftButton, Qt.NoButton, modifiers), ] + if context.target == Target.current: + elem.remove_blank_target() for evt in events: self.mouse_event.emit(evt) if elem.is_text_input() and elem.is_editable(): @@ -741,7 +746,8 @@ class HintManager(QObject): target: What to do with the selected element. - - `normal`: Open the link in the current tab. + - `normal`: Open the link. + - `current`: Open the link in the current tab. - `tab`: Open the link in a new tab (honoring the background-tabs setting). - `tab-fg`: Open the link in a new foreground tab. @@ -891,6 +897,7 @@ class HintManager(QObject): # Handlers which take a QWebElement elem_handlers = { Target.normal: self._click, + Target.current: self._click, Target.tab: self._click, Target.tab_fg: self._click, Target.tab_bg: self._click, diff --git a/qutebrowser/browser/webelem.py b/qutebrowser/browser/webelem.py index 49f4bfc27..df481b98c 100644 --- a/qutebrowser/browser/webelem.py +++ b/qutebrowser/browser/webelem.py @@ -285,6 +285,19 @@ class WebElementWrapper(collections.abc.MutableMapping): tag = self._elem.tagName().lower() return self.get('role', None) in roles or tag in ('input', 'textarea') + def remove_blank_target(self): + """Remove target from link.""" + elem = self._elem + for _ in range(5): + if elem is None: + break + tag = elem.tagName().lower() + if tag == 'a' or tag == 'area': + if elem.attribute('target') == '_blank': + elem.setAttribute('target', '_top') + break + elem = elem.parent() + def debug_text(self): """Get a text based on an element suitable for debug output.""" self._check_vanished() diff --git a/tests/integration/data/hints/link_blank.html b/tests/integration/data/hints/link_blank.html new file mode 100644 index 000000000..f738e61dc --- /dev/null +++ b/tests/integration/data/hints/link_blank.html @@ -0,0 +1,10 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>A link to use hints on</title> + </head> + <body> + <a href="/data/hello.txt" target="_blank">Follow me!</a> + </body> +</html> diff --git a/tests/integration/data/hints/link_span.html b/tests/integration/data/hints/link_span.html new file mode 100644 index 000000000..2a5bbfdfd --- /dev/null +++ b/tests/integration/data/hints/link_span.html @@ -0,0 +1,10 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>A link to use hints on</title> + </head> + <body> + <a href="/data/hello.txt" target="_blank"><span style="font-size: large">Follow me!</span></a> + </body> +</html> diff --git a/tests/integration/features/hints.feature b/tests/integration/features/hints.feature index d95cdf868..3f6fab924 100644 --- a/tests/integration/features/hints.feature +++ b/tests/integration/features/hints.feature @@ -18,3 +18,29 @@ Feature: Using hints And I run :hint links normal And I run :follow-hint xyz Then the error "No hint xyz!" should be shown + + Scenario: Following a hint and force to open in current tab. + When I open data/hints/link_blank.html + And I run :hint links current + And I run :follow-hint a + And I wait until data/hello.txt is loaded + Then the following tabs should be open: + - data/hello.txt (active) + + Scenario: Following a hint and allow to open in new tab. + When I open data/hints/link_blank.html + And I run :hint links normal + And I run :follow-hint a + And I wait until data/hello.txt is loaded + Then the following tabs should be open: + - data/hints/link_blank.html + - data/hello.txt (active) + + Scenario: Following a hint to link with sub-element and force to open in current tab. + When I open data/hints/link_span.html + And I run :tab-close + And I run :hint links current + And I run :follow-hint a + And I wait until data/hello.txt is loaded + Then the following tabs should be open: + - data/hello.txt (active) diff --git a/tests/unit/browser/test_webelem.py b/tests/unit/browser/test_webelem.py index 1457e08ef..459a8b1b1 100644 --- a/tests/unit/browser/test_webelem.py +++ b/tests/unit/browser/test_webelem.py @@ -36,7 +36,8 @@ from qutebrowser.browser import webelem def get_webelem(geometry=None, frame=None, null=False, style=None, - display='', attributes=None, tagname=None, classes=None): + display='', attributes=None, tagname=None, classes=None, + parent=None): """Factory for WebElementWrapper objects based on a mock. Args: @@ -55,6 +56,7 @@ def get_webelem(geometry=None, frame=None, null=False, style=None, elem.tagName.return_value = tagname elem.toOuterXml.return_value = '<fakeelem/>' elem.toPlainText.return_value = 'text' + elem.parent.return_value = parent attribute_dict = {} if attributes is None: @@ -326,6 +328,47 @@ class TestWebElementWrapper: assert elem.debug_text() == expected +class TestRemoveBlankTarget: + + @pytest.mark.parametrize('tagname', ['a', 'area']) + @pytest.mark.parametrize('target', ['_self', '_parent', '_top', '']) + def test_keep_target(self, tagname, target): + elem = get_webelem(tagname=tagname, attributes={'target': target}) + elem.remove_blank_target() + assert elem['target'] == target + + @pytest.mark.parametrize('tagname', ['a', 'area']) + def test_no_target(self, tagname): + elem = get_webelem(tagname=tagname) + elem.remove_blank_target() + assert 'target' not in elem + + @pytest.mark.parametrize('tagname', ['a', 'area']) + def test_blank_target(self, tagname): + elem = get_webelem(tagname=tagname, attributes={'target': '_blank'}) + elem.remove_blank_target() + assert elem['target'] == '_top' + + @pytest.mark.parametrize('tagname', ['a', 'area']) + def test_ancestor_blank_target(self, tagname): + elem = get_webelem(tagname=tagname, attributes={'target': '_blank'}) + elem_child = get_webelem(tagname='img', parent=elem._elem) + elem_child._elem.encloseWith(elem._elem) + elem_child.remove_blank_target() + assert elem['target'] == '_top' + + @pytest.mark.parametrize('depth', [1, 5, 10]) + def test_no_link(self, depth): + elem = [None] * depth + elem[0] = get_webelem(tagname='div') + for i in range(1, depth): + elem[i] = get_webelem(tagname='div', parent=elem[i-1]) + elem[i]._elem.encloseWith(elem[i-1]._elem) + elem[-1].remove_blank_target() + for i in range(depth): + assert 'target' not in elem[i] + + class TestIsVisible: @pytest.fixture |