diff --git a/qutebrowser/browser/curcommand.py b/qutebrowser/browser/curcommand.py
index a0027aa94..e7d354f05 100644
--- a/qutebrowser/browser/curcommand.py
+++ b/qutebrowser/browser/curcommand.py
@@ -77,6 +77,15 @@ class CurCommandDispatcher(QObject):
return
frame.setScrollBarValue(orientation, int(m * perc / 100))
+ def _prevnext(self, prev, newtab):
+ """Inner logic for {tab,}{prev,next}page."""
+ widget = self._tabs.currentWidget()
+ frame = widget.page_.currentFrame()
+ if frame is None:
+ message.error("No frame focused!")
+ return
+ widget.hintmanager.follow_prevnext(frame, prev, newtab)
+
@cmdutils.register(instance='mainwindow.tabs.cur', name='open', maxsplit=0)
def openurl(self, url, count=None):
"""Open an url in the current/[count]th tab.
@@ -99,6 +108,19 @@ class CurCommandDispatcher(QObject):
else:
tab.openurl(url)
+ @pyqtSlot('QUrl', bool)
+ def openurl_slot(self, url, newtab):
+ """Open an URL, used as a slot.
+
+ Args:
+ url: The URL to open.
+ newtab: True to open URL in a new tab, False otherwise.
+ """
+ if newtab:
+ self._tabs.tabopen(url)
+ else:
+ self._tabs.currentWidget().openurl(url)
+
@cmdutils.register(instance='mainwindow.tabs.cur', name='reload')
def reloadpage(self, count=None):
"""Reload the current/[count]th tab.
@@ -223,24 +245,24 @@ class CurCommandDispatcher(QObject):
self._tabs.currentWidget().hintmanager.fire(keystr)
@cmdutils.register(instance='mainwindow.tabs.cur')
- def prev_page(self):
- """Click on a "previous" link."""
- widget = self._tabs.currentWidget()
- frame = widget.page_.currentFrame()
- if frame is None:
- message.error("No frame focused!")
- return
- widget.hintmanager.click_prevnext(frame, prev=True)
+ def prevpage(self):
+ """Open a "previous" link."""
+ self._prevnext(prev=True, newtab=False)
@cmdutils.register(instance='mainwindow.tabs.cur')
- def next_page(self):
- """Click on a "next" link."""
- widget = self._tabs.currentWidget()
- frame = widget.page_.currentFrame()
- if frame is None:
- message.error("No frame focused!")
- return
- widget.hintmanager.click_prevnext(frame, prev=False)
+ def nextpage(self):
+ """Open a "next" link."""
+ self._prevnext(prev=False, newtab=False)
+
+ @cmdutils.register(instance='mainwindow.tabs.cur')
+ def tabprevpage(self):
+ """Open a "previous" link in a new tab."""
+ self._prevnext(prev=True, newtab=True)
+
+ @cmdutils.register(instance='mainwindow.tabs.cur')
+ def tabnextpage(self):
+ """Open a "next" link in a new tab."""
+ self._prevnext(prev=False, newtab=True)
@pyqtSlot(str, int)
def search(self, text, flags):
diff --git a/qutebrowser/browser/hints.py b/qutebrowser/browser/hints.py
index 4ee0ab103..0fdb8081e 100644
--- a/qutebrowser/browser/hints.py
+++ b/qutebrowser/browser/hints.py
@@ -59,8 +59,8 @@ class HintManager(QObject):
mouse_event: Mouse event to be posted in the web view.
arg: A QMouseEvent
openurl: Open a new url
- arg 0: URL to open as a string.
- arg 1: true if it should be opened in a new tab, else false.
+ arg 0: URL to open as QUrl.
+ arg 1: True if it should be opened in a new tab, else False.
set_open_target: Set a new target to open the links in.
"""
@@ -79,6 +79,7 @@ class HintManager(QObject):
hint_strings_updated = pyqtSignal(list)
mouse_event = pyqtSignal('QMouseEvent')
+ openurl = pyqtSignal('QUrl', bool)
set_open_target = pyqtSignal(str)
def __init__(self, parent=None):
@@ -278,26 +279,44 @@ class HintManager(QObject):
link = self._baseurl.resolved(link)
return link
- def click_prevnext(self, frame, prev=False):
- """Click a "previous"/"next" element on the page."""
+ def _find_prevnext(self, frame, prev=False):
+ """Find a prev/next element in frame."""
# First check for
elems = frame.findAllElements(webelem.SELECTORS['prevnext_rel'])
rel_values = ['prev', 'previous'] if prev else ['next']
for e in elems:
if e.attribute('rel') in rel_values:
- self._click(e, 'normal', frame)
- return
+ return e
# Then check for regular links
elems = frame.findAllElements(webelem.SELECTORS['prevnext'])
option = 'prev-regexes' if prev else 'next-regexes'
- if elems:
- for regex in config.get('hints', option):
- for e in elems:
- if regex.match(e.toPlainText()):
- self._click(e, 'normal', frame)
- return
- message.error("No {} links found!".format("prev" if prev
- else "forward"))
+ if not elems:
+ return None
+ for regex in config.get('hints', option):
+ for e in elems:
+ if regex.match(e.toPlainText()):
+ return e
+ return None
+
+ def follow_prevnext(self, frame, prev=False, newtab=False):
+ """Click a "previous"/"next" element on the page.
+
+ Args:
+ frame: The frame where the element is in.
+ prev: True to open a "previous" link, False to open a "next" link.
+ newtab: True to open in a new tab, False for the current tab.
+ """
+ elem = self._find_prevnext(frame, prev)
+ if elem is None:
+ message.error("No {} links found!".format("prev" if prev
+ else "forward"))
+ return
+ link = self._resolve_link(elem)
+ if link is None:
+ message.error("No {} links found!".format("prev" if prev
+ else "forward"))
+ return
+ self.openurl.emit(link, newtab)
def start(self, frame, baseurl, mode='all', target='normal'):
diff --git a/qutebrowser/config/configdata.py b/qutebrowser/config/configdata.py
index bbcee95c5..2ad484611 100644
--- a/qutebrowser/config/configdata.py
+++ b/qutebrowser/config/configdata.py
@@ -469,8 +469,10 @@ DATA = OrderedDict([
('PP', 'tabpaste sel'),
('-', 'zoomout'),
('+', 'zoomin'),
- ('[[', 'prev_page'),
- (']]', 'next_page'),
+ ('[[', 'prevpage'),
+ (']]', 'nextpage'),
+ ('{{', 'tabprevpage'),
+ ('}}', 'tabnextpage'),
('', 'enter_mode passthrough'),
('', 'quit'),
('', 'undo'),
diff --git a/qutebrowser/widgets/_tabbedbrowser.py b/qutebrowser/widgets/_tabbedbrowser.py
index b2101c025..008877fbc 100644
--- a/qutebrowser/widgets/_tabbedbrowser.py
+++ b/qutebrowser/widgets/_tabbedbrowser.py
@@ -136,6 +136,7 @@ class TabbedBrowser(TabWidget):
tab.urlChanged.connect(self._filter.create(self.cur_url_changed))
# hintmanager
tab.hintmanager.hint_strings_updated.connect(self.hint_strings_updated)
+ tab.hintmanager.openurl.connect(self.cur.openurl_slot)
# misc
tab.titleChanged.connect(self.on_title_changed)
tab.open_tab.connect(self.tabopen)