More window support.

This commit is contained in:
Florian Bruhin 2014-10-06 17:58:40 +02:00
parent 2cd4642ece
commit 6324751af6
5 changed files with 86 additions and 43 deletions

View File

@ -28,7 +28,7 @@ It was inspired by other browsers/addons like dwb and Vimperator/Pentadactyl.
Commands to execute on startup. Commands to execute on startup.
*'URL'*:: *'URL'*::
URLs to open on startup. URLs to open on startup (empty as a window separator).
=== optional arguments === optional arguments
*-h*, *--help*:: *-h*, *--help*::

View File

@ -63,10 +63,19 @@ class CommandDispatcher:
def __repr__(self): def __repr__(self):
return utils.get_repr(self) return utils.get_repr(self)
def _tabbed_browser(self): def _tabbed_browser(self, window=False):
"""Convienence method to get the right tabbed-browser.""" """Convienence method to get the right tabbed-browser.
return objreg.get('tabbed-browser', scope='window',
window=self._win_id) Args:
window: If True, open a new window.
"""
if window:
# We have to import this here to avoid a circular import.
from qutebrowser.widgets import mainwindow
win_id = mainwindow.create_window(True)
else:
win_id = self._win_id
return objreg.get('tabbed-browser', scope='window', window=win_id)
def _count(self): def _count(self):
"""Convenience method to get the widget count.""" """Convenience method to get the widget count."""
@ -104,11 +113,7 @@ class CommandDispatcher:
if sum(1 for e in (tab, background, window) if e) > 1: if sum(1 for e in (tab, background, window) if e) > 1:
raise cmdexc.CommandError("Only one of -t/-b/-w can be given!") raise cmdexc.CommandError("Only one of -t/-b/-w can be given!")
elif window: elif window:
# We have to import this here to avoid a circular import. tabbed_browser = self._tabbed_browser(window=True)
from qutebrowser.widgets import mainwindow
win_id = mainwindow.create_window(True)
tabbed_browser = objreg.get('tabbed-browser', scope='window',
window=win_id)
tabbed_browser.tabopen(url) tabbed_browser.tabopen(url)
elif tab: elif tab:
tabbed_browser.tabopen(url, background=False, explicit=True) tabbed_browser.tabopen(url, background=False, explicit=True)
@ -302,26 +307,29 @@ class CommandDispatcher:
diag.open(lambda: tab.print(diag.printer())) diag.open(lambda: tab.print(diag.printer()))
@cmdutils.register(instance='command-dispatcher', scope='window') @cmdutils.register(instance='command-dispatcher', scope='window')
def tab_clone(self, bg=False): def tab_clone(self, bg=False, window=False):
"""Duplicate the current tab. """Duplicate the current tab.
Args: Args:
bg: Open in a background tab. bg: Open in a background tab.
window: Open in a new window.
Return: Return:
The new QWebView. The new QWebView.
""" """
if bg and window:
raise cmdexc.CommandError("Only one of -b/-w can be given!")
curtab = self._current_widget() curtab = self._current_widget()
tabbed_browser = self._tabbed_browser() tabbed_browser = self._tabbed_browser(window)
newtab = tabbed_browser.tabopen(background=bg, explicit=True) newtab = tabbed_browser.tabopen(background=bg, explicit=True)
history = qtutils.serialize(curtab.history()) history = qtutils.serialize(curtab.history())
qtutils.deserialize(history, newtab.history()) qtutils.deserialize(history, newtab.history())
return newtab return newtab
def _back_forward(self, tab, bg, count, forward): def _back_forward(self, tab, bg, window, count, forward):
"""Helper function for :back/:forward.""" """Helper function for :back/:forward."""
if tab or bg: if tab or bg or window:
widget = self.tab_clone(bg) widget = self.tab_clone(bg, window)
else: else:
widget = self._current_widget() widget = self._current_widget()
for _ in range(count): for _ in range(count):
@ -331,34 +339,38 @@ class CommandDispatcher:
widget.go_back() widget.go_back()
@cmdutils.register(instance='command-dispatcher', scope='window') @cmdutils.register(instance='command-dispatcher', scope='window')
def back(self, tab=False, bg=False, count=1): def back(self, tab=False, bg=False, window=False, count=1):
"""Go back in the history of the current tab. """Go back in the history of the current tab.
Args: Args:
tab: Go back in a new tab. tab: Go back in a new tab.
bg: Go back in a background tab. bg: Go back in a background tab.
window: Go back in a new window.
count: How many pages to go back. count: How many pages to go back.
""" """
self._back_forward(tab, bg, count, forward=False) self._back_forward(tab, bg, window, count, forward=False)
@cmdutils.register(instance='command-dispatcher', scope='window') @cmdutils.register(instance='command-dispatcher', scope='window')
def forward(self, tab=False, bg=False, count=1): def forward(self, tab=False, bg=False, window=False, count=1):
"""Go forward in the history of the current tab. """Go forward in the history of the current tab.
Args: Args:
tab: Go forward in a new tab. tab: Go forward in a new tab.
bg: Go back in a background tab. bg: Go forward in a background tab.
window: Go forward in a new window.
count: How many pages to go forward. count: How many pages to go forward.
""" """
self._back_forward(tab, bg, count, forward=True) self._back_forward(tab, bg, window, count, forward=True)
def _navigate_incdec(self, url, tab, incdec): def _navigate_incdec(self, url, incdec, tab, background, window):
"""Helper method for :navigate when `where' is increment/decrement. """Helper method for :navigate when `where' is increment/decrement.
Args: Args:
url: The current url. url: The current url.
tab: Whether to open the link in a new tab.
incdec: Either 'increment' or 'decrement'. incdec: Either 'increment' or 'decrement'.
tab: Whether to open the link in a new tab.
background: Open the link in a new background tab.
window: Open the link in a new window.
""" """
encoded = bytes(url.toEncoded()).decode('ascii') encoded = bytes(url.toEncoded()).decode('ascii')
# Get the last number in a string # Get the last number in a string
@ -383,25 +395,27 @@ class CommandDispatcher:
raise ValueError("Invalid value {} for indec!".format(incdec)) raise ValueError("Invalid value {} for indec!".format(incdec))
urlstr = ''.join([pre, str(val), post]).encode('ascii') urlstr = ''.join([pre, str(val), post]).encode('ascii')
new_url = QUrl.fromEncoded(urlstr) new_url = QUrl.fromEncoded(urlstr)
self._open(new_url, tab, background=False, window=False) self._open(new_url, tab, background, window)
def _navigate_up(self, url, tab): def _navigate_up(self, url, tab, background, window):
"""Helper method for :navigate when `where' is up. """Helper method for :navigate when `where' is up.
Args: Args:
url: The current url. url: The current url.
tab: Whether to open the link in a new tab. tab: Whether to open the link in a new tab.
background: Open the link in a new background tab.
window: Open the link in a new window.
""" """
path = url.path() path = url.path()
if not path or path == '/': if not path or path == '/':
raise cmdexc.CommandError("Can't go up!") raise cmdexc.CommandError("Can't go up!")
new_path = posixpath.join(path, posixpath.pardir) new_path = posixpath.join(path, posixpath.pardir)
url.setPath(new_path) url.setPath(new_path)
self._open(url, tab, background=False, window=False) self._open(url, tab, background, window)
@cmdutils.register(instance='command-dispatcher', scope='window') @cmdutils.register(instance='command-dispatcher', scope='window')
def navigate(self, where: ('prev', 'next', 'up', 'increment', 'decrement'), def navigate(self, where: ('prev', 'next', 'up', 'increment', 'decrement'),
tab=False): tab=False, bg=False, window=False):
"""Open typical prev/next links or navigate using the URL path. """Open typical prev/next links or navigate using the URL path.
This tries to automatically click on typical _Previous Page_ or This tries to automatically click on typical _Previous Page_ or
@ -419,7 +433,11 @@ class CommandDispatcher:
- `decrement`: Decrement the last number in the URL. - `decrement`: Decrement the last number in the URL.
tab: Open in a new tab. tab: Open in a new tab.
bg: Open in a background tab.
window: Open in a new window.
""" """
if sum(1 for e in (tab, bg, window) if e) > 1:
raise cmdexc.CommandError("Only one of -t/-b/-w can be given!")
widget = self._current_widget() widget = self._current_widget()
frame = widget.page().currentFrame() frame = widget.page().currentFrame()
url = self._current_url() url = self._current_url()
@ -427,13 +445,15 @@ class CommandDispatcher:
raise cmdexc.CommandError("No frame focused!") raise cmdexc.CommandError("No frame focused!")
hintmanager = objreg.get('hintmanager', scope='tab') hintmanager = objreg.get('hintmanager', scope='tab')
if where == 'prev': if where == 'prev':
hintmanager.follow_prevnext(frame, url, prev=True, newtab=tab) hintmanager.follow_prevnext(frame, url, prev=True, tab=tab,
background=background, window=window)
elif where == 'next': elif where == 'next':
hintmanager.follow_prevnext(frame, url, prev=False, newtab=tab) hintmanager.follow_prevnext(frame, url, prev=False, tab=tab,
background=background, window=window)
elif where == 'up': elif where == 'up':
self._navigate_up(url, tab) self._navigate_up(url, tab, background, window)
elif where in ('decrement', 'increment'): elif where in ('decrement', 'increment'):
self._navigate_incdec(url, tab, where) self._navigate_incdec(url, where, tab, background, window)
else: else:
raise ValueError("Got called with invalid value {} for " raise ValueError("Got called with invalid value {} for "
"`where'.".format(where)) "`where'.".format(where))

View File

@ -37,7 +37,7 @@ from qutebrowser.utils import usertypes, log, qtutils, message, objreg
ElemTuple = collections.namedtuple('ElemTuple', ['elem', 'label']) ElemTuple = collections.namedtuple('ElemTuple', ['elem', 'label'])
Target = usertypes.enum('Target', ['normal', 'tab', 'tab_bg', 'yank', Target = usertypes.enum('Target', ['normal', 'tab', 'tab_bg', 'window', 'yank',
'yank_primary', 'fill', 'rapid', 'download', 'yank_primary', 'fill', 'rapid', 'download',
'userscript', 'spawn']) 'userscript', 'spawn'])
@ -58,7 +58,7 @@ class HintContext:
elems: A mapping from keystrings to (elem, label) namedtuples. elems: A mapping from keystrings to (elem, label) namedtuples.
baseurl: The URL of the current page. baseurl: The URL of the current page.
target: What to do with the opened links. target: What to do with the opened links.
normal/tab/tab_bg: Get passed to BrowserTab. normal/tab/tab_bg/window: Get passed to BrowserTab.
yank/yank_primary: Yank to clipboard/primary selection yank/yank_primary: Yank to clipboard/primary selection
fill: Fill commandline with link. fill: Fill commandline with link.
rapid: Rapid mode with background tabs rapid: Rapid mode with background tabs
@ -127,6 +127,7 @@ class HintManager(QObject):
Target.normal: "Follow hint...", Target.normal: "Follow hint...",
Target.tab: "Follow hint in new tab...", Target.tab: "Follow hint in new tab...",
Target.tab_bg: "Follow hint in background tab...", Target.tab_bg: "Follow hint in background tab...",
Target.window: "Follow hint in new window...",
Target.yank: "Yank hint to clipboard...", Target.yank: "Yank hint to clipboard...",
Target.yank_primary: "Yank hint to primary selection...", Target.yank_primary: "Yank hint to primary selection...",
Target.fill: "Set hint in commandline...", Target.fill: "Set hint in commandline...",
@ -500,14 +501,17 @@ class HintManager(QObject):
keyparser = keyparsers[usertypes.KeyMode.hint] keyparser = keyparsers[usertypes.KeyMode.hint]
keyparser.update_bindings(strings) keyparser.update_bindings(strings)
def follow_prevnext(self, frame, baseurl, prev=False, newtab=False): def follow_prevnext(self, frame, baseurl, prev=False, tab=False,
background=False, window=False):
"""Click a "previous"/"next" element on the page. """Click a "previous"/"next" element on the page.
Args: Args:
frame: The frame where the element is in. frame: The frame where the element is in.
baseurl: The base URL of the current tab. baseurl: The base URL of the current tab.
prev: True to open a "previous" link, False to open a "next" link. 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. tab: True to open in a new tab, False for the current tab.
background: True to open in a background tab.
window: True to open in a new window, False for the current one.
""" """
elem = self._find_prevnext(frame, prev) elem = self._find_prevnext(frame, prev)
if elem is None: if elem is None:
@ -518,13 +522,21 @@ class HintManager(QObject):
raise cmdexc.CommandError("No {} links found!".format( raise cmdexc.CommandError("No {} links found!".format(
"prev" if prev else "forward")) "prev" if prev else "forward"))
qtutils.ensure_valid(url) qtutils.ensure_valid(url)
if newtab: if window:
tabbed_browser = objreg.get('tabbed-browser', scope='window', # We have to import this here to avoid a circular import.
window=self._win_id) from qutebrowser.widgets import mainwindow
tabbed_browser.tabopen(url, background=False) win_id = mainwindow.create_window(True)
tab_id = 0
else: else:
webview = objreg.get('webview', scope='tab', window=self._win_id, win_id = self._win_id
tab=self._tab_id) tab_id = self._tab_id
if tab:
tabbed_browser = objreg.get('tabbed-browser', scope='window',
window=win_id)
tabbed_browser.tabopen(url, background=background)
else:
webview = objreg.get('webview', scope='tab', window=win_id,
tab=tab_id)
webview.openurl(url) webview.openurl(url)
@cmdutils.register(instance='hintmanager', scope='tab', name='hint') @cmdutils.register(instance='hintmanager', scope='tab', name='hint')
@ -544,6 +556,7 @@ class HintManager(QObject):
- `normal`: Open the link in the current tab. - `normal`: Open the link in the current tab.
- `tab`: Open the link in a new tab. - `tab`: Open the link in a new tab.
- `tab-bg`: Open the link in a new background tab. - `tab-bg`: Open the link in a new background tab.
- `window`: Open the link in a new window.
- `yank`: Yank the link to the clipboard. - `yank`: Yank the link to the clipboard.
- `yank-primary`: Yank the link to the primary selection. - `yank-primary`: Yank the link to the primary selection.
- `fill`: Fill the commandline with the command given as - `fill`: Fill the commandline with the command given as
@ -650,6 +663,7 @@ class HintManager(QObject):
Target.normal: self._click, Target.normal: self._click,
Target.tab: self._click, Target.tab: self._click,
Target.tab_bg: self._click, Target.tab_bg: self._click,
Target.window: self._click,
Target.rapid: self._click, Target.rapid: self._click,
# _download needs a QWebElement to get the frame. # _download needs a QWebElement to get the frame.
Target.download: self._download, Target.download: self._download,

View File

@ -302,11 +302,20 @@ class BrowserPage(QWebPage):
return False return False
tabbed_browser = objreg.get('tabbed-browser', scope='window', tabbed_browser = objreg.get('tabbed-browser', scope='window',
window=self._win_id) window=self._win_id)
if self.view().open_target == usertypes.ClickTarget.tab: open_target = self.view().open_target
if open_target == usertypes.ClickTarget.tab:
tabbed_browser.tabopen(url, False) tabbed_browser.tabopen(url, False)
return False return False
elif self.view().open_target == usertypes.ClickTarget.tab_bg: elif open_target == usertypes.ClickTarget.tab_bg:
tabbed_browser.tabopen(url, True) tabbed_browser.tabopen(url, True)
return False return False
elif open_target == usertypes.ClickTarget.window:
# We have to import this here to avoid a circular import.
from qutebrowser.widgets import mainwindow
win_id = mainwindow.create_window(True)
tabbed_browser = objreg.get('tabbed-browser', scope='window',
window=win_id)
tabbed_browser.openurl(url, False)
return False
else: else:
return True return True

View File

@ -228,7 +228,7 @@ PromptMode = enum('PromptMode', ['yesno', 'text', 'user_pwd', 'alert'])
# Where to open a clicked link. # Where to open a clicked link.
ClickTarget = enum('ClickTarget', ['normal', 'tab', 'tab_bg']) ClickTarget = enum('ClickTarget', ['normal', 'tab', 'tab_bg', 'window'])
# Key input modes # Key input modes