From 3f024518288f9122cc788078da2fb80a352ff315 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Wed, 24 Sep 2014 07:06:45 +0200 Subject: [PATCH] Move object registry to its own file. --- qutebrowser/app.py | 8 +- qutebrowser/browser/commands.py | 4 +- qutebrowser/browser/downloads.py | 5 +- qutebrowser/browser/hints.py | 12 +-- qutebrowser/commands/argparser.py | 4 +- qutebrowser/commands/command.py | 7 +- qutebrowser/commands/runners.py | 4 +- qutebrowser/config/config.py | 6 +- qutebrowser/config/style.py | 8 +- qutebrowser/keyinput/basekeyparser.py | 4 +- qutebrowser/keyinput/modeman.py | 12 +-- qutebrowser/models/completion.py | 6 +- qutebrowser/models/downloadmodel.py | 8 +- qutebrowser/network/networkmanager.py | 6 +- qutebrowser/utils/completer.py | 4 +- qutebrowser/utils/message.py | 16 ++-- qutebrowser/utils/objreg.py | 95 +++++++++++++++++++++++ qutebrowser/utils/usertypes.py | 33 -------- qutebrowser/utils/utilcmds.py | 6 +- qutebrowser/utils/utils.py | 38 --------- qutebrowser/widgets/completion.py | 6 +- qutebrowser/widgets/crash.py | 4 +- qutebrowser/widgets/mainwindow.py | 8 +- qutebrowser/widgets/statusbar/bar.py | 8 +- qutebrowser/widgets/statusbar/command.py | 6 +- qutebrowser/widgets/statusbar/prompt.py | 4 +- qutebrowser/widgets/statusbar/prompter.py | 4 +- qutebrowser/widgets/tabbedbrowser.py | 11 ++- qutebrowser/widgets/tabwidget.py | 4 +- qutebrowser/widgets/webview.py | 4 +- 30 files changed, 185 insertions(+), 160 deletions(-) create mode 100644 qutebrowser/utils/objreg.py diff --git a/qutebrowser/app.py b/qutebrowser/app.py index f20fcb148..3688d202c 100644 --- a/qutebrowser/app.py +++ b/qutebrowser/app.py @@ -44,7 +44,7 @@ from qutebrowser.browser import quickmarks, cookies, downloads, cache from qutebrowser.widgets import mainwindow, console, crash from qutebrowser.keyinput import modeparsers, keyparser, modeman from qutebrowser.utils import (log, version, message, utilcmds, readline, - utils, qtutils, urlutils, debug) + utils, qtutils, urlutils, debug, objreg) from qutebrowser.utils import usertypes as utypes @@ -83,8 +83,8 @@ class Application(QApplication): 'tabs': False, 'main': False, } - self.meta_registry = utypes.ObjectRegistry() - self.registry = utypes.ObjectRegistry() + self.meta_registry = objreg.ObjectRegistry() + self.registry = objreg.ObjectRegistry() self.meta_registry['global'] = self.registry self.registry['app'] = self self._shutting_down = False @@ -626,7 +626,7 @@ class Application(QApplication): # exceptions occur. if pages is None: pages = [] - for tab in utils.get_object('tabbed-browser').widgets(): + for tab in objreg.get('tabbed-browser').widgets(): urlstr = tab.cur_url.toString( QUrl.RemovePassword | QUrl.FullyEncoded) if urlstr: diff --git a/qutebrowser/browser/commands.py b/qutebrowser/browser/commands.py index d8f64f5f5..8e3351148 100644 --- a/qutebrowser/browser/commands.py +++ b/qutebrowser/browser/commands.py @@ -38,7 +38,7 @@ from qutebrowser.commands import userscripts, cmdexc, cmdutils from qutebrowser.config import config from qutebrowser.browser import hints, quickmarks, webelem from qutebrowser.utils import (message, editor, usertypes, log, qtutils, - urlutils, utils) + urlutils, objreg) class CommandDispatcher: @@ -143,7 +143,7 @@ class CommandDispatcher: def _tab_focus_last(self): """Select the tab which was last focused.""" try: - tab = utils.get_object('last-focused-tab') + tab = objreg.get('last-focused-tab') except KeyError: raise cmdexc.CommandError("No last focused tab!") idx = self._tabs.indexOf(tab) diff --git a/qutebrowser/browser/downloads.py b/qutebrowser/browser/downloads.py index bc9f21339..ea80c85bb 100644 --- a/qutebrowser/browser/downloads.py +++ b/qutebrowser/browser/downloads.py @@ -29,7 +29,8 @@ from PyQt5.QtNetwork import QNetworkRequest, QNetworkReply from qutebrowser.config import config from qutebrowser.commands import cmdexc, cmdutils -from qutebrowser.utils import message, http, usertypes, log, utils, qtutils +from qutebrowser.utils import (message, http, usertypes, log, utils, qtutils, + objreg) class DownloadItem(QObject): @@ -409,7 +410,7 @@ class DownloadManager(QObject): q.destroyed.connect(functools.partial(self.questions.remove, q)) self.questions.append(q) download.cancelled.connect(q.abort) - utils.get_object('message-bridge').ask(q, blocking=False) + objreg.get('message-bridge').ask(q, blocking=False) @pyqtSlot(DownloadItem) def on_finished(self, download): diff --git a/qutebrowser/browser/hints.py b/qutebrowser/browser/hints.py index 0c30fe410..90ffddf2f 100644 --- a/qutebrowser/browser/hints.py +++ b/qutebrowser/browser/hints.py @@ -31,7 +31,7 @@ from qutebrowser.config import config from qutebrowser.keyinput import modeman from qutebrowser.browser import webelem from qutebrowser.commands import userscripts, cmdexc -from qutebrowser.utils import usertypes, log, qtutils, message, utils +from qutebrowser.utils import usertypes, log, qtutils, message, objreg ElemTuple = collections.namedtuple('ElemTuple', 'elem, label') @@ -149,8 +149,8 @@ class HintManager(QObject): """ super().__init__(parent) self._context = None - utils.get_object('mode-manager').left.connect(self.on_mode_left) - utils.get_object('mode-manager').entered.connect(self.on_mode_entered) + objreg.get('mode-manager').left.connect(self.on_mode_left) + objreg.get('mode-manager').entered.connect(self.on_mode_entered) def _cleanup(self): """Clean up after hinting.""" @@ -160,7 +160,7 @@ class HintManager(QObject): except webelem.IsNullError: pass text = self.HINT_TEXTS[self._context.target] - utils.get_object('message-bridge').maybe_reset_text(text) + objreg.get('message-bridge').maybe_reset_text(text) self._context = None def _hint_strings(self, elems): @@ -271,7 +271,7 @@ class HintManager(QObject): display = 'none' rect = elem.geometry() return self.HINT_CSS.format( - left=rect.x(), top=rect.y(), config=utils.get_object('config'), + left=rect.x(), top=rect.y(), config=objreg.get('config'), display=display) def _draw_label(self, elem, string): @@ -542,7 +542,7 @@ class HintManager(QObject): self._context.frames = webelem.get_child_frames(mainframe) self._context.args = args self._init_elements(mainframe, group) - utils.get_object('message-bridge').set_text(self.HINT_TEXTS[target]) + objreg.get('message-bridge').set_text(self.HINT_TEXTS[target]) self._connect_frame_signals() try: modeman.enter(usertypes.KeyMode.hint, 'HintManager.start') diff --git a/qutebrowser/commands/argparser.py b/qutebrowser/commands/argparser.py index a92a1599a..9ef3d59aa 100644 --- a/qutebrowser/commands/argparser.py +++ b/qutebrowser/commands/argparser.py @@ -25,7 +25,7 @@ import argparse from PyQt5.QtCore import QUrl from qutebrowser.commands import cmdexc -from qutebrowser.utils import utils +from qutebrowser.utils import utils, objreg SUPPRESS = argparse.SUPPRESS @@ -54,7 +54,7 @@ class HelpAction(argparse.Action): """ def __call__(self, parser, _namespace, _values, _option_string=None): - utils.get_object('tabbed-browser').tabopen( + objreg.get('tabbed-browser').tabopen( QUrl('qute://help/commands.html#{}'.format(parser.name))) parser.exit() diff --git a/qutebrowser/commands/command.py b/qutebrowser/commands/command.py index 3e65d69bc..b2dd39810 100644 --- a/qutebrowser/commands/command.py +++ b/qutebrowser/commands/command.py @@ -25,7 +25,8 @@ import collections from PyQt5.QtWebKit import QWebSettings from qutebrowser.commands import cmdexc, argparser -from qutebrowser.utils import log, utils, message, debug, usertypes, docutils +from qutebrowser.utils import (log, utils, message, debug, usertypes, docutils, + objreg) class Command: @@ -97,7 +98,7 @@ class Command: Raise: PrerequisitesError if the command can't be called currently. """ - curmode = utils.get_object('mode-manager').mode() + curmode = objreg.get('mode-manager').mode() if self.modes is not None and curmode not in self.modes: mode_names = '/'.join(mode.name for mode in self.modes) raise cmdexc.PrerequisitesError( @@ -298,7 +299,7 @@ class Command: args: The positional argument list. Gets modified directly. """ assert param.kind == inspect.Parameter.POSITIONAL_OR_KEYWORD - obj = utils.get_object(self.instance) + obj = objreg.get(self.instance) args.append(obj) def _get_count_arg(self, param, args, kwargs): diff --git a/qutebrowser/commands/runners.py b/qutebrowser/commands/runners.py index 2b934222f..9821c9706 100644 --- a/qutebrowser/commands/runners.py +++ b/qutebrowser/commands/runners.py @@ -24,7 +24,7 @@ from PyQt5.QtWebKitWidgets import QWebPage from qutebrowser.config import config from qutebrowser.commands import cmdexc, cmdutils -from qutebrowser.utils import message, log, utils +from qutebrowser.utils import message, log, utils, objreg def replace_variables(arglist): @@ -32,7 +32,7 @@ def replace_variables(arglist): args = [] for arg in arglist: if arg == '{url}': - url = utils.get_object('tabbed-browser').current_url().toString( + url = objreg.get('tabbed-browser').current_url().toString( QUrl.FullyEncoded | QUrl.RemovePassword) args.append(url) else: diff --git a/qutebrowser/config/config.py b/qutebrowser/config/config.py index 5e28d5997..f76ab7415 100644 --- a/qutebrowser/config/config.py +++ b/qutebrowser/config/config.py @@ -35,18 +35,18 @@ from PyQt5.QtCore import pyqtSignal, QObject from qutebrowser.utils import log from qutebrowser.config import configdata, iniparsers, configtypes, textwrapper from qutebrowser.commands import cmdexc, cmdutils -from qutebrowser.utils import message, utils +from qutebrowser.utils import message, objreg from qutebrowser.utils.usertypes import Completion def get(*args, **kwargs): """Convenience method to call get(...) of the config instance.""" - return utils.get_object('config').get(*args, **kwargs) + return objreg.get('config').get(*args, **kwargs) def section(sect): """Get a config section from the global config.""" - return utils.get_object('config')[sect] + return objreg.get('config')[sect] class NoSectionError(configparser.NoSectionError): diff --git a/qutebrowser/config/style.py b/qutebrowser/config/style.py index 12c21c739..4b964c87c 100644 --- a/qutebrowser/config/style.py +++ b/qutebrowser/config/style.py @@ -25,7 +25,7 @@ import jinja2 from PyQt5.QtGui import QColor from qutebrowser.config import config -from qutebrowser.utils import log, utils +from qutebrowser.utils import log, objreg @functools.lru_cache(maxsize=16) @@ -42,7 +42,7 @@ def get_stylesheet(template_str): fontdict = FontDict(config.section('fonts')) template = jinja2.Template(template_str) return template.render(color=colordict, font=fontdict, - config=utils.get_object('config')) + config=objreg.get('config')) def set_register_stylesheet(obj): @@ -60,8 +60,8 @@ def set_register_stylesheet(obj): log.style.vdebug("stylesheet for {}: {}".format( obj.__class__.__name__, qss)) obj.setStyleSheet(qss) - utils.get_object('config').changed.connect( - functools.partial(_update_stylesheet, obj)) + objreg.get('config').changed.connect(functools.partial( + _update_stylesheet, obj)) def _update_stylesheet(obj, _section, _option): diff --git a/qutebrowser/keyinput/basekeyparser.py b/qutebrowser/keyinput/basekeyparser.py index ebfb51d81..e5be993f8 100644 --- a/qutebrowser/keyinput/basekeyparser.py +++ b/qutebrowser/keyinput/basekeyparser.py @@ -26,7 +26,7 @@ import functools from PyQt5.QtCore import pyqtSignal, pyqtSlot, Qt, QObject from qutebrowser.config import config -from qutebrowser.utils import usertypes, log, utils +from qutebrowser.utils import usertypes, log, utils, objreg class BaseKeyParser(QObject): @@ -321,7 +321,7 @@ class BaseKeyParser(QObject): self._modename = modename self.bindings = {} self.special_bindings = {} - keyconfparser = utils.get_object('key-config') + keyconfparser = objreg.get('key-config') for (key, cmd) in keyconfparser.get_bindings_for(modename).items(): if not cmd: continue diff --git a/qutebrowser/keyinput/modeman.py b/qutebrowser/keyinput/modeman.py index 22a561d8b..41fa44aae 100644 --- a/qutebrowser/keyinput/modeman.py +++ b/qutebrowser/keyinput/modeman.py @@ -29,7 +29,7 @@ from PyQt5.QtWidgets import QApplication from qutebrowser.config import config from qutebrowser.commands import cmdexc, cmdutils -from qutebrowser.utils import usertypes, log, utils +from qutebrowser.utils import usertypes, log, objreg class ModeLockedError(Exception): @@ -39,18 +39,18 @@ class ModeLockedError(Exception): def enter(mode, reason=None): """Enter the mode 'mode'.""" - utils.get_object('mode-manager').enter(mode, reason) + objreg.get('mode-manager').enter(mode, reason) def leave(mode, reason=None): """Leave the mode 'mode'.""" - utils.get_object('mode-manager').leave(mode, reason) + objreg.get('mode-manager').leave(mode, reason) def maybe_enter(mode, reason=None): """Convenience method to enter 'mode' without exceptions.""" try: - utils.get_object('mode-manager').enter(mode, reason) + objreg.get('mode-manager').enter(mode, reason) except ModeLockedError: pass @@ -58,7 +58,7 @@ def maybe_enter(mode, reason=None): def maybe_leave(mode, reason=None): """Convenience method to leave 'mode' without exceptions.""" try: - utils.get_object('mode-manager').leave(mode, reason) + objreg.get('mode-manager').leave(mode, reason) except ValueError as e: # This is rather likely to happen, so we only log to debug log. log.modes.debug(e) @@ -283,7 +283,7 @@ class ModeManager(QObject): # we're not interested in it anymore. return False if (QApplication.instance().activeWindow() is not - utils.get_object('main-window')): + objreg.get('main-window')): # Some other window (print dialog, etc.) is focused so we pass # the event through. return False diff --git a/qutebrowser/models/completion.py b/qutebrowser/models/completion.py index 3b2c66dc1..d15096d7c 100644 --- a/qutebrowser/models/completion.py +++ b/qutebrowser/models/completion.py @@ -23,7 +23,7 @@ from PyQt5.QtCore import pyqtSlot, Qt from qutebrowser.config import config, configdata from qutebrowser.models import basecompletion -from qutebrowser.utils import log, qtutils, utils +from qutebrowser.utils import log, qtutils, objreg from qutebrowser.commands import cmdutils @@ -155,7 +155,7 @@ class CommandCompletionModel(basecompletion.BaseCompletionModel): assert cmdutils.cmd_dict cmdlist = [] for obj in set(cmdutils.cmd_dict.values()): - if obj.hide or (obj.debug and not utils.get_object('args').debug): + if obj.hide or (obj.debug and not objreg.get('args').debug): pass else: cmdlist.append((obj.name, obj.desc)) @@ -182,7 +182,7 @@ class HelpCompletionModel(basecompletion.BaseCompletionModel): assert cmdutils.cmd_dict cmdlist = [] for obj in set(cmdutils.cmd_dict.values()): - if obj.hide or (obj.debug and not utils.get_object('args').debug): + if obj.hide or (obj.debug and not objreg.get('args').debug): pass else: cmdlist.append((':' + obj.name, obj.desc)) diff --git a/qutebrowser/models/downloadmodel.py b/qutebrowser/models/downloadmodel.py index a99bb8188..4f0a15954 100644 --- a/qutebrowser/models/downloadmodel.py +++ b/qutebrowser/models/downloadmodel.py @@ -23,7 +23,7 @@ from PyQt5.QtCore import (pyqtSlot, Qt, QVariant, QAbstractListModel, QModelIndex) from qutebrowser.config import config -from qutebrowser.utils import usertypes, qtutils, utils +from qutebrowser.utils import usertypes, qtutils, objreg Role = usertypes.enum('Role', 'item', start=Qt.UserRole, is_int=True) @@ -39,7 +39,7 @@ class DownloadModel(QAbstractListModel): def __init__(self, parent=None): super().__init__(parent) - download_manager = utils.get_object('download-manager') + download_manager = objreg.get('download-manager') download_manager.download_about_to_be_added.connect( lambda idx: self.beginInsertRows(QModelIndex(), idx, idx)) download_manager.download_added.connect(self.endInsertRows) @@ -81,7 +81,7 @@ class DownloadModel(QAbstractListModel): if index.parent().isValid() or index.column() != 0: return QVariant() - item = utils.get_object('download-manager').downloads[index.row()] + item = objreg.get('download-manager').downloads[index.row()] if role == Qt.DisplayRole: data = str(item) elif role == Qt.ForegroundRole: @@ -105,4 +105,4 @@ class DownloadModel(QAbstractListModel): if parent.isValid(): # We don't have children return 0 - return len(utils.get_object('download-manager').downloads) + return len(objreg.get('download-manager').downloads) diff --git a/qutebrowser/network/networkmanager.py b/qutebrowser/network/networkmanager.py index 7bcf6d665..e306af54d 100644 --- a/qutebrowser/network/networkmanager.py +++ b/qutebrowser/network/networkmanager.py @@ -30,7 +30,7 @@ else: SSL_AVAILABLE = QSslSocket.supportsSsl() from qutebrowser.config import config -from qutebrowser.utils import message, log, usertypes, utils +from qutebrowser.utils import message, log, usertypes, utils, objreg from qutebrowser.network import qutescheme, schemehandler @@ -55,10 +55,10 @@ class NetworkManager(QNetworkAccessManager): # We have a shared cookie jar and cache - we restore their parents so # we don't take ownership of them. app = QCoreApplication.instance() - cookie_jar = utils.get_object('cookie-jar') + cookie_jar = objreg.get('cookie-jar') self.setCookieJar(cookie_jar) cookie_jar.setParent(app) - cache = utils.get_object('cache') + cache = objreg.get('cache') self.setCache(cache) cache.setParent(app) diff --git a/qutebrowser/utils/completer.py b/qutebrowser/utils/completer.py index b951f66f3..748d3d38d 100644 --- a/qutebrowser/utils/completer.py +++ b/qutebrowser/utils/completer.py @@ -23,7 +23,7 @@ from PyQt5.QtCore import pyqtSlot, pyqtSignal, QObject from qutebrowser.config import config, configdata from qutebrowser.commands import cmdutils -from qutebrowser.utils import usertypes, log, utils +from qutebrowser.utils import usertypes, log, objreg from qutebrowser.models import completion as models from qutebrowser.models.completionfilter import CompletionFilterModel as CFM @@ -72,7 +72,7 @@ class Completer(QObject): def _init_setting_completions(self): """Initialize setting completion models.""" - config_obj = utils.get_object('config') + config_obj = objreg.get('config') self._models[usertypes.Completion.section] = CFM( models.SettingSectionCompletionModel(self), self) self._models[usertypes.Completion.option] = {} diff --git a/qutebrowser/utils/message.py b/qutebrowser/utils/message.py index 31ef8e615..7d11c84d3 100644 --- a/qutebrowser/utils/message.py +++ b/qutebrowser/utils/message.py @@ -21,7 +21,7 @@ from PyQt5.QtCore import pyqtSignal, QObject, QTimer -from qutebrowser.utils import usertypes, log, utils +from qutebrowser.utils import usertypes, log, objreg def error(message, immediately=False): @@ -30,7 +30,7 @@ def error(message, immediately=False): Args: See MessageBridge.error. """ - utils.get_object('message-bridge').error(message, immediately) + objreg.get('message-bridge').error(message, immediately) def info(message, immediately=True): @@ -39,12 +39,12 @@ def info(message, immediately=True): Args: See MessageBridge.info. """ - utils.get_object('message-bridge').info(message, immediately) + objreg.get('message-bridge').info(message, immediately) def set_cmd_text(txt): """Convienience function to Set the statusbar command line to a text.""" - utils.get_object('message-bridge').set_cmd_text(txt) + objreg.get('message-bridge').set_cmd_text(txt) def ask(message, mode, default=None): @@ -62,7 +62,7 @@ def ask(message, mode, default=None): q.text = message q.mode = mode q.default = default - utils.get_object('message-bridge').ask(q, blocking=True) + objreg.get('message-bridge').ask(q, blocking=True) q.deleteLater() return q.answer @@ -72,7 +72,7 @@ def alert(message): q = usertypes.Question() q.text = message q.mode = usertypes.PromptMode.alert - utils.get_object('message-bridge').ask(q, blocking=True) + objreg.get('message-bridge').ask(q, blocking=True) q.deleteLater() @@ -87,7 +87,7 @@ def ask_async(message, mode, handler, default=None): """ if not isinstance(mode, usertypes.PromptMode): raise TypeError("Mode {} is no PromptMode member!".format(mode)) - bridge = utils.get_object('message-bridge') + bridge = objreg.get('message-bridge') q = usertypes.Question(bridge) q.text = message q.mode = mode @@ -106,7 +106,7 @@ def confirm_async(message, yes_action, no_action=None, default=None): no_action: Callable to be called when the user answered no. default: True/False to set a default value, or None. """ - bridge = utils.get_object('message-bridge') + bridge = objreg.get('message-bridge') q = usertypes.Question(bridge) q.text = message q.mode = usertypes.PromptMode.yesno diff --git a/qutebrowser/utils/objreg.py b/qutebrowser/utils/objreg.py new file mode 100644 index 000000000..d83727c9a --- /dev/null +++ b/qutebrowser/utils/objreg.py @@ -0,0 +1,95 @@ +# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et: + +# Copyright 2014 Florian Bruhin (The Compiler) +# +# This file is part of qutebrowser. +# +# qutebrowser is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# qutebrowser is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with qutebrowser. If not, see . + +"""The global object registry and related utility functions.""" + + +import collections +import functools + +from PyQt5.QtCore import QCoreApplication, QObject + + +_UNSET = object() + + +class ObjectRegistry(collections.UserDict): + + """A registry of long-living objects in qutebrowser. + + Inspired by the eric IDE code (E5Gui/E5Application.py). + """ + + def __setitem__(self, name, obj): + """Register an object in the object registry. + + Sets a slot to remove QObjects when they are destroyed. + """ + if isinstance(obj, QObject): + obj.destroyed.connect(functools.partial(self.on_destroyed, name)) + super().__setitem__(name, obj) + + def on_destroyed(self, name): + """Remove a destroyed QObject.""" + try: + del self[name] + except KeyError: + pass + + def dump_objects(self): + """Dump all objects as a list of strings.""" + lines = [] + for name, obj in self.data.items(): + lines.append("{}: {}".format(name, repr(obj))) + return lines + + +def get(name, default=_UNSET): + """Helper function to get an object. + + Args: + default: A default to return if the object does not exist. + """ + try: + return QCoreApplication.instance().registry[name] + except KeyError: + if default is not _UNSET: + return default + else: + raise + + +def register(name, obj, update=False): + """Helper function to register an object. + + Args: + name: The name the object will be registered as. + obj: The object to register. + update: If True, allows to update an already registered object. + """ + registry = QCoreApplication.instance().registry + if not update and name in registry: + raise KeyError("Object '{}' is already registered ({})!".format( + name, repr(registry[name]))) + registry[name] = obj + + +def delete(name): + """Helper function to unregister an object.""" + del QCoreApplication.instance().registry[name] diff --git a/qutebrowser/utils/usertypes.py b/qutebrowser/utils/usertypes.py index 81af0a357..e17e231ac 100644 --- a/qutebrowser/utils/usertypes.py +++ b/qutebrowser/utils/usertypes.py @@ -24,8 +24,6 @@ Module attributes: """ import operator -import functools -import collections import collections.abc import enum as pyenum @@ -383,34 +381,3 @@ class Timer(QTimer): super().start(msec) else: super().start() - - -class ObjectRegistry(collections.UserDict): - - """A registry of long-living objects in qutebrowser. - - Inspired by the eric IDE code (E5Gui/E5Application.py). - """ - - def __setitem__(self, name, obj): - """Register an object in the object registry. - - Sets a slot to remove QObjects when they are destroyed. - """ - if isinstance(obj, QObject): - obj.destroyed.connect(functools.partial(self.on_destroyed, name)) - super().__setitem__(name, obj) - - def on_destroyed(self, name): - """Remove a destroyed QObject.""" - try: - del self[name] - except KeyError: - pass - - def dump_objects(self): - """Dump all objects as a list of strings.""" - lines = [] - for name, obj in self.data.items(): - lines.append("{}: {}".format(name, repr(obj))) - return lines diff --git a/qutebrowser/utils/utilcmds.py b/qutebrowser/utils/utilcmds.py index 7c507d910..82d2a8e09 100644 --- a/qutebrowser/utils/utilcmds.py +++ b/qutebrowser/utils/utilcmds.py @@ -25,7 +25,7 @@ import functools from PyQt5.QtCore import QCoreApplication -from qutebrowser.utils import usertypes, log, utils +from qutebrowser.utils import usertypes, log, objreg from qutebrowser.commands import runners, cmdexc, cmdutils from qutebrowser.config import style @@ -96,7 +96,7 @@ def debug_all_objects(): @cmdutils.register(debug=True) def debug_cache_stats(): """Print LRU cache stats.""" - config_info = utils.get_object('config').get.cache_info() + config_info = objreg.get('config').get.cache_info() style_info = style.get_stylesheet.cache_info() log.misc.debug('config: {}'.format(config_info)) log.misc.debug('style: {}'.format(style_info)) @@ -105,4 +105,4 @@ def debug_cache_stats(): @cmdutils.register(debug=True) def debug_console(): """Show the debugging console.""" - utils.get_object('debug-console').show() + objreg.get('debug-console').show() diff --git a/qutebrowser/utils/utils.py b/qutebrowser/utils/utils.py index b8e306ff9..387c53d90 100644 --- a/qutebrowser/utils/utils.py +++ b/qutebrowser/utils/utils.py @@ -39,9 +39,6 @@ import qutebrowser from qutebrowser.utils import qtutils, log -_UNSET = object() - - def elide(text, length): """Elide text so it uses a maximum of length chars.""" if length < 1: @@ -581,38 +578,3 @@ def is_enum(obj): return issubclass(obj, enum.Enum) except TypeError: return False - - -def get_object(name, default=_UNSET): - """Helper function to get an object. - - Args: - default: A default to return if the object does not exist. - """ - try: - return QCoreApplication.instance().registry[name] - except KeyError: - if default is not _UNSET: - return default - else: - raise - - -def register_object(name, obj, update=False): - """Helper function to register an object. - - Args: - name: The name the object will be registered as. - obj: The object to register. - update: If True, allows to update an already registered object. - """ - registry = QCoreApplication.instance().registry - if not update and name in registry: - raise KeyError("Object '{}' is already registered ({})!".format( - name, repr(registry[name]))) - registry[name] = obj - - -def delete_object(name): - """Helper function to unregister an object.""" - del QCoreApplication.instance().registry[name] diff --git a/qutebrowser/widgets/completion.py b/qutebrowser/widgets/completion.py index 68da7576a..5a237a824 100644 --- a/qutebrowser/widgets/completion.py +++ b/qutebrowser/widgets/completion.py @@ -29,7 +29,7 @@ from PyQt5.QtCore import pyqtSlot, pyqtSignal, Qt, QItemSelectionModel from qutebrowser.commands import cmdutils from qutebrowser.config import config, style from qutebrowser.widgets import completiondelegate -from qutebrowser.utils import completer, usertypes, qtutils, utils +from qutebrowser.utils import completer, usertypes, qtutils, objreg class CompletionView(QTreeView): @@ -92,7 +92,7 @@ class CompletionView(QTreeView): def __init__(self, parent=None): super().__init__(parent) completer_obj = completer.Completer(self) - utils.register_object('completer', completer_obj) + objreg.register('completer', completer_obj) self.enabled = config.get('completion', 'show') self._delegate = completiondelegate.CompletionItemDelegate(self) @@ -225,7 +225,7 @@ class CompletionView(QTreeView): def selectionChanged(self, selected, deselected): """Extend selectionChanged to call completers selection_changed.""" super().selectionChanged(selected, deselected) - utils.get_object('completer').selection_changed(selected, deselected) + objreg.get('completer').selection_changed(selected, deselected) def resizeEvent(self, e): """Extend resizeEvent to adjust column size.""" diff --git a/qutebrowser/widgets/crash.py b/qutebrowser/widgets/crash.py index 4bbb738b6..9a6fe6167 100644 --- a/qutebrowser/widgets/crash.py +++ b/qutebrowser/widgets/crash.py @@ -29,7 +29,7 @@ from PyQt5.QtCore import Qt, QSize from PyQt5.QtWidgets import (QDialog, QLabel, QTextEdit, QPushButton, QVBoxLayout, QHBoxLayout) -from qutebrowser.utils import version, log, utils +from qutebrowser.utils import version, log, utils, objreg class _CrashDialog(QDialog): @@ -130,7 +130,7 @@ class _CrashDialog(QDialog): except Exception: self._crash_info.append(("Version info", traceback.format_exc())) try: - conf = utils.get_object('config') + conf = objreg.get('config') self._crash_info.append(("Config", conf.dump_userconfig())) except Exception: self._crash_info.append(("Config", traceback.format_exc())) diff --git a/qutebrowser/widgets/mainwindow.py b/qutebrowser/widgets/mainwindow.py index 723bd7ad8..3455a2e56 100644 --- a/qutebrowser/widgets/mainwindow.py +++ b/qutebrowser/widgets/mainwindow.py @@ -27,7 +27,7 @@ from PyQt5.QtWidgets import QWidget, QVBoxLayout from qutebrowser.commands import cmdutils from qutebrowser.config import config -from qutebrowser.utils import message, log, usertypes, qtutils, utils +from qutebrowser.utils import message, log, usertypes, qtutils, objreg from qutebrowser.widgets import tabbedbrowser, completion, downloads from qutebrowser.widgets.statusbar import bar @@ -50,7 +50,7 @@ class MainWindow(QWidget): super().__init__(parent) self.setWindowTitle('qutebrowser') - state_config = utils.get_object('state-config') + state_config = objreg.get('state-config') try: data = state_config['geometry']['mainwindow'] log.init.debug("Restoring mainwindow from {}".format(data)) @@ -83,11 +83,11 @@ class MainWindow(QWidget): self._tabbed_browser = tabbedbrowser.TabbedBrowser() self._tabbed_browser.title_changed.connect(self.setWindowTitle) - utils.register_object('tabbed-browser', self._tabbed_browser) + objreg.register('tabbed-browser', self._tabbed_browser) self._vbox.addWidget(self._tabbed_browser) self._completion = completion.CompletionView(self) - utils.register_object('completion', self._completion) + objreg.register('completion', self._completion) self.status = bar.StatusBar() self._vbox.addWidget(self.status) diff --git a/qutebrowser/widgets/statusbar/bar.py b/qutebrowser/widgets/statusbar/bar.py index b2c51b1f6..c4a66020e 100644 --- a/qutebrowser/widgets/statusbar/bar.py +++ b/qutebrowser/widgets/statusbar/bar.py @@ -26,7 +26,7 @@ from PyQt5.QtCore import pyqtSignal, pyqtSlot, pyqtProperty, Qt from PyQt5.QtWidgets import QWidget, QHBoxLayout, QStackedLayout, QSizePolicy from qutebrowser.config import config, style -from qutebrowser.utils import usertypes, log, utils +from qutebrowser.utils import usertypes, log, objreg from qutebrowser.widgets.statusbar import (command, progress, keystring, percentage, url, prompt) from qutebrowser.widgets.statusbar import text as textwidget @@ -132,7 +132,7 @@ class StatusBar(QWidget): self._stack.setContentsMargins(0, 0, 0, 0) self._cmd = command.Command() - utils.register_object('status-command', self._cmd) + objreg.register('status-command', self._cmd) self._stack.addWidget(self._cmd) self.txt = textwidget.Text() @@ -376,7 +376,7 @@ class StatusBar(QWidget): @pyqtSlot(usertypes.KeyMode) def on_mode_entered(self, mode): """Mark certain modes in the commandline.""" - if mode in utils.get_object('mode-manager').passthrough: + if mode in objreg.get('mode-manager').passthrough: text = "-- {} MODE --".format(mode.name.upper()) self.txt.set_text(self.txt.Text.normal, text) if mode == usertypes.KeyMode.insert: @@ -385,7 +385,7 @@ class StatusBar(QWidget): @pyqtSlot(usertypes.KeyMode) def on_mode_left(self, mode): """Clear marked mode.""" - if mode in utils.get_object('mode-manager').passthrough: + if mode in objreg.get('mode-manager').passthrough: self.txt.set_text(self.txt.Text.normal, '') if mode == usertypes.KeyMode.insert: self._set_insert_active(False) diff --git a/qutebrowser/widgets/statusbar/command.py b/qutebrowser/widgets/statusbar/command.py index d6c38935e..a15a165d0 100644 --- a/qutebrowser/widgets/statusbar/command.py +++ b/qutebrowser/widgets/statusbar/command.py @@ -26,7 +26,7 @@ from qutebrowser.keyinput import modeman, modeparsers from qutebrowser.commands import runners, cmdexc, cmdutils from qutebrowser.widgets import misc from qutebrowser.models import cmdhistory -from qutebrowser.utils import usertypes, log, utils +from qutebrowser.utils import usertypes, log, objreg class Command(misc.MinimalLineEditMixin, misc.CommandLineEdit): @@ -74,7 +74,7 @@ class Command(misc.MinimalLineEditMixin, misc.CommandLineEdit): misc.CommandLineEdit.__init__(self, parent) misc.MinimalLineEditMixin.__init__(self) self.cursor_part = 0 - self.history.history = utils.get_object('command-history').data + self.history.history = objreg.get('command-history').data self._empty_item_idx = None self.textEdited.connect(self.on_text_edited) self.cursorPositionChanged.connect(self._update_cursor_part) @@ -172,7 +172,7 @@ class Command(misc.MinimalLineEditMixin, misc.CommandLineEdit): Args: text: The commandline to set. """ - url = utils.get_object('tabbed-browser').current_url().toString( + url = objreg.get('tabbed-browser').current_url().toString( QUrl.FullyEncoded | QUrl.RemovePassword) # FIXME we currently replace the URL in any place in the arguments, # rather than just replacing it if it is a dedicated argument. We could diff --git a/qutebrowser/widgets/statusbar/prompt.py b/qutebrowser/widgets/statusbar/prompt.py index 3122703dd..015cbd795 100644 --- a/qutebrowser/widgets/statusbar/prompt.py +++ b/qutebrowser/widgets/statusbar/prompt.py @@ -24,7 +24,7 @@ from PyQt5.QtWidgets import QHBoxLayout, QWidget, QLineEdit from qutebrowser.widgets import misc from qutebrowser.widgets.statusbar import textbase, prompter -from qutebrowser.utils import utils +from qutebrowser.utils import objreg class PromptLineEdit(misc.MinimalLineEditMixin, QLineEdit): @@ -66,7 +66,7 @@ class Prompt(QWidget): self._hbox.addWidget(self.lineedit) prompter_obj = prompter.Prompter(self) - utils.register_object('prompter', prompter_obj) + objreg.register('prompter', prompter_obj) def __repr__(self): return '<{}>'.format(self.__class__.__name__) diff --git a/qutebrowser/widgets/statusbar/prompter.py b/qutebrowser/widgets/statusbar/prompter.py index 16cacb85c..22b8874e6 100644 --- a/qutebrowser/widgets/statusbar/prompter.py +++ b/qutebrowser/widgets/statusbar/prompter.py @@ -26,7 +26,7 @@ from PyQt5.QtWidgets import QLineEdit from qutebrowser.keyinput import modeman from qutebrowser.commands import cmdutils -from qutebrowser.utils import usertypes, log, qtutils, utils +from qutebrowser.utils import usertypes, log, qtutils, objreg PromptContext = collections.namedtuple('PromptContext', @@ -280,7 +280,7 @@ class Prompter: self.question = question mode = self._display_question() question.aborted.connect(lambda: modeman.maybe_leave(mode, 'aborted')) - mode_manager = utils.get_object('mode-manager') + mode_manager = objreg.get('mode-manager') try: modeman.enter(mode, 'question asked') except modeman.ModeLockedError: diff --git a/qutebrowser/widgets/tabbedbrowser.py b/qutebrowser/widgets/tabbedbrowser.py index 82a5f5d51..bcad5e93b 100644 --- a/qutebrowser/widgets/tabbedbrowser.py +++ b/qutebrowser/widgets/tabbedbrowser.py @@ -31,7 +31,7 @@ from qutebrowser.commands import cmdexc, cmdutils from qutebrowser.keyinput import modeman from qutebrowser.widgets import tabwidget, webview from qutebrowser.browser import signalfilter, commands -from qutebrowser.utils import log, message, usertypes, utils, qtutils +from qutebrowser.utils import log, message, usertypes, utils, qtutils, objreg class TabbedBrowser(tabwidget.TabWidget): @@ -109,7 +109,7 @@ class TabbedBrowser(tabwidget.TabWidget): self.url_stack = [] self._filter = signalfilter.SignalFilter(self) dispatcher = commands.CommandDispatcher(self) - utils.register_object('command-dispatcher', dispatcher) + objreg.register('command-dispatcher', dispatcher) self._now_focused = None # FIXME adjust this to font size self.setIconSize(QSize(12, 12)) @@ -261,8 +261,8 @@ class TabbedBrowser(tabwidget.TabWidget): tab)) if tab is self._now_focused: self._now_focused = None - if tab is utils.get_object('last-focused-tab', None): - utils.delete_object('last-focused-tab') + if tab is objreg.get('last-focused-tab', None): + objreg.delete('last-focused-tab') if not tab.cur_url.isEmpty(): qtutils.ensure_valid(tab.cur_url) self.url_stack.append(tab.cur_url) @@ -525,8 +525,7 @@ class TabbedBrowser(tabwidget.TabWidget): tab.setFocus() modeman.maybe_leave(usertypes.KeyMode.hint, 'tab changed') if self._now_focused is not None: - utils.register_object('last-focused-tab', self._now_focused, - update=True) + objreg.register('last-focused-tab', self._now_focused, update=True) self._now_focused = tab self.current_tab_changed.emit(tab) self.title_changed.emit('{} - qutebrowser'.format(self.tabText(idx))) diff --git a/qutebrowser/widgets/tabwidget.py b/qutebrowser/widgets/tabwidget.py index e5af752e3..a43c993ab 100644 --- a/qutebrowser/widgets/tabwidget.py +++ b/qutebrowser/widgets/tabwidget.py @@ -31,7 +31,7 @@ from PyQt5.QtWidgets import (QTabWidget, QTabBar, QSizePolicy, QCommonStyle, QStyle, QStylePainter, QStyleOptionTab) from PyQt5.QtGui import QIcon, QPalette, QColor -from qutebrowser.utils import qtutils, utils +from qutebrowser.utils import qtutils, objreg from qutebrowser.config import config @@ -209,7 +209,7 @@ class TabBar(QTabBar): confwidth = str(config.get('tabs', 'width')) if confwidth.endswith('%'): perc = int(confwidth.rstrip('%')) - width = utils.get_object('main-window').width() * perc / 100 + width = objreg.get('main-window').width() * perc / 100 else: width = int(confwidth) size = QSize(max(minimum_size.width(), width), height) diff --git a/qutebrowser/widgets/webview.py b/qutebrowser/widgets/webview.py index 8ee2dc11c..f12eef131 100644 --- a/qutebrowser/widgets/webview.py +++ b/qutebrowser/widgets/webview.py @@ -26,7 +26,7 @@ from PyQt5.QtWebKitWidgets import QWebView, QWebPage from qutebrowser.config import config from qutebrowser.keyinput import modeman -from qutebrowser.utils import message, log, usertypes, utils, qtutils +from qutebrowser.utils import message, log, usertypes, utils, qtutils, objreg from qutebrowser.browser import webpage, hints, webelem from qutebrowser.commands import cmdexc @@ -358,7 +358,7 @@ class WebView(QWebView): self._set_load_status(LoadStatus.error) if not config.get('input', 'auto-insert-mode'): return - cur_mode = utils.get_object('mode-manager').mode() + cur_mode = objreg.get('mode-manager').mode() if cur_mode == usertypes.KeyMode.insert or not ok: return frame = self.page().currentFrame()