Clean up webview and move commands

This commit is contained in:
Florian Bruhin 2014-05-17 22:38:07 +02:00
parent d901fe69e6
commit c7cf0aaf9a
5 changed files with 310 additions and 306 deletions

3
TODO
View File

@ -25,9 +25,6 @@ Style
=====
- initialize completion models at some nicer place (not in widget)
- move curcommand stuff to other places (e.g. current widget, etc.)
maybe rename curcommand to commands or so?
also some curcommand stuff is in tabbedbrowser, etc.
- reorder config #2
- rework exception hierarchy for config (common base exception)

View File

@ -374,13 +374,13 @@ class QuteBrowser(QApplication):
cmd.got_search.connect(self.searchmanager.search)
cmd.got_search_rev.connect(self.searchmanager.search_rev)
cmd.returnPressed.connect(tabs.setFocus)
self.searchmanager.do_search.connect(tabs.cur.search)
self.searchmanager.do_search.connect(tabs.search)
kp['normal'].keystring_updated.connect(status.keystring.setText)
# hints
kp['hint'].fire_hint.connect(tabs.cur.fire_hint)
kp['hint'].filter_hints.connect(tabs.cur.filter_hints)
kp['hint'].keystring_updated.connect(tabs.cur.handle_hint_key)
kp['hint'].fire_hint.connect(tabs.fire_hint)
kp['hint'].filter_hints.connect(tabs.filter_hints)
kp['hint'].keystring_updated.connect(tabs.handle_hint_key)
tabs.hint_strings_updated.connect(kp['hint'].on_hint_strings_updated)
# messages
@ -555,7 +555,7 @@ class QuteBrowser(QApplication):
except Exception as e: # pylint: disable=broad-except
out = ': '.join([e.__class__.__name__, str(e)])
qutescheme.pyeval_output = out
self.mainwindow.tabs.cur.openurl('qute:pyeval')
self.mainwindow.tabs.cmd.openurl('qute:pyeval')
@cmdutils.register(instance='', hide=True)
def crash(self, typ='exception'):

View File

