Don't depend on objreg for CommandDispatcher.

See #640.
This commit is contained in:
Florian Bruhin 2015-05-18 21:31:54 +02:00
parent 54eae77328
commit dd292b0781
3 changed files with 64 additions and 72 deletions

View File

@ -56,46 +56,40 @@ class CommandDispatcher:
Attributes: Attributes:
_editor: The ExternalEditor object. _editor: The ExternalEditor object.
_win_id: The window ID the CommandDispatcher is associated with. _win_id: The window ID the CommandDispatcher is associated with.
_tabbed_browser: The TabbedBrowser used.
""" """
def __init__(self, win_id): def __init__(self, win_id, tabbed_browser):
self._editor = None self._editor = None
self._win_id = win_id self._win_id = win_id
self._tabbed_browser = tabbed_browser
def __repr__(self): def __repr__(self):
return utils.get_repr(self) return utils.get_repr(self)
def _tabbed_browser(self, window=False): def _new_tabbed_browser(self):
"""Convienence method to get the right tabbed-browser. """Get a tabbed-browser from a new window."""
Args:
window: If True, open a new window.
"""
from qutebrowser.mainwindow import mainwindow from qutebrowser.mainwindow import mainwindow
if window: new_window = mainwindow.MainWindow()
new_window = mainwindow.MainWindow() new_window.show()
new_window.show() return new_window.tabbed_browser
win_id = new_window.win_id
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."""
return self._tabbed_browser().count() return self._tabbed_browser.count()
def _set_current_index(self, idx): def _set_current_index(self, idx):
"""Convenience method to set the current widget index.""" """Convenience method to set the current widget index."""
return self._tabbed_browser().setCurrentIndex(idx) return self._tabbed_browser.setCurrentIndex(idx)
def _current_index(self): def _current_index(self):
"""Convenience method to get the current widget index.""" """Convenience method to get the current widget index."""
return self._tabbed_browser().currentIndex() return self._tabbed_browser.currentIndex()
def _current_url(self): def _current_url(self):
"""Convenience method to get the current url.""" """Convenience method to get the current url."""
try: try:
return self._tabbed_browser().current_url() return self._tabbed_browser.current_url()
except qtutils.QtValueError as e: except qtutils.QtValueError as e:
msg = "Current URL is invalid" msg = "Current URL is invalid"
if e.reason: if e.reason:
@ -105,7 +99,7 @@ class CommandDispatcher:
def _current_widget(self): def _current_widget(self):
"""Get the currently active widget from a command.""" """Get the currently active widget from a command."""
widget = self._tabbed_browser().currentWidget() widget = self._tabbed_browser.currentWidget()
if widget is None: if widget is None:
raise cmdexc.CommandError("No WebView available yet!") raise cmdexc.CommandError("No WebView available yet!")
return widget return widget
@ -120,10 +114,10 @@ class CommandDispatcher:
window: Whether to open in a new window window: Whether to open in a new window
""" """
urlutils.raise_cmdexc_if_invalid(url) urlutils.raise_cmdexc_if_invalid(url)
tabbed_browser = self._tabbed_browser() tabbed_browser = self._tabbed_browser
cmdutils.check_exclusive((tab, background, window), 'tbw') cmdutils.check_exclusive((tab, background, window), 'tbw')
if window: if window:
tabbed_browser = self._tabbed_browser(window=True) tabbed_browser = self._new_tabbed_browser()
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)
@ -144,12 +138,11 @@ class CommandDispatcher:
The widget with the given tab ID if count is given. The widget with the given tab ID if count is given.
None if no widget was found. None if no widget was found.
""" """
tabbed_browser = self._tabbed_browser()
if count is None: if count is None:
return tabbed_browser.currentWidget() return self._tabbed_browser.currentWidget()
elif 1 <= count <= self._count(): elif 1 <= count <= self._count():
cmdutils.check_overflow(count + 1, 'int') cmdutils.check_overflow(count + 1, 'int')
return tabbed_browser.widget(count - 1) return self._tabbed_browser.widget(count - 1)
else: else:
return None return None
@ -213,7 +206,7 @@ class CommandDispatcher:
window=self._win_id) window=self._win_id)
except KeyError: except KeyError:
raise cmdexc.CommandError("No last focused tab!") raise cmdexc.CommandError("No last focused tab!")
idx = self._tabbed_browser().indexOf(tab) idx = self._tabbed_browser.indexOf(tab)
if idx == -1: if idx == -1:
raise cmdexc.CommandError("Last focused tab vanished!") raise cmdexc.CommandError("Last focused tab vanished!")
self._set_current_index(idx) self._set_current_index(idx)
@ -271,16 +264,15 @@ class CommandDispatcher:
tab = self._cntwidget(count) tab = self._cntwidget(count)
if tab is None: if tab is None:
return return
tabbed_browser = self._tabbed_browser() tabbar = self._tabbed_browser.tabBar()
tabbar = tabbed_browser.tabBar()
selection_override = self._get_selection_override(left, right, selection_override = self._get_selection_override(left, right,
opposite) opposite)
if selection_override is None: if selection_override is None:
tabbed_browser.close_tab(tab) self._tabbed_browser.close_tab(tab)
else: else:
old_selection_behavior = tabbar.selectionBehaviorOnRemove() old_selection_behavior = tabbar.selectionBehaviorOnRemove()
tabbar.setSelectionBehaviorOnRemove(selection_override) tabbar.setSelectionBehaviorOnRemove(selection_override)
tabbed_browser.close_tab(tab) self._tabbed_browser.close_tab(tab)
tabbar.setSelectionBehaviorOnRemove(old_selection_behavior) tabbar.setSelectionBehaviorOnRemove(old_selection_behavior)
@cmdutils.register(instance='command-dispatcher', name='open', @cmdutils.register(instance='command-dispatcher', name='open',
@ -315,7 +307,7 @@ class CommandDispatcher:
if count is None: if count is None:
# We want to open a URL in the current tab, but none exists # We want to open a URL in the current tab, but none exists
# yet. # yet.
self._tabbed_browser().tabopen(url) self._tabbed_browser.tabopen(url)
else: else:
# Explicit count with a tab that doesn't exist. # Explicit count with a tab that doesn't exist.
return return
@ -391,12 +383,14 @@ class CommandDispatcher:
""" """
if bg and window: if bg and window:
raise cmdexc.CommandError("Only one of -b/-w can be given!") raise cmdexc.CommandError("Only one of -b/-w can be given!")
cur_tabbed_browser = self._tabbed_browser()
curtab = self._current_widget() curtab = self._current_widget()
cur_title = cur_tabbed_browser.page_title(self._current_index()) cur_title = self._tabbed_browser.page_title(self._current_index())
# The new tab could be in a new tabbed_browser (e.g. because of # The new tab could be in a new tabbed_browser (e.g. because of
# tabs-are-windows being set) # tabs-are-windows being set)
new_tabbed_browser = self._tabbed_browser(window) if window:
new_tabbed_browser = self._new_tabbed_browser()
else:
new_tabbed_browser = self._tabbed_browser
newtab = new_tabbed_browser.tabopen(background=bg, explicit=True) newtab = new_tabbed_browser.tabopen(background=bg, explicit=True)
new_tabbed_browser = objreg.get('tabbed-browser', scope='window', new_tabbed_browser = objreg.get('tabbed-browser', scope='window',
window=newtab.win_id) window=newtab.win_id)
@ -414,9 +408,8 @@ class CommandDispatcher:
"""Detach the current tab to its own window.""" """Detach the current tab to its own window."""
url = self._current_url() url = self._current_url()
self._open(url, window=True) self._open(url, window=True)
tabbed_browser = self._tabbed_browser()
cur_widget = self._current_widget() cur_widget = self._current_widget()
tabbed_browser.close_tab(cur_widget) self._tabbed_browser.close_tab(cur_widget)
def _back_forward(self, tab, bg, window, count, forward): def _back_forward(self, tab, bg, window, count, forward):
"""Helper function for :back/:forward.""" """Helper function for :back/:forward."""
@ -686,7 +679,7 @@ class CommandDispatcher:
""" """
clipboard = QApplication.clipboard() clipboard = QApplication.clipboard()
if title: if title:
s = self._tabbed_browser().page_title(self._current_index()) s = self._tabbed_browser.page_title(self._current_index())
else: else:
s = self._current_url().toString( s = self._current_url().toString(
QUrl.FullyEncoded | QUrl.RemovePassword) QUrl.FullyEncoded | QUrl.RemovePassword)
@ -752,22 +745,21 @@ class CommandDispatcher:
right: Keep tabs to the right of the current. right: Keep tabs to the right of the current.
""" """
cmdutils.check_exclusive((left, right), 'lr') cmdutils.check_exclusive((left, right), 'lr')
tabbed_browser = self._tabbed_browser() cur_idx = self._tabbed_browser.currentIndex()
cur_idx = tabbed_browser.currentIndex()
assert cur_idx != -1 assert cur_idx != -1
for i, tab in enumerate(tabbed_browser.widgets()): for i, tab in enumerate(self._tabbed_browser.widgets()):
if (i == cur_idx or (left and i < cur_idx) or if (i == cur_idx or (left and i < cur_idx) or
(right and i > cur_idx)): (right and i > cur_idx)):
continue continue
else: else:
tabbed_browser.close_tab(tab) self._tabbed_browser.close_tab(tab)
@cmdutils.register(instance='command-dispatcher', scope='window') @cmdutils.register(instance='command-dispatcher', scope='window')
def undo(self): def undo(self):
"""Re-open a closed tab (optionally skipping [count] closed tabs).""" """Re-open a closed tab (optionally skipping [count] closed tabs)."""
try: try:
self._tabbed_browser().undo() self._tabbed_browser.undo()
except IndexError: except IndexError:
raise cmdexc.CommandError("Nothing to undo!") raise cmdexc.CommandError("Nothing to undo!")
@ -880,20 +872,19 @@ class CommandDispatcher:
if not 0 <= new_idx < self._count(): if not 0 <= new_idx < self._count():
raise cmdexc.CommandError("Can't move tab to position {}!".format( raise cmdexc.CommandError("Can't move tab to position {}!".format(
new_idx)) new_idx))
tabbed_browser = self._tabbed_browser()
tab = self._current_widget() tab = self._current_widget()
cur_idx = self._current_index() cur_idx = self._current_index()
icon = tabbed_browser.tabIcon(cur_idx) icon = self._tabbed_browser.tabIcon(cur_idx)
label = tabbed_browser.page_title(cur_idx) label = self._tabbed_browser.page_title(cur_idx)
cmdutils.check_overflow(cur_idx, 'int') cmdutils.check_overflow(cur_idx, 'int')
cmdutils.check_overflow(new_idx, 'int') cmdutils.check_overflow(new_idx, 'int')
tabbed_browser.setUpdatesEnabled(False) self._tabbed_browser.setUpdatesEnabled(False)
try: try:
tabbed_browser.removeTab(cur_idx) self._tabbed_browser.removeTab(cur_idx)
tabbed_browser.insertTab(new_idx, tab, icon, label) self._tabbed_browser.insertTab(new_idx, tab, icon, label)
self._set_current_index(new_idx) self._set_current_index(new_idx)
finally: finally:
tabbed_browser.setUpdatesEnabled(True) self._tabbed_browser.setUpdatesEnabled(True)
@cmdutils.register(instance='command-dispatcher', scope='window', @cmdutils.register(instance='command-dispatcher', scope='window',
win_id='win_id') win_id='win_id')
@ -949,11 +940,10 @@ class CommandDispatcher:
} }
idx = self._current_index() idx = self._current_index()
tabbed_browser = self._tabbed_browser()
if idx != -1: if idx != -1:
env['QUTE_TITLE'] = tabbed_browser.page_title(idx) env['QUTE_TITLE'] = self._tabbed_browser.page_title(idx)
webview = tabbed_browser.currentWidget() webview = self._tabbed_browser.currentWidget()
if webview is None: if webview is None:
mainframe = None mainframe = None
else: else:
@ -963,7 +953,7 @@ class CommandDispatcher:
mainframe = webview.page().mainFrame() mainframe = webview.page().mainFrame()
try: try:
url = tabbed_browser.current_url() url = self._tabbed_browser.current_url()
except qtutils.QtValueError: except qtutils.QtValueError:
pass pass
else: else:
@ -1055,7 +1045,7 @@ class CommandDispatcher:
full=True, linenos='table') full=True, linenos='table')
highlighted = pygments.highlight(html, lexer, formatter) highlighted = pygments.highlight(html, lexer, formatter)
current_url = self._current_url() current_url = self._current_url()
tab = self._tabbed_browser().tabopen(explicit=True) tab = self._tabbed_browser.tabopen(explicit=True)
tab.setHtml(highlighted, current_url) tab.setHtml(highlighted, current_url)
tab.viewing_source = True tab.viewing_source = True
@ -1128,7 +1118,7 @@ class CommandDispatcher:
else: else:
text = elem.evaluateJavaScript('this.value') text = elem.evaluateJavaScript('this.value')
self._editor = editor.ExternalEditor( self._editor = editor.ExternalEditor(
self._win_id, self._tabbed_browser()) self._win_id, self._tabbed_browser)
self._editor.editing_finished.connect( self._editor.editing_finished.connect(
functools.partial(self.on_editing_finished, elem)) functools.partial(self.on_editing_finished, elem))
self._editor.edit(text) self._editor.edit(text)

View File

@ -22,6 +22,7 @@
import binascii import binascii
import base64 import base64
import itertools import itertools
import functools
from PyQt5.QtCore import pyqtSlot, QRect, QPoint, QTimer, Qt from PyQt5.QtCore import pyqtSlot, QRect, QPoint, QTimer, Qt
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QApplication from PyQt5.QtWidgets import QWidget, QVBoxLayout, QApplication
@ -33,7 +34,7 @@ from qutebrowser.mainwindow import tabbedbrowser
from qutebrowser.mainwindow.statusbar import bar from qutebrowser.mainwindow.statusbar import bar
from qutebrowser.completion import completionwidget from qutebrowser.completion import completionwidget
from qutebrowser.keyinput import modeman from qutebrowser.keyinput import modeman
from qutebrowser.browser import hints, downloads, downloadview from qutebrowser.browser import hints, downloads, downloadview, commands
win_id_gen = itertools.count(0) win_id_gen = itertools.count(0)
@ -89,8 +90,8 @@ class MainWindow(QWidget):
Attributes: Attributes:
status: The StatusBar widget. status: The StatusBar widget.
tabbed_browser: The TabbedBrowser widget.
_downloadview: The DownloadView widget. _downloadview: The DownloadView widget.
_tabbed_browser: The TabbedBrowser widget.
_vbox: The main QVBoxLayout. _vbox: The main QVBoxLayout.
_commandrunner: The main CommandRunner instance. _commandrunner: The main CommandRunner instance.
""" """
@ -138,9 +139,16 @@ class MainWindow(QWidget):
self._downloadview = downloadview.DownloadView(self.win_id) self._downloadview = downloadview.DownloadView(self.win_id)
self._tabbed_browser = tabbedbrowser.TabbedBrowser(self.win_id) self.tabbed_browser = tabbedbrowser.TabbedBrowser(self.win_id)
objreg.register('tabbed-browser', self._tabbed_browser, scope='window', objreg.register('tabbed-browser', self.tabbed_browser, scope='window',
window=self.win_id) window=self.win_id)
dispatcher = commands.CommandDispatcher(self.win_id,
self.tabbed_browser)
objreg.register('command-dispatcher', dispatcher, scope='window',
window=self.win_id)
self.tabbed_browser.destroyed.connect(
functools.partial(objreg.delete, 'command-dispatcher',
scope='window', window=self.win_id))
# We need to set an explicit parent for StatusBar because it does some # We need to set an explicit parent for StatusBar because it does some
# show/hide magic immediately which would mean it'd show up as a # show/hide magic immediately which would mean it'd show up as a
@ -185,15 +193,15 @@ class MainWindow(QWidget):
def _add_widgets(self): def _add_widgets(self):
"""Add or readd all widgets to the VBox.""" """Add or readd all widgets to the VBox."""
self._vbox.removeWidget(self._tabbed_browser) self._vbox.removeWidget(self.tabbed_browser)
self._vbox.removeWidget(self._downloadview) self._vbox.removeWidget(self._downloadview)
self._vbox.removeWidget(self.status) self._vbox.removeWidget(self.status)
position = config.get('ui', 'downloads-position') position = config.get('ui', 'downloads-position')
if position == 'north': if position == 'north':
self._vbox.addWidget(self._downloadview) self._vbox.addWidget(self._downloadview)
self._vbox.addWidget(self._tabbed_browser) self._vbox.addWidget(self.tabbed_browser)
elif position == 'south': elif position == 'south':
self._vbox.addWidget(self._tabbed_browser) self._vbox.addWidget(self.tabbed_browser)
self._vbox.addWidget(self._downloadview) self._vbox.addWidget(self._downloadview)
else: else:
raise ValueError("Invalid position {}!".format(position)) raise ValueError("Invalid position {}!".format(position))
@ -260,7 +268,7 @@ class MainWindow(QWidget):
prompter = self._get_object('prompter') prompter = self._get_object('prompter')
# misc # misc
self._tabbed_browser.close_window.connect(self.close) self.tabbed_browser.close_window.connect(self.close)
mode_manager.entered.connect(hints.on_mode_entered) mode_manager.entered.connect(hints.on_mode_entered)
# status bar # status bar
@ -381,12 +389,12 @@ class MainWindow(QWidget):
super().resizeEvent(e) super().resizeEvent(e)
self.resize_completion() self.resize_completion()
self._downloadview.updateGeometry() self._downloadview.updateGeometry()
self._tabbed_browser.tabBar().refresh() self.tabbed_browser.tabBar().refresh()
def closeEvent(self, e): def closeEvent(self, e):
"""Override closeEvent to display a confirmation if needed.""" """Override closeEvent to display a confirmation if needed."""
confirm_quit = config.get('ui', 'confirm-quit') confirm_quit = config.get('ui', 'confirm-quit')
tab_count = self._tabbed_browser.count() tab_count = self.tabbed_browser.count()
download_manager = objreg.get('download-manager', scope='window', download_manager = objreg.get('download-manager', scope='window',
window=self.win_id) window=self.win_id)
download_count = download_manager.rowCount() download_count = download_manager.rowCount()
@ -419,4 +427,4 @@ class MainWindow(QWidget):
objreg.get('session-manager').save_last_window_session() objreg.get('session-manager').save_last_window_session()
self._save_geometry() self._save_geometry()
log.destroy.debug("Closing window {}".format(self.win_id)) log.destroy.debug("Closing window {}".format(self.win_id))
self._tabbed_browser.shutdown() self.tabbed_browser.shutdown()

View File

@ -29,7 +29,7 @@ from PyQt5.QtGui import QIcon
from qutebrowser.config import config from qutebrowser.config import config
from qutebrowser.keyinput import modeman from qutebrowser.keyinput import modeman
from qutebrowser.mainwindow import tabwidget from qutebrowser.mainwindow import tabwidget
from qutebrowser.browser import signalfilter, commands, webview from qutebrowser.browser import signalfilter, webview
from qutebrowser.utils import log, usertypes, utils, qtutils, objreg, urlutils from qutebrowser.utils import log, usertypes, utils, qtutils, objreg, urlutils
@ -107,12 +107,6 @@ class TabbedBrowser(tabwidget.TabWidget):
self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
self._undo_stack = [] self._undo_stack = []
self._filter = signalfilter.SignalFilter(win_id, self) self._filter = signalfilter.SignalFilter(win_id, self)
dispatcher = commands.CommandDispatcher(win_id)
objreg.register('command-dispatcher', dispatcher, scope='window',
window=win_id)
self.destroyed.connect(
functools.partial(objreg.delete, 'command-dispatcher',
scope='window', window=win_id))
self._now_focused = None self._now_focused = None
# FIXME adjust this to font size # FIXME adjust this to font size
# https://github.com/The-Compiler/qutebrowser/issues/119 # https://github.com/The-Compiler/qutebrowser/issues/119