From 4d650c8dfd46ce81c82ef9abd8c2b43c8ac42ce9 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Mon, 4 Jul 2016 13:35:38 +0200 Subject: [PATCH] Add tab.caret.follow_selected() --- qutebrowser/browser/commands.py | 30 +++------------- qutebrowser/browser/tab.py | 16 +++++---- qutebrowser/browser/webengine/webenginetab.py | 5 +-- qutebrowser/browser/webkit/webkittab.py | 34 ++++++++++++++++--- 4 files changed, 45 insertions(+), 40 deletions(-) diff --git a/qutebrowser/browser/commands.py b/qutebrowser/browser/commands.py index 7c855c75b..24d22107d 100644 --- a/qutebrowser/browser/commands.py +++ b/qutebrowser/browser/commands.py @@ -25,7 +25,6 @@ import sys import shlex import posixpath import functools -import xml.etree.ElementTree from PyQt5.QtWebKit import QWebSettings from PyQt5.QtWidgets import QApplication, QTabBar @@ -40,6 +39,7 @@ import pygments.formatters from qutebrowser.commands import userscripts, cmdexc, cmdutils, runners from qutebrowser.config import config, configexc from qutebrowser.browser import urlmarks +from qutebrowser.browser import tab as tabmod from qutebrowser.browser.webkit import webelem, inspector, downloads, mhtml from qutebrowser.keyinput import modeman from qutebrowser.utils import (message, usertypes, log, qtutils, urlutils, @@ -1107,30 +1107,10 @@ class CommandDispatcher: Args: tab: Load the selected link in a new tab. """ - widget = self._current_widget() - if not widget.caret.has_selection(): - return - if QWebSettings.globalSettings().testAttribute( - QWebSettings.JavascriptEnabled): - if tab: - widget.set_open_target(usertypes.ClickTarget.tab) - widget.run_js_async( - 'window.getSelection().anchorNode.parentNode.click()') - else: - selection = widget.caret.selection(html=True) - try: - selected_element = xml.etree.ElementTree.fromstring( - '{}'.format(selection)).find('a') - except xml.etree.ElementTree.ParseError: - raise cmdexc.CommandError('Could not parse selected element!') - - if selected_element is not None: - try: - url = selected_element.attrib['href'] - except KeyError: - raise cmdexc.CommandError('Anchor element without href!') - url = self._current_url().resolved(QUrl(url)) - self._open(url, tab) + try: + self._current_widget().caret.follow_selected(tab=tab) + except tabmod.WebTabError as e: + raise cmdexc.CommandError(str(e)) @cmdutils.register(instance='command-dispatcher', name='inspector', scope='window') diff --git a/qutebrowser/browser/tab.py b/qutebrowser/browser/tab.py index 004d7ae77..d6d16a391 100644 --- a/qutebrowser/browser/tab.py +++ b/qutebrowser/browser/tab.py @@ -32,6 +32,10 @@ from qutebrowser.utils import utils, objreg, usertypes tab_id_gen = itertools.count(0) +class WebTabError(Exception): + + """Base class for various errors.""" + class WrapperLayout(QLayout): @@ -188,8 +192,9 @@ class AbstractCaret(QObject): """Attribute of AbstractTab for caret browsing.""" - def __init__(self, win_id, parent=None): + def __init__(self, win_id, tab, parent=None): super().__init__(parent) + self._tab = tab self._win_id = win_id self._widget = None self.selection_enabled = False @@ -261,6 +266,9 @@ class AbstractCaret(QObject): def selection(self, html=False): raise NotImplementedError + def follow_selected(self, tab=False): + raise NotImplementedError + class AbstractScroller(QObject): @@ -398,7 +406,7 @@ class AbstractTab(QWidget): super().__init__(parent) # self.history = AbstractHistory(self) # self.scroll = AbstractScroller(parent=self) - # self.caret = AbstractCaret(win_id=win_id, parent=self) + # self.caret = AbstractCaret(win_id=win_id, tab=self, parent=self) # self.zoom = AbstractZoom(win_id=win_id) # self.search = AbstractSearch(parent=self) self._layout = None @@ -462,10 +470,6 @@ class AbstractTab(QWidget): def icon(self): raise NotImplementedError - def set_open_target(self, target): - """Select where the next navigation request should open.""" - raise NotImplementedError - def __repr__(self): url = utils.elide(self.cur_url.toDisplayString(QUrl.EncodeUnicode), 100) diff --git a/qutebrowser/browser/webengine/webenginetab.py b/qutebrowser/browser/webengine/webenginetab.py index b942c6038..0d9a02895 100644 --- a/qutebrowser/browser/webengine/webenginetab.py +++ b/qutebrowser/browser/webengine/webenginetab.py @@ -102,7 +102,7 @@ class WebEngineViewTab(tab.AbstractTab): widget = QWebEngineView() self.history = WebEngineHistory(self) self.scroll = WebEngineScroller() - self.caret = WebEngineCaret(win_id=win_id, parent=self) + self.caret = WebEngineCaret(win_id=win_id, tab=self, parent=self) self.zoom = WebEngineZoom(win_id=win_id, parent=self) self.search = WebEngineSearch(parent=self) self._set_widget(widget) @@ -155,9 +155,6 @@ class WebEngineViewTab(tab.AbstractTab): def icon(self): return self._widget.icon() - def set_open_target(self, target): - raise NotImplementedError - def _connect_signals(self): view = self._widget page = view.page() diff --git a/qutebrowser/browser/webkit/webkittab.py b/qutebrowser/browser/webkit/webkittab.py index 4e8ec0802..3e50a04a5 100644 --- a/qutebrowser/browser/webkit/webkittab.py +++ b/qutebrowser/browser/webkit/webkittab.py @@ -20,8 +20,9 @@ """Wrapper over our (QtWebKit) WebView.""" import sys +import xml.etree.ElementTree -from PyQt5.QtCore import pyqtSlot, Qt, QEvent +from PyQt5.QtCore import pyqtSlot, Qt, QEvent, QUrl from PyQt5.QtGui import QKeyEvent from PyQt5.QtWebKitWidgets import QWebPage from PyQt5.QtWebKit import QWebSettings @@ -260,6 +261,32 @@ class WebViewCaret(tab.AbstractCaret): return self._widget.selectedHtml() return self._widget.selectedText() + def follow_selected(self, *, tab=False): + if not self.has_selection(): + return + if QWebSettings.globalSettings().testAttribute( + QWebSettings.JavascriptEnabled): + if tab: + self._widget.page().open_target = usertypes.ClickTarget.tab + self._tab.run_js_async( + 'window.getSelection().anchorNode.parentNode.click()') + else: + selection = self.selection(html=True) + try: + selected_element = xml.etree.ElementTree.fromstring( + '{}'.format(selection)).find('a') + except xml.etree.ElementTree.ParseError: + raise tab.WebTabError('Could not parse selected element!') + + if selected_element is not None: + try: + url = selected_element.attrib['href'] + except KeyError: + raise tab.WebTabError('Anchor element without href!') + url = self._tab.cur_url.resolved(QUrl(url)) + # FIXME(refactoring) does this open in a new tab? + self._tab.openurl(url) + class WebViewZoom(tab.AbstractZoom): @@ -411,7 +438,7 @@ class WebViewTab(tab.AbstractTab): widget = webview.WebView(win_id, self.tab_id, tab=self) self.history = WebViewHistory(self) self.scroll = WebViewScroller(parent=self) - self.caret = WebViewCaret(win_id=win_id, parent=self) + self.caret = WebViewCaret(win_id=win_id, tab=self, parent=self) self.zoom = WebViewZoom(win_id=win_id, parent=self) self.search = WebViewSearch(parent=self) self._set_widget(widget) @@ -464,9 +491,6 @@ class WebViewTab(tab.AbstractTab): def title(self): return self._widget.title() - def set_open_target(self, target): - self._widget.page().open_target = target - def _connect_signals(self): view = self._widget page = view.page()