@ -24,7 +24,7 @@ from tempfile import mkstemp
from functools import partial
from PyQt5.QtWidgets import QApplication
from PyQt5.QtCore import pyqtSlot, Qt, QObject, QProcess, QPoint
from PyQt5.QtCore import Qt, QObject, QProcess, QPoint
from PyQt5.QtGui import QClipboard
from PyQt5.QtPrintSupport import QPrintDialog, QPrintPreviewDialog
@ -34,7 +34,7 @@ import qutebrowser.browser.hints as hints
import qutebrowser.utils.url as urlutils
import qutebrowser.utils.message as message
import qutebrowser.utils.webelem as webelem
import qutebrowser.utils.misc as utils
from qutebrowser.utils.misc import check_overflow
from qutebrowser.utils.misc import shell_escape
from qutebrowser.commands.exceptions import CommandError
@ -46,7 +46,7 @@ class CurCommandDispatcher(QObject):
Contains all commands which are related to the current tab.
We can't simply add these commands to BrowserTab directly and use
currentWidget() for TabbedBrowser.cur because at the time
currentWidget() for TabbedBrowser.cmd because at the time
cmdutils.register() decorators are run, currentWidget() will return None.
Attributes:
@ -76,7 +76,7 @@ class CurCommandDispatcher(QObject):
perc = int(count)
else:
perc = float(perc)
perc = utils.check_overflow(perc, 'int', fatal=False)
perc = check_overflow(perc, 'int', fatal=False)
frame = self._tabs.currentWidget().page_.currentFrame()
if orientation == Qt.Horizontal:
right = frame.contentsSize().width()
@ -100,7 +100,60 @@ class CurCommandDispatcher(QObject):
raise CommandError("No frame focused!")
widget.hintmanager.follow_prevnext(frame, widget.url(), prev, newtab)
@cmdutils.register(instance='mainwindow.tabs.cur', name='open',
def _tab_move_absolute(self, idx):
"""Get an index for moving a tab absolutely.
Args:
idx: The index to get, as passed as count.
"""
if idx is None:
return 0
elif idx == 0:
return self._tabs.count() - 1
else:
return idx - 1
def _tab_move_relative(self, direction, delta):
"""Get an index for moving a tab relatively.
Args:
direction: + or - for relative moving, None for absolute.
delta: Delta to the current tab.
"""
if delta is None:
raise ValueError
if direction == '-':
return self._tabs.currentIndex() - delta
elif direction == '+':
return self._tabs.currentIndex() + delta
def _editor_cleanup(self, oshandle, filename):
"""Clean up temporary file when the editor was closed."""
os.close(oshandle)
try:
os.remove(filename)
except PermissionError:
raise CommandError("Failed to delete tempfile...")
@cmdutils.register(instance='mainwindow.tabs.cmd')
def tab_close(self, count=None):
"""Close the current/[count]th tab.
Command handler for :tab-close.
Args:
count: The tab index to close, or None
Emit:
quit: If last tab was closed and last-close in config is set to
quit.
"""
tab = self._tabs.cntwidget(count)
if tab is None:
return
self._close_tab(tab)
@cmdutils.register(instance='mainwindow.tabs.cmd', name='open',
split=False)
def openurl(self, url, count=None):
"""Open a URL in the current/[count]th tab.
@ -123,20 +176,7 @@ class CurCommandDispatcher(QObject):
else:
tab.openurl(url)
@pyqtSlot('QUrl', bool)
def openurl_slot(self, url, newtab):
"""Open a 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, background=False)
else:
self._tabs.currentWidget().openurl(url)
@cmdutils.register(instance='mainwindow.tabs.cur', name='reload')
@cmdutils.register(instance='mainwindow.tabs.cmd', name='reload')
def reloadpage(self, count=None):
"""Reload the current/[count]th tab.
@ -149,7 +189,7 @@ class CurCommandDispatcher(QObject):
if tab is not None:
tab.reload()
@cmdutils.register(instance='mainwindow.tabs.cur')
@cmdutils.register(instance='mainwindow.tabs.cmd')
def stop(self, count=None):
"""Stop loading in the current/[count]th tab.
@ -162,7 +202,7 @@ class CurCommandDispatcher(QObject):
if tab is not None:
tab.stop()
@cmdutils.register(instance='mainwindow.tabs.cur')
@cmdutils.register(instance='mainwindow.tabs.cmd')
def print_preview(self, count=None):
"""Preview printing of the current/[count]th tab.
@ -177,7 +217,7 @@ class CurCommandDispatcher(QObject):
preview.paintRequested.connect(tab.print)
preview.exec_()
@cmdutils.register(instance='mainwindow.tabs.cur', name='print')
@cmdutils.register(instance='mainwindow.tabs.cmd', name='print')
def printpage(self, count=None):
"""Print the current/[count]th tab.
@ -194,7 +234,7 @@ class CurCommandDispatcher(QObject):
printdiag = QPrintDialog()
printdiag.open(lambda: tab.print(printdiag.printer()))
@cmdutils.register(instance='mainwindow.tabs.cur')
@cmdutils.register(instance='mainwindow.tabs.cmd')
def back(self, count=1):
"""Go back in the history of the current tab.
@ -206,7 +246,7 @@ class CurCommandDispatcher(QObject):
for _ in range(count):
self._tabs.currentWidget().go_back()
@cmdutils.register(instance='mainwindow.tabs.cur')
@cmdutils.register(instance='mainwindow.tabs.cmd')
def forward(self, count=1):
"""Go forward in the history of the current tab.
@ -218,7 +258,7 @@ class CurCommandDispatcher(QObject):
for _ in range(count):
self._tabs.currentWidget().go_forward()
@cmdutils.register(instance='mainwindow.tabs.cur')
@cmdutils.register(instance='mainwindow.tabs.cmd')
def hint(self, groupstr='all', targetstr='normal'):
"""Start hinting.
@ -242,57 +282,32 @@ class CurCommandDispatcher(QObject):
raise CommandError("Unknown hinting target {}!".format(targetstr))
widget.hintmanager.start(frame, widget.url(), group, target)
@cmdutils.register(instance='mainwindow.tabs.cur', hide=True)
@cmdutils.register(instance='mainwindow.tabs.cmd', hide=True)
def follow_hint(self):
"""Follow the currently selected hint."""
self._tabs.currentWidget().hintmanager.follow_hint()
@pyqtSlot(str)
def handle_hint_key(self, keystr):
"""Handle a new hint keypress."""
self._tabs.currentWidget().hintmanager.handle_partial_key(keystr)
@pyqtSlot(str)
def fire_hint(self, keystr):
"""Fire a completed hint."""
self._tabs.currentWidget().hintmanager.fire(keystr)
@pyqtSlot(str)
def filter_hints(self, filterstr):
"""Filter displayed hints."""
self._tabs.currentWidget().hintmanager.filter_hints(filterstr)
@cmdutils.register(instance='mainwindow.tabs.cur')
@cmdutils.register(instance='mainwindow.tabs.cmd')
def prev_page(self):
"""Open a "previous" link."""
self._prevnext(prev=True, newtab=False)
@cmdutils.register(instance='mainwindow.tabs.cur')
@cmdutils.register(instance='mainwindow.tabs.cmd')
def next_page(self):
"""Open a "next" link."""
self._prevnext(prev=False, newtab=False)
@cmdutils.register(instance='mainwindow.tabs.cur')
@cmdutils.register(instance='mainwindow.tabs.cmd')
def prev_page_tab(self):
"""Open a "previous" link in a new tab."""
self._prevnext(prev=True, newtab=True)
@cmdutils.register(instance='mainwindow.tabs.cur')
@cmdutils.register(instance='mainwindow.tabs.cmd')
def next_page_tab(self):
"""Open a "next" link in a new tab."""
self._prevnext(prev=False, newtab=True)
@pyqtSlot(str, int)
def search(self, text, flags):
"""Search for text in the current page.
Args:
text: The text to search for.
flags: The QWebPage::FindFlags.
"""
self._tabs.currentWidget().findText(text, flags)
@cmdutils.register(instance='mainwindow.tabs.cur', hide=True)
@cmdutils.register(instance='mainwindow.tabs.cmd', hide=True)
def scroll(self, dx, dy, count=1):
"""Scroll the current tab by count * dx/dy.
@ -309,7 +324,7 @@ class CurCommandDispatcher(QObject):
cmdutils.check_overflow(dy, 'int')
self._tabs.currentWidget().page_.currentFrame().scroll(dx, dy)
@cmdutils.register(instance='mainwindow.tabs.cur', name='scroll-perc-x',
@cmdutils.register(instance='mainwindow.tabs.cmd', name='scroll-perc-x',
hide=True)
def scroll_percent_x(self, perc=None, count=None):
"""Scroll the current tab to a specific percent of the page (horiz).
@ -322,7 +337,7 @@ class CurCommandDispatcher(QObject):
"""
self._scroll_percent(perc, count, Qt.Horizontal)
@cmdutils.register(instance='mainwindow.tabs.cur', name='scroll-perc-y',
@cmdutils.register(instance='mainwindow.tabs.cmd', name='scroll-perc-y',
hide=True)
def scroll_percent_y(self, perc=None, count=None):
"""Scroll the current tab to a specific percent of the page (vert).
@ -335,7 +350,7 @@ class CurCommandDispatcher(QObject):
"""
self._scroll_percent(perc, count, Qt.Vertical)
@cmdutils.register(instance='mainwindow.tabs.cur', hide=True)
@cmdutils.register(instance='mainwindow.tabs.cmd', hide=True)
def scroll_page(self, mx, my, count=1):
"""Scroll the frame page-wise.
@ -352,7 +367,7 @@ class CurCommandDispatcher(QObject):
cmdutils.check_overflow(dy, 'int')
frame.scroll(dx, dy)
@cmdutils.register(instance='mainwindow.tabs.cur')
@cmdutils.register(instance='mainwindow.tabs.cmd')
def yank(self, sel=False):
"""Yank the current URL to the clipboard or primary selection.
@ -368,7 +383,7 @@ class CurCommandDispatcher(QObject):
message.info("URL yanked to {}".format("primary selection" if sel
else "clipboard"))
@cmdutils.register(instance='mainwindow.tabs.cur')
@cmdutils.register(instance='mainwindow.tabs.cmd')
def yank_title(self, sel=False):
"""Yank the current title to the clipboard or primary selection.
@ -384,7 +399,7 @@ class CurCommandDispatcher(QObject):
message.info("Title yanked to {}".format("primary selection" if sel
else "clipboard"))
@cmdutils.register(instance='mainwindow.tabs.cur')
@cmdutils.register(instance='mainwindow.tabs.cmd')
def zoom_in(self, count=1):
"""Increase the zoom level for the current tab.
@ -394,7 +409,7 @@ class CurCommandDispatcher(QObject):
tab = self._tabs.currentWidget()
tab.zoom(count)
@cmdutils.register(instance='mainwindow.tabs.cur')
@cmdutils.register(instance='mainwindow.tabs.cmd')
def zoom_out(self, count=1):
"""Decrease the zoom level for the current tab.
@ -404,7 +419,7 @@ class CurCommandDispatcher(QObject):
tab = self._tabs.currentWidget()
tab.zoom(-count)
@cmdutils.register(instance='mainwindow.tabs.cur', name='zoom')
@cmdutils.register(instance='mainwindow.tabs.cmd', name='zoom')
def zoom_perc(self, zoom=None, count=None):
"""Set the zoom level for the current tab to [count] or 100 percent.
@ -418,7 +433,177 @@ class CurCommandDispatcher(QObject):
tab = self._tabs.currentWidget()
tab.zoom_perc(level)
@cmdutils.register(instance='mainwindow.tabs.cur', split=False)
@cmdutils.register(instance='mainwindow.tabs.cmd')
def tab_only(self):
"""Close all tabs except for the current one."""
for tab in self._tabs.widgets:
if tab is self._tabs.currentWidget():
continue
self._tabs.close_tab(tab)
@cmdutils.register(instance='mainwindow.tabs.cmd', split=False)
def open_tab(self, url):
"""Open a new tab with a given url."""
self._tabs.tabopen(url, background=False)
@cmdutils.register(instance='mainwindow.tabs.cmd', split=False)
def open_tab_bg(self, url):
"""Open a new tab in background."""
self._tabs.tabopen(url, background=True)
@cmdutils.register(instance='mainwindow.tabs.cmd', hide=True)
def open_tab_cur(self):
"""Set the statusbar to :tabopen and the current URL."""
url = urlutils.urlstring(self._tabs.currentWidget().url())
message.set_cmd_text(':open-tab ' + url)
@cmdutils.register(instance='mainwindow.tabs.cmd', hide=True)
def open_cur(self):
"""Set the statusbar to :open and the current URL."""
url = urlutils.urlstring(self._tabs.currentWidget().url())
message.set_cmd_text(':open ' + url)
@cmdutils.register(instance='mainwindow.tabs.cmd', hide=True)
def open_tab_bg_cur(self):
"""Set the statusbar to :tabopen-bg and the current URL."""
url = urlutils.urlstring(self._tabs.currentWidget().url())
message.set_cmd_text(':open-tab-bg ' + url)
@cmdutils.register(instance='mainwindow.tabs.cmd', name='undo')
def undo_close(self):
"""Re-open a closed tab (optionally skipping [count] tabs).
Command handler for :undo.
"""
if self._tabs.url_stack:
self.tabopen(self._tabs.url_stack.pop())
else:
raise CommandError("Nothing to undo!")
@cmdutils.register(instance='mainwindow.tabs.cmd', name='tab-prev')
def switch_prev(self, count=1):
"""Switch to the previous tab, or skip [count] tabs.
Command handler for :tab-prev.
Args:
count: How many tabs to switch back.
"""
newidx = self._tabs.currentIndex() - count
if newidx >= 0:
self._tabs.setCurrentIndex(newidx)
elif config.get('tabbar', 'wrap'):
self._tabs.setCurrentIndex(newidx % self._tabs.count())
else:
raise CommandError("First tab")
@cmdutils.register(instance='mainwindow.tabs.cmd', name='tab-next')
def switch_next(self, count=1):
"""Switch to the next tab, or skip [count] tabs.
Command handler for :tab-next.
Args:
count: How many tabs to switch forward.
"""
newidx = self._tabs.currentIndex() + count
if newidx < self._tabs.count():
self._tabs.setCurrentIndex(newidx)
elif config.get('tabbar', 'wrap'):
self._tabs.setCurrentIndex(newidx % self._tabs.count())
else:
raise CommandError("Last tab")
@cmdutils.register(instance='mainwindow.tabs.cmd', nargs=(0, 1))
def paste(self, sel=False, tab=False):
"""Open a page from the clipboard.
Command handler for :paste.
Args:
sel: True to use primary selection, False to use clipboard
tab: True to open in a new tab.
"""
clip = QApplication.clipboard()
mode = QClipboard.Selection if sel else QClipboard.Clipboard
url = clip.text(mode)
if not url:
raise CommandError("Clipboard is empty.")
logging.debug("Clipboard contained: '{}'".format(url))
if tab:
self._tabs.tabopen(url)
else:
self.openurl(url)
@cmdutils.register(instance='mainwindow.tabs.cmd')
def paste_tab(self, sel=False):
"""Open a page from the clipboard in a new tab.
Command handler for :paste.
Args:
sel: True to use primary selection, False to use clipboard
"""
self._tabs.paste(sel, True)
@cmdutils.register(instance='mainwindow.tabs.cmd')
def tab_focus(self, index=None, count=None):
"""Select the tab given as argument/[count].
Args:
index: The tab index to focus, starting with 1.
"""
try:
idx = cmdutils.arg_or_count(index, count, default=1,
countzero=self._tabs.count())
except ValueError as e:
raise CommandError(e)
cmdutils.check_overflow(idx + 1, 'int')
if 1 <= idx <= self._tabs.count():
self._tabs.setCurrentIndex(idx - 1)
else:
raise CommandError("There's no tab with index {}!".format(idx))
@cmdutils.register(instance='mainwindow.tabs.cmd')
def tab_move(self, direction=None, count=None):
"""Move the current tab.
Args:
direction: + or - for relative moving, None for absolute.
count: If moving absolutely: New position (or first).
If moving relatively: Offset.
"""
if direction is None:
new_idx = self._tab_move_absolute(count)
elif direction in '+-':
try:
new_idx = self._tab_move_relative(direction, count)
except ValueError:
raise CommandError("Count must be given for relative moving!")
else:
raise CommandError("Invalid direction '{}'!".format(direction))
if not 0 <= new_idx < self._tabs.count():
raise CommandError("Can't move tab to position {}!".format(
new_idx))
tab = self._tabs.currentWidget()
cur_idx = self._tabs.currentIndex()
icon = self._tabs.tabIcon(cur_idx)
label = self._tabs.tabText(cur_idx)
cmdutils.check_overflow(cur_idx, 'int')
cmdutils.check_overflow(new_idx, 'int')
self._tabs.removeTab(cur_idx)
self._tabs.insertTab(new_idx, tab, icon, label)
self._tabs.setCurrentIndex(new_idx)
@cmdutils.register(instance='mainwindow.tabs.cmd')
def tab_focus_last(self):
"""Select the tab which was last focused."""
idx = self._tabs.indexOf(self._tabs.last_focused)
if idx == -1:
raise CommandError("Last focused tab vanished!")
self._tabs.setCurrentIndex(idx)
@cmdutils.register(instance='mainwindow.tabs.cmd', split=False)
def spawn(self, cmd):
"""Spawn a command in a shell. {} gets replaced by the current URL.
@ -440,12 +625,12 @@ class CurCommandDispatcher(QObject):
logging.debug("Executing: {}".format(cmd))
subprocess.Popen(cmd, shell=True)
@cmdutils.register(instance='mainwindow.tabs.cur')
@cmdutils.register(instance='mainwindow.tabs.cmd')
def home(self):
"""Open main startpage in current tab."""
self.openurl(config.get('general', 'startpage')[0])
@cmdutils.register(instance='mainwindow.tabs.cur', modes=['insert'],
@cmdutils.register(instance='mainwindow.tabs.cmd', modes=['insert'],
name='open_editor', hide=True)
def editor(self):
"""Open an external editor with the current form field.
@ -474,14 +659,6 @@ class CurCommandDispatcher(QObject):
logging.debug("Calling '{}' with args {}".format(executable, args))
proc.start(executable, args)
def _editor_cleanup(self, oshandle, filename):
"""Clean up temporary file."""
os.close(oshandle)
try:
os.remove(filename)
except PermissionError:
raise CommandError("Failed to delete tempfile...")
def on_editor_closed(self, elem, oshandle, filename, exitcode,
exitstatus):
"""Write the editor text into the form field and clean up tempfile.

View File

@ -20,19 +20,16 @@
import logging
from functools import partial
from PyQt5.QtWidgets import QApplication, QSizePolicy
from PyQt5.QtWidgets import QSizePolicy
from PyQt5.QtCore import pyqtSignal, pyqtSlot, QSize
from PyQt5.QtGui import QClipboard
import qutebrowser.utils.url as urlutils
import qutebrowser.utils.message as message
import qutebrowser.config.config as config
import qutebrowser.commands.utils as cmdutils
from qutebrowser.widgets._tabwidget import TabWidget, EmptyTabIcon
from qutebrowser.widgets.webview import WebView
from qutebrowser.browser.signalfilter import SignalFilter
from qutebrowser.browser.curcommand import CurCommandDispatcher
from qutebrowser.commands.exceptions import CommandError
class TabbedBrowser(TabWidget):
@ -48,11 +45,10 @@ class TabbedBrowser(TabWidget):
emitted if the signal occured in the current tab.
Attributes:
_url_stack: Stack of URLs of closed tabs.
_tabs: A list of open tabs.
_filter: A SignalFilter instance.
cur: A CurCommandDispatcher instance to dispatch commands to the
current tab.
url_stack: Stack of URLs of closed tabs.
cmd: A TabCommandDispatcher instance.
last_focused: The tab which was focused last.
now_focused: The tab which is focused now.
@ -96,9 +92,9 @@ class TabbedBrowser(TabWidget):
self.currentChanged.connect(self.on_current_changed)
self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
self._tabs = []
self._url_stack = []
self.url_stack = []
self._filter = SignalFilter(self)
self.cur = CurCommandDispatcher(self)
self.cmd = CurCommandDispatcher(self)
self.last_focused = None
self.now_focused = None
# FIXME adjust this to font size
@ -151,14 +147,14 @@ class TabbedBrowser(TabWidget):
self._filter.create(self.cur_load_status_changed))
# hintmanager
tab.hintmanager.hint_strings_updated.connect(self.hint_strings_updated)
tab.hintmanager.openurl.connect(self.cur.openurl_slot)
tab.hintmanager.openurl.connect(self.cmd.openurl)
# misc
tab.titleChanged.connect(self.on_title_changed)
tab.iconChanged.connect(self.on_icon_changed)
tab.page().mainFrame().loadStarted.connect(partial(
self.on_load_started, tab))
def _close_tab(self, tab_or_idx):
def close_tab(self, tab_or_idx):
"""Close a tab with either index or tab given.
Args:
@ -180,7 +176,7 @@ class TabbedBrowser(TabWidget):
if self.count() > 1:
url = tab.url()
if not url.isEmpty():
self._url_stack.append(url)
self.url_stack.append(url)
self.removeTab(idx)
tab.shutdown(callback=partial(self._cb_tab_shutdown, tab))
elif last_close == 'quit':
@ -188,37 +184,23 @@ class TabbedBrowser(TabWidget):
elif last_close == 'blank':
tab.openurl('about:blank')
@pyqtSlot('QUrl', bool)
def openurl(self, url, newtab):
"""Open a 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.tabopen(url, background=False)
else:
self.currentWidget().openurl(url)
@pyqtSlot(int)
def on_tab_close_requested(self, idx):
"""Close a tab via an index."""
self._close_tab(idx)
def _tab_move_absolute(self, idx):
"""Get an index for moving a tab absolutely.
Args:
idx: The index to get, as passed as count.
"""
if idx is None:
return 0
elif idx == 0:
return self.count() - 1
else:
return idx - 1
def _tab_move_relative(self, direction, delta):
"""Get an index for moving a tab relatively.
Args:
direction: + or - for relative moving, None for absolute.
delta: Delta to the current tab.
"""
if delta is None:
raise ValueError
if direction == '-':
return self.currentIndex() - delta
elif direction == '+':
return self.currentIndex() + delta
self.close_tab(idx)
@pyqtSlot(str, bool)
def tabopen(self, url=None, background=None):
@ -287,193 +269,30 @@ class TabbedBrowser(TabWidget):
for tab in self.widgets:
tab.shutdown(callback=partial(self._cb_tab_shutdown, tab))
@cmdutils.register(instance='mainwindow.tabs', name='tab-close')
def tabclose(self, count=None):
"""Close the current/[count]th tab.
Command handler for :tab-close.
@pyqtSlot(str, int)
def search(self, text, flags):
"""Search for text in the current page.
Args:
count: The tab index to close, or None
Emit:
quit: If last tab was closed and last-close in config is set to
quit.
text: The text to search for.
flags: The QWebPage::FindFlags.
"""
tab = self.cntwidget(count)
if tab is None:
return
self._close_tab(tab)
self._tabs.currentWidget().findText(text, flags)
@cmdutils.register(instance='mainwindow.tabs')
def tab_only(self):
"""Close all tabs except for the current one."""
for tab in self.widgets:
if tab is self.currentWidget():
continue
self._close_tab(tab)
@pyqtSlot(str)
def handle_hint_key(self, keystr):
"""Handle a new hint keypress."""
self.currentWidget().hintmanager.handle_partial_key(keystr)
@cmdutils.register(instance='mainwindow.tabs', split=False)
def open_tab(self, url):
"""Open a new tab with a given url."""
self.tabopen(url, background=False)
@pyqtSlot(str)
def fire_hint(self, keystr):
"""Fire a completed hint."""
self.currentWidget().hintmanager.fire(keystr)
@cmdutils.register(instance='mainwindow.tabs', split=False)
def open_tab_bg(self, url):
"""Open a new tab in background."""
self.tabopen(url, background=True)
@cmdutils.register(instance='mainwindow.tabs', hide=True)
def open_tab_cur(self):
"""Set the statusbar to :tabopen and the current URL."""
url = urlutils.urlstring(self.currentWidget().url())
message.set_cmd_text(':open-tab ' + url)
@cmdutils.register(instance='mainwindow.tabs', hide=True)
def open_cur(self):
"""Set the statusbar to :open and the current URL."""
url = urlutils.urlstring(self.currentWidget().url())
message.set_cmd_text(':open ' + url)
@cmdutils.register(instance='mainwindow.tabs', hide=True)
def open_tab_bg_cur(self):
"""Set the statusbar to :tabopen-bg and the current URL."""
url = urlutils.urlstring(self.currentWidget().url())
message.set_cmd_text(':open-tab-bg ' + url)
@cmdutils.register(instance='mainwindow.tabs', name='undo')
def undo_close(self):
"""Re-open a closed tab (optionally skipping [count] tabs).
Command handler for :undo.
"""
if self._url_stack:
self.tabopen(self._url_stack.pop())
else:
raise CommandError("Nothing to undo!")
@cmdutils.register(instance='mainwindow.tabs', name='tab-prev')
def switch_prev(self, count=1):
"""Switch to the previous tab, or skip [count] tabs.
Command handler for :tab-prev.
Args:
count: How many tabs to switch back.
"""
newidx = self.currentIndex() - count
if newidx >= 0:
self.setCurrentIndex(newidx)
elif config.get('tabbar', 'wrap'):
self.setCurrentIndex(newidx % self.count())
else:
raise CommandError("First tab")
@cmdutils.register(instance='mainwindow.tabs', name='tab-next')
def switch_next(self, count=1):
"""Switch to the next tab, or skip [count] tabs.
Command handler for :tab-next.
Args:
count: How many tabs to switch forward.
"""
newidx = self.currentIndex() + count
if newidx < self.count():
self.setCurrentIndex(newidx)
elif config.get('tabbar', 'wrap'):
self.setCurrentIndex(newidx % self.count())
else:
raise CommandError("Last tab")
@cmdutils.register(instance='mainwindow.tabs', nargs=(0, 1))
def paste(self, sel=False, tab=False):
"""Open a page from the clipboard.
Command handler for :paste.
Args:
sel: True to use primary selection, False to use clipboard
tab: True to open in a new tab.
"""
clip = QApplication.clipboard()
mode = QClipboard.Selection if sel else QClipboard.Clipboard
url = clip.text(mode)
if not url:
raise CommandError("Clipboard is empty.")
logging.debug("Clipboard contained: '{}'".format(url))
if tab:
self.tabopen(url)
else:
self.cur.openurl(url)
@cmdutils.register(instance='mainwindow.tabs')
def paste_tab(self, sel=False):
"""Open a page from the clipboard in a new tab.
Command handler for :paste.
Args:
sel: True to use primary selection, False to use clipboard
"""
self.paste(sel, True)
@cmdutils.register(instance='mainwindow.tabs')
def tab_focus(self, index=None, count=None):
"""Select the tab given as argument/[count].
Args:
index: The tab index to focus, starting with 1.
"""
try:
idx = cmdutils.arg_or_count(index, count, default=1,
countzero=self.count())
except ValueError as e:
raise CommandError(e)
cmdutils.check_overflow(idx + 1, 'int')
if 1 <= idx <= self.count():
self.setCurrentIndex(idx - 1)
else:
raise CommandError("There's no tab with index {}!".format(idx))
@cmdutils.register(instance='mainwindow.tabs')
def tab_move(self, direction=None, count=None):
"""Move the current tab.
Args:
direction: + or - for relative moving, None for absolute.
count: If moving absolutely: New position (or first).
If moving relatively: Offset.
"""
if direction is None:
new_idx = self._tab_move_absolute(count)
elif direction in '+-':
try:
new_idx = self._tab_move_relative(direction, count)
except ValueError:
raise CommandError("Count must be given for relative moving!")
else:
raise CommandError("Invalid direction '{}'!".format(direction))
if not 0 <= new_idx < self.count():
raise CommandError("Can't move tab to position {}!".format(
new_idx))
tab = self.currentWidget()
cur_idx = self.currentIndex()
icon = self.tabIcon(cur_idx)
label = self.tabText(cur_idx)
cmdutils.check_overflow(cur_idx, 'int')
cmdutils.check_overflow(new_idx, 'int')
self.removeTab(cur_idx)
self.insertTab(new_idx, tab, icon, label)
self.setCurrentIndex(new_idx)
@cmdutils.register(instance='mainwindow.tabs')
def tab_focus_last(self):
"""Select the tab which was last focused."""
idx = self.indexOf(self.last_focused)
if idx == -1:
raise CommandError("Last focused tab vanished!")
self.setCurrentIndex(idx)
@pyqtSlot(str)
def filter_hints(self, filterstr):
"""Filter displayed hints."""
self.currentWidget().hintmanager.filter_hints(filterstr)
@pyqtSlot(str, str)
def on_config_changed(self, section, option):
@ -513,6 +332,7 @@ class TabbedBrowser(TabWidget):
else:
logging.debug("ignoring title change")
@pyqtSlot(str)
def on_url_text_changed(self, url):
"""Set the new URL as title if there's no title yet."""

View File

@ -30,7 +30,7 @@ import qutebrowser.config.config as config
import qutebrowser.keyinput.modeman as modeman
import qutebrowser.utils.message as message
import qutebrowser.utils.webelem as webelem
import qutebrowser.utils.misc as utils
from qutebrowser.utils.misc import elide
from qutebrowser.browser.webpage import BrowserPage
from qutebrowser.browser.hints import HintManager
from qutebrowser.utils.usertypes import NeighborList, enum
@ -118,7 +118,7 @@ class WebView(QWebView):
def __repr__(self):
return "WebView(url='{}')".format(
utils.elide(urlutils.urlstring(self.url()), 50))
elide(urlutils.urlstring(self.url()), 50))
@property
def load_status(self):
@ -320,6 +320,16 @@ class WebView(QWebView):
level = self._zoom.getitem(offset)
self.zoom_perc(level, fuzzyval=False)
@pyqtSlot(str, int)
def search(self, text, flags):
"""Search for text in the current page.
Args:
text: The text to search for.
flags: The QWebPage::FindFlags.
"""
self._tabs.currentWidget().findText(text, flags)
def go_back(self):
"""Go back a page in the history."""
if self.page_.history().canGoBack():