diff --git a/doc/TODO b/doc/TODO index a4cdaaabd..8a27f25e9 100644 --- a/doc/TODO +++ b/doc/TODO @@ -129,9 +129,6 @@ style rewrite. - Use separate logger for config - Use unittest.Mock and especially unittest.patch more. -- Use decorators for on_config_changed - - Will also make it easier to implement section-changed handlers for - :reload - Check where using signals would be better than objreg.get. dwb keybindings to possibly implement diff --git a/qutebrowser/app.py b/qutebrowser/app.py index 84d41eec1..b28703eff 100644 --- a/qutebrowser/app.py +++ b/qutebrowser/app.py @@ -294,7 +294,6 @@ class Application(QApplication): message_bridge = objreg.get('message-bridge') mode_manager = objreg.get('mode-manager') prompter = objreg.get('prompter') - command_history = objreg.get('command-history') download_manager = objreg.get('download-manager') config_obj = objreg.get('config') key_config = objreg.get('key-config') @@ -331,9 +330,6 @@ class Application(QApplication): # config config_obj.style_changed.connect(style.get_stylesheet.cache_clear) - for obj in (tabs, completion, main_window, command_history, - websettings, mode_manager, status, status.txt): - config_obj.changed.connect(obj.on_config_changed) for obj in kp.values(): key_config.changed.connect(obj.on_keyconfig_changed) diff --git a/qutebrowser/config/config.py b/qutebrowser/config/config.py index daf35f89a..2dc6d15b7 100644 --- a/qutebrowser/config/config.py +++ b/qutebrowser/config/config.py @@ -27,8 +27,10 @@ we borrow some methods and classes from there where it makes sense. import os import sys import os.path +import inspect import functools import configparser +import collections import collections.abc from PyQt5.QtCore import pyqtSignal, QObject, QStandardPaths @@ -36,12 +38,39 @@ from PyQt5.QtWidgets import QMessageBox from qutebrowser.utils import log from qutebrowser.config import (configdata, iniparsers, configtypes, - textwrapper, lineparser, keyconfparser) + textwrapper, keyconfparser) from qutebrowser.commands import cmdexc, cmdutils from qutebrowser.utils import message, objreg, utils from qutebrowser.utils.usertypes import Completion +ChangeHandler = collections.namedtuple('ChangeHandler', ['func', 'section', + 'option']) + + +change_handlers = [] + + +def on_change(func, sectname=None, optname=None): + """Register a new change handler. + + Args: + func: The function to be called on change. + sectname: Filter for the config section. + If None, the handler gets called for all sections. + optname: Filter for the config option. + If None, the handler gets called for all options. + """ + if optname is not None and sectname is None: + raise TypeError("option is {} but section is None!".format(optname)) + if sectname is not None and sectname not in configdata.DATA: + raise NoSectionError("Section '{}' does not exist!".format(sectname)) + if optname is not None and optname not in configdata.DATA[sectname]: + raise NoOptionError("Option '{}' does not exist in section " + "'{}'!".format(optname, sectname)) + change_handlers.append(ChangeHandler(func, sectname, optname)) + + def get(*args, **kwargs): """Convenience method to call get(...) of the config instance.""" return objreg.get('config').get(*args, **kwargs) @@ -102,6 +131,8 @@ def init(args): objreg.register('key-config', key_config) state_config = iniparsers.ReadWriteConfigParser(confdir, 'state') objreg.register('state-config', state_config) + # We need to import this here because lineparser needs config. + from qutebrowser.config import lineparser command_history = lineparser.LineConfigParser( confdir, 'cmd_history', ('completion', 'history-length')) objreg.register('command-history', command_history) @@ -155,8 +186,6 @@ class ConfigManager(QObject): _initialized: Whether the ConfigManager is fully initialized yet. Signals: - changed: Gets emitted when the config has changed. - Args: the changed section, option and new value. style_changed: When style caches need to be invalidated. Args: the changed section and option. """ @@ -164,7 +193,6 @@ class ConfigManager(QObject): KEY_ESCAPE = r'\#[' ESCAPE_CHAR = '\\' - changed = pyqtSignal(str, str) style_changed = pyqtSignal(str, str) def __init__(self, configdir, fname, parent=None): @@ -285,28 +313,42 @@ class ConfigManager(QObject): e.option = k raise - def _emit_changed(self, sectname, optname): - """Emit the appropriate signals for a changed config option.""" + def _changed(self, sectname, optname): + """Notify other objects the config has changed.""" log.misc.debug("Config option changed: {} -> {}".format( sectname, optname)) if sectname in ('colors', 'fonts'): self.style_changed.emit(sectname, optname) - self.changed.emit(sectname, optname) + for handler in change_handlers: + if handler.section is not None and handler.section != sectname: + continue + if handler.option is not None and handler.option != optname: + continue + param_count = len(inspect.signature(handler.func).parameters) + if param_count == 2: + handler.func(sectname, optname) + elif param_count == 1: + handler.func(sectname) + elif param_count == 0: + handler.func() + else: + raise TypeError("Handler {} has invalid signature.".format( + handler.func.__qualname__)) def _after_set(self, changed_sect, changed_opt): """Clean up caches and emit signals after an option has been set.""" self.get.cache_clear() - self._emit_changed(changed_sect, changed_opt) + self._changed(changed_sect, changed_opt) # Options in the same section and ${optname} interpolation. for optname, option in self.sections[changed_sect].items(): if '${' + changed_opt + '}' in option.value(): - self._emit_changed(changed_sect, optname) + self._changed(changed_sect, optname) # Options in any section and ${sectname:optname} interpolation. for sectname, sect in self.sections.items(): for optname, option in sect.items(): if ('${' + changed_sect + ':' + changed_opt + '}' in option.value()): - self._emit_changed(sectname, optname) + self._changed(sectname, optname) def items(self, sectname, raw=True): """Get a list of (optname, value) tuples for a section. diff --git a/qutebrowser/config/lineparser.py b/qutebrowser/config/lineparser.py index ba360f44c..755bbc699 100644 --- a/qutebrowser/config/lineparser.py +++ b/qutebrowser/config/lineparser.py @@ -22,9 +22,8 @@ import os import os.path -from PyQt5.QtCore import pyqtSlot - from qutebrowser.utils import log, utils +from qutebrowser.config import config class LineConfigParser: @@ -58,6 +57,8 @@ class LineConfigParser: else: log.init.debug("Reading config from {}".format(self._configfile)) self.read(self._configfile) + if limit is not None: + config.on_change(self.cleanup_file, *limit) def __repr__(self): return utils.get_repr(self, constructor=True, @@ -98,8 +99,6 @@ class LineConfigParser: if not self.data: log.destroy.debug("No data to save.") return - # We need to import this here because config needs LineConfigParser. - from qutebrowser.config import config limit = -1 if self._limit is None else config.get(*self._limit) if limit == 0: return @@ -113,14 +112,9 @@ class LineConfigParser: with open(self._configfile, 'w', encoding='utf-8') as f: self.write(f, limit) - @pyqtSlot(str, str) - def on_config_changed(self, section, option): + def cleanup_file(self, section, option): """Delete the file if the limit was changed to 0.""" - if self._limit is None: - return - # We need to import this here because config needs LineConfigParser. - from qutebrowser.config import config value = config.get(section, option) - if (section, option) == self._limit and value == 0: + if value == 0: if os.path.exists(self._configfile): os.remove(self._configfile) diff --git a/qutebrowser/config/style.py b/qutebrowser/config/style.py index 4b964c87c..6484cb3c9 100644 --- a/qutebrowser/config/style.py +++ b/qutebrowser/config/style.py @@ -49,8 +49,6 @@ def set_register_stylesheet(obj): """Set the stylesheet for an object based on it's STYLESHEET attribute. Also, register an update when the config is changed. - This isn't really good OOP, but it's the cleanest solution I could think - of. Args: obj: The object to set the stylesheet for and register. @@ -60,11 +58,10 @@ def set_register_stylesheet(obj): log.style.vdebug("stylesheet for {}: {}".format( obj.__class__.__name__, qss)) obj.setStyleSheet(qss) - objreg.get('config').changed.connect(functools.partial( - _update_stylesheet, obj)) + config.on_change(functools.partial(update_stylesheet, obj)) -def _update_stylesheet(obj, _section, _option): +def update_stylesheet(obj): """Update the stylesheet for obj.""" obj.setStyleSheet(get_stylesheet(obj.STYLESHEET)) diff --git a/qutebrowser/config/websettings.py b/qutebrowser/config/websettings.py index ff9ffcd7e..d8c0f3ea5 100644 --- a/qutebrowser/config/websettings.py +++ b/qutebrowser/config/websettings.py @@ -28,7 +28,6 @@ Module attributes: import os.path -from PyQt5.QtCore import pyqtSlot from PyQt5.QtWebKit import QWebSettings from PyQt5.QtCore import QStandardPaths @@ -193,10 +192,10 @@ def init(): for optname, (typ, arg) in section.items(): value = config.get(sectname, optname) _set_setting(typ, arg, value) + config.on_change(update_settings) -@pyqtSlot(str, str) -def on_config_changed(section, option): +def update_settings(section, option): """Update global settings when qwebsettings changed.""" try: typ, arg = MAPPINGS[section][option] diff --git a/qutebrowser/keyinput/basekeyparser.py b/qutebrowser/keyinput/basekeyparser.py index 613796782..92b6148e8 100644 --- a/qutebrowser/keyinput/basekeyparser.py +++ b/qutebrowser/keyinput/basekeyparser.py @@ -348,7 +348,7 @@ class BaseKeyParser(QObject): def on_keyconfig_changed(self, mode): """Re-read the config if a keybinding was changed.""" if self._modename is None: - raise AttributeError("on_config_changed called but no section " + raise AttributeError("on_keyconfig_changed called but no section " "defined!") if mode == self._modename: self.read_config() diff --git a/qutebrowser/keyinput/modeman.py b/qutebrowser/keyinput/modeman.py index 92a8a6dd6..192c768e3 100644 --- a/qutebrowser/keyinput/modeman.py +++ b/qutebrowser/keyinput/modeman.py @@ -24,7 +24,7 @@ Module attributes: """ from PyQt5.QtGui import QWindow -from PyQt5.QtCore import pyqtSignal, pyqtSlot, QObject, QEvent +from PyQt5.QtCore import pyqtSignal, QObject, QEvent from PyQt5.QtWidgets import QApplication from qutebrowser.keyinput import modeparsers, keyparser @@ -131,8 +131,10 @@ class ModeManager(QObject): self.passthrough = [] self._mode_stack = [] self._releaseevents_to_pass = [] - self._forward_unbound_keys = config.get('input', - 'forward-unbound-keys') + self._forward_unbound_keys = config.get( + 'input', 'forward-unbound-keys') + config.on_change(self.set_forward_unbound_keys, 'input', + 'forward-unbound-keys') def __repr__(self): return utils.get_repr(self, mode=self.mode(), locked=self.locked, @@ -287,12 +289,10 @@ class ModeManager(QObject): raise ValueError("Can't leave normal mode!") self.leave(self.mode(), 'leave current') - @pyqtSlot(str, str) - def on_config_changed(self, section, option): + def set_forward_unbound_keys(self): """Update local setting when config changed.""" - if (section, option) == ('input', 'forward-unbound-keys'): - self._forward_unbound_keys = config.get('input', - 'forward-unbound-keys') + self._forward_unbound_keys = config.get( + 'input', 'forward-unbound-keys') def eventFilter(self, obj, event): """Filter all events based on the currently set mode. diff --git a/qutebrowser/models/completion.py b/qutebrowser/models/completion.py index d15096d7c..98bf46635 100644 --- a/qutebrowser/models/completion.py +++ b/qutebrowser/models/completion.py @@ -19,7 +19,7 @@ """CompletionModels for different usages.""" -from PyQt5.QtCore import pyqtSlot, Qt +from PyQt5.QtCore import Qt from qutebrowser.config import config, configdata from qutebrowser.models import basecompletion @@ -46,7 +46,6 @@ class SettingOptionCompletionModel(basecompletion.BaseCompletionModel): """A CompletionModel filled with settings and their descriptions. Attributes: - _section: The section of this model. _misc_items: A dict of the misc. column items which will be set later. """ @@ -57,7 +56,7 @@ class SettingOptionCompletionModel(basecompletion.BaseCompletionModel): cat = self.new_category(section) sectdata = configdata.DATA[section] self._misc_items = {} - self._section = section + config.on_change(self.update_misc_column, section) for name in sectdata.keys(): try: desc = sectdata.descriptions[name] @@ -72,11 +71,8 @@ class SettingOptionCompletionModel(basecompletion.BaseCompletionModel): value) self._misc_items[name] = miscitem - @pyqtSlot(str, str) - def on_config_changed(self, section, option): + def update_misc_column(self, section, option): """Update misc column when config changed.""" - if section != self._section: - return try: item = self._misc_items[option] except KeyError: @@ -95,19 +91,13 @@ class SettingOptionCompletionModel(basecompletion.BaseCompletionModel): class SettingValueCompletionModel(basecompletion.BaseCompletionModel): - """A CompletionModel filled with setting values. - - Attributes: - _section: The section of this model. - _option: The option of this model. - """ + """A CompletionModel filled with setting values.""" # pylint: disable=abstract-method def __init__(self, section, option=None, parent=None): super().__init__(parent) - self._section = section - self._option = option + config.on_change(self.update_current_value, section, option) cur_cat = self.new_category("Current", sort=0) value = config.get(section, option, raw=True) if not value: @@ -128,11 +118,8 @@ class SettingValueCompletionModel(basecompletion.BaseCompletionModel): for (val, desc) in vals: self.new_item(cat, val, desc) - @pyqtSlot(str, str) - def on_config_changed(self, section, option): + def update_current_value(self, section, option): """Update current value when config changed.""" - if (section, option) != (self._section, self._option): - return value = config.get(section, option, raw=True) if not value: value = '""' diff --git a/qutebrowser/utils/completer.py b/qutebrowser/utils/completer.py index 8f5136bc5..99611dde8 100644 --- a/qutebrowser/utils/completer.py +++ b/qutebrowser/utils/completer.py @@ -74,7 +74,6 @@ class Completer(QObject): def _init_setting_completions(self): """Initialize setting completion models.""" - config_obj = objreg.get('config') self._models[usertypes.Completion.section] = CFM( models.SettingSectionCompletionModel(self), self) self._models[usertypes.Completion.option] = {} @@ -83,13 +82,11 @@ class Completer(QObject): model = models.SettingOptionCompletionModel(sectname, self) self._models[usertypes.Completion.option][sectname] = CFM( model, self) - config_obj.changed.connect(model.on_config_changed) self._models[usertypes.Completion.value][sectname] = {} for opt in configdata.DATA[sectname].keys(): model = models.SettingValueCompletionModel(sectname, opt, self) self._models[usertypes.Completion.value][sectname][opt] = CFM( model, self) - config_obj.changed.connect(model.on_config_changed) def _get_new_completion(self, parts, cursor_part): """Get a new completion model. diff --git a/qutebrowser/widgets/completion.py b/qutebrowser/widgets/completion.py index 5598520fa..73d56b6f2 100644 --- a/qutebrowser/widgets/completion.py +++ b/qutebrowser/widgets/completion.py @@ -95,6 +95,9 @@ class CompletionView(QTreeView): completer_obj = completer.Completer() objreg.register('completer', completer_obj) self.enabled = config.get('completion', 'show') + config.on_change(self.set_enabled, 'completion', 'show') + # FIXME + #config.on_change(self.init_command_completion, 'aliases') self._delegate = completiondelegate.CompletionItemDelegate(self) self.setItemDelegate(self._delegate) @@ -195,13 +198,9 @@ class CompletionView(QTreeView): if config.get('completion', 'shrink'): self.resize_completion.emit() - @pyqtSlot(str, str) - def on_config_changed(self, section, option): + def set_enabled(self): """Update self.enabled when the config changed.""" - if section == 'completion' and option == 'show': - self.enabled = config.get('completion', 'show') - elif section == 'aliases': - self._init_command_completion() + self.enabled = config.get('completion', 'show') @pyqtSlot() def on_clear_completion_selection(self): diff --git a/qutebrowser/widgets/console.py b/qutebrowser/widgets/console.py index 65b203090..d433c705d 100644 --- a/qutebrowser/widgets/console.py +++ b/qutebrowser/widgets/console.py @@ -51,7 +51,8 @@ class ConsoleLineEdit(misc.CommandLineEdit): sys.ps2 = '... ' super().__init__(parent) self.set_prompt(sys.ps1) - self.setFont(config.get('fonts', 'debug-console')) + self.update_font() + config.on_change(self.update_font, 'fonts', 'debug-console') self._more = False self._buffer = [] interpreter_locals = { @@ -144,10 +145,9 @@ class ConsoleLineEdit(misc.CommandLineEdit): else: super().keyPressEvent(e) - def on_config_changed(self, section, option): - """Update font when config changed.""" - if section == 'fonts' and option == 'debug-console': - self.setFont(config.get('fonts', 'debug-console')) + def update_font(self): + """Set the correct font.""" + self.setFont(config.get('fonts', 'debug-console')) class ConsoleTextEdit(QTextEdit): @@ -158,16 +158,16 @@ class ConsoleTextEdit(QTextEdit): super().__init__(parent) self.setAcceptRichText(False) self.setReadOnly(True) - self.setFont(config.get('fonts', 'debug-console')) + config.on_change(self.update_font, 'fonts', 'debug-console') + self.update_font() self.setFocusPolicy(Qt.NoFocus) def __repr__(self): return utils.get_repr(self) - def on_config_changed(self, section, option): + def update_font(self): """Update font when config changed.""" - if section == 'fonts' and option == 'debug-console': - self.setFont(config.get('fonts', 'debug-console')) + self.setFont(config.get('fonts', 'debug-console')) class ConsoleWidget(QWidget): @@ -194,9 +194,3 @@ class ConsoleWidget(QWidget): def __repr__(self): return utils.get_repr(self, visible=self.isVisible()) - - @pyqtSlot(str, str) - def on_config_changed(self, section, option): - """Update font when config changed.""" - self._lineedit.on_config_changed(section, option) - self._output.on_config_changed(section, option) diff --git a/qutebrowser/widgets/mainwindow.py b/qutebrowser/widgets/mainwindow.py index e3086719e..d8dd81601 100644 --- a/qutebrowser/widgets/mainwindow.py +++ b/qutebrowser/widgets/mainwindow.py @@ -95,6 +95,9 @@ class MainWindow(QWidget): # resizing will fail. Therefore, we use singleShot QTimers to make sure # we defer this until everything else is initialized. QTimer.singleShot(0, self._connect_resize_completion) + config.on_change(self.resize_completion, 'completion', 'height') + config.on_change(self.resize_completion, 'completion', 'shrink') + #self.retranslateUi(MainWindow) #self.tabWidget.setCurrentIndex(0) #QtCore.QMetaObject.connectSlotsByName(MainWindow) @@ -111,12 +114,6 @@ class MainWindow(QWidget): """Set some sensible default geometry.""" self.setGeometry(QRect(50, 50, 800, 600)) - @pyqtSlot(str, str) - def on_config_changed(self, section, option): - """Resize completion if config changed.""" - if section == 'completion' and option in ('height', 'shrink'): - self.resize_completion() - @pyqtSlot() def resize_completion(self): """Adjust completion according to config.""" diff --git a/qutebrowser/widgets/statusbar/bar.py b/qutebrowser/widgets/statusbar/bar.py index e9920f972..920221b52 100644 --- a/qutebrowser/widgets/statusbar/bar.py +++ b/qutebrowser/widgets/statusbar/bar.py @@ -141,8 +141,9 @@ class StatusBar(QWidget): self._timer_was_active = False self._text_queue = collections.deque() self._text_pop_timer = usertypes.Timer(self, 'statusbar_text_pop') - self._text_pop_timer.setInterval(config.get('ui', 'message-timeout')) self._text_pop_timer.timeout.connect(self._pop_text) + self.set_pop_timer_interval() + config.on_change(self.set_pop_timer_interval, 'ui', 'message-timeout') self.prompt = prompt.Prompt() self._stack.addWidget(self.prompt) @@ -391,12 +392,9 @@ class StatusBar(QWidget): if mode == usertypes.KeyMode.insert: self._set_insert_active(False) - @pyqtSlot(str, str) - def on_config_changed(self, section, option): + def set_pop_timer_interval(self): """Update message timeout when config changed.""" - if section == 'ui' and option == 'message-timeout': - self._text_pop_timer.setInterval(config.get('ui', - 'message-timeout')) + self._text_pop_timer.setInterval(config.get('ui', 'message-timeout')) def resizeEvent(self, e): """Extend resizeEvent of QWidget to emit a resized signal afterwards. diff --git a/qutebrowser/widgets/statusbar/text.py b/qutebrowser/widgets/statusbar/text.py index 1ad3b354f..fc26bd9a3 100644 --- a/qutebrowser/widgets/statusbar/text.py +++ b/qutebrowser/widgets/statusbar/text.py @@ -46,6 +46,7 @@ class Text(textbase.TextBase): self._normaltext = '' self._temptext = '' self._jstext = '' + config.on_change(self.update_text, 'ui', 'display-statusbar-messages') def set_text(self, which, text): """Set a text. @@ -64,7 +65,7 @@ class Text(textbase.TextBase): self._jstext = text else: raise ValueError("Invalid value {} for which!".format(which)) - self._update_text() + self.update_text() @pyqtSlot(str) def maybe_reset_text(self, text): @@ -75,7 +76,7 @@ class Text(textbase.TextBase): else: log.misc.debug("Ignoring reset: '{}'".format(text)) - def _update_text(self): + def update_text(self): """Update QLabel text when needed.""" if self._temptext: self.setText(self._temptext) @@ -100,9 +101,3 @@ class Text(textbase.TextBase): def on_tab_changed(self, tab): """Set the correct jstext when the current tab changed.""" self._jstext = tab.statusbar_message - - @pyqtSlot(str, str) - def on_config_changed(self, section, option): - """Update text if display-statusbar-messages option changed.""" - if (section, option) == ('ui', 'display-statusbar-messages'): - self._update_text() diff --git a/qutebrowser/widgets/tabbedbrowser.py b/qutebrowser/widgets/tabbedbrowser.py index b969d3bf4..1b814978f 100644 --- a/qutebrowser/widgets/tabbedbrowser.py +++ b/qutebrowser/widgets/tabbedbrowser.py @@ -113,6 +113,7 @@ class TabbedBrowser(tabwidget.TabWidget): self._now_focused = None # FIXME adjust this to font size self.setIconSize(QSize(12, 12)) + config.on_change(self.update_favicons, 'tabs', 'show-favicons') def __repr__(self): return utils.get_repr(self, count=self.count()) @@ -381,19 +382,14 @@ class TabbedBrowser(tabwidget.TabWidget): # We first want QWebPage to refresh. QTimer.singleShot(0, check_scroll_pos) - @pyqtSlot(str, str) - def on_config_changed(self, section, option): - """Update tab config when config was changed.""" - super().on_config_changed(section, option) - for tab in self._tabs: - tab.on_config_changed(section, option) - if (section, option) == ('tabs', 'show-favicons'): - show = config.get('tabs', 'show-favicons') - for i, tab in enumerate(self.widgets()): - if show: - self.setTabIcon(i, tab.icon()) - else: - self.setTabIcon(i, QIcon()) + def update_favicons(self): + """Update favicons when config was changed.""" + show = config.get('tabs', 'show-favicons') + for i, tab in enumerate(self.widgets()): + if show: + self.setTabIcon(i, tab.icon()) + else: + self.setTabIcon(i, QIcon()) @pyqtSlot() def on_load_started(self, tab): diff --git a/qutebrowser/widgets/tabwidget.py b/qutebrowser/widgets/tabwidget.py index 4ab4cde6b..354519f7b 100644 --- a/qutebrowser/widgets/tabwidget.py +++ b/qutebrowser/widgets/tabwidget.py @@ -26,7 +26,7 @@ Module attributes: import functools -from PyQt5.QtCore import pyqtSlot, Qt, QSize, QRect, QPoint, QTimer +from PyQt5.QtCore import Qt, QSize, QRect, QPoint, QTimer from PyQt5.QtWidgets import (QTabWidget, QTabBar, QSizePolicy, QCommonStyle, QStyle, QStylePainter, QStyleOptionTab) from PyQt5.QtGui import QIcon, QPalette, QColor @@ -52,9 +52,10 @@ class TabWidget(QTabWidget): self.setElideMode(Qt.ElideRight) self.setUsesScrollButtons(True) bar.setDrawBase(False) - self._init_config() + self.init_config() + config.on_change(self.init_config, 'tabs') - def _init_config(self): + def init_config(self): """Initialize attributes based on the config.""" position_conv = { 'north': QTabWidget.North, @@ -78,13 +79,6 @@ class TabWidget(QTabWidget): tabbar.setSelectionBehaviorOnRemove(select_conv[selstr]) tabbar.refresh() - @pyqtSlot(str, str) - def on_config_changed(self, section, option): - """Update attributes when config changed.""" - self.tabBar().on_config_changed(section, option) - if section == 'tabs': - self._init_config() - class TabBar(QTabBar): @@ -101,18 +95,19 @@ class TabBar(QTabBar): def __init__(self, parent=None): super().__init__(parent) self.setStyle(TabBarStyle(self.style())) - self.setFont(config.get('fonts', 'tabbar')) + self.set_font() + config.on_change(self.set_font, 'fonts', 'tabbar') self.vertical = False self.setAutoFillBackground(True) - p = self.palette() - p.setColor(QPalette.Window, config.get('colors', 'tab.bg.bar')) - self.setPalette(p) - QTimer.singleShot(0, self._autohide) + self.set_colors() + config.on_change(self.set_colors, 'colors', 'tab.bg.bar') + QTimer.singleShot(0, self.autohide) + config.on_change(self.autohide, 'tabs', 'auto-hide') def __repr__(self): return utils.get_repr(self, count=self.count()) - def _autohide(self): + def autohide(self): """Auto-hide the tabbar if needed.""" auto_hide = config.get('tabs', 'auto-hide') if auto_hide and self.count() == 1: @@ -136,17 +131,15 @@ class TabBar(QTabBar): self.setTabData(idx, color) self.update(self.tabRect(idx)) - @pyqtSlot(str, str) - def on_config_changed(self, section, option): - """Update attributes when config changed.""" - if section == 'fonts' and option == 'tabbar': - self.setFont(config.get('fonts', 'tabbar')) - elif section == 'colors' and option == 'tab.bg.bar': - p = self.palette() - p.setColor(QPalette.Window, config.get('colors', 'tab.bg.bar')) - self.setPalette(p) - elif section == 'tabs' and option == 'auto-hide': - self._autohide() + def set_font(self): + """Set the tabbar font.""" + self.setFont(config.get('fonts', 'tabbar')) + + def set_colors(self): + """Set the tabbar colors.""" + p = self.palette() + p.setColor(QPalette.Window, config.get('colors', 'tab.bg.bar')) + self.setPalette(p) def mousePressEvent(self, e): """Override mousePressEvent to close tabs if configured.""" @@ -256,12 +249,12 @@ class TabBar(QTabBar): def tabInserted(self, idx): """Show the tabbar if configured to hide and >1 tab is open.""" - self._autohide() + self.autohide() super().tabInserted(idx) def tabRemoved(self, idx): """Hide the tabbar if configured when only one tab is open.""" - self._autohide() + self.autohide() super().tabRemoved(idx) diff --git a/qutebrowser/widgets/webview.py b/qutebrowser/widgets/webview.py index b9b6eceee..71cbfab37 100644 --- a/qutebrowser/widgets/webview.py +++ b/qutebrowser/widgets/webview.py @@ -91,7 +91,9 @@ class WebView(QWebView): self._force_open_target = None self._zoom = None self._has_ssl_errors = False - self._init_neighborlist() + self.init_neighborlist() + config.on_change(self.init_neighborlist, 'ui', 'zoom-levels') + config.on_change(self.init_neighborlist, 'ui', 'default-zoom') self._cur_url = None self.cur_url = QUrl() self.progress = 0 @@ -133,7 +135,7 @@ class WebView(QWebView): self.load_status = val self.load_status_changed.emit(val.name) - def _init_neighborlist(self): + def init_neighborlist(self): """Initialize the _zoom neighborlist.""" levels = config.get('ui', 'zoom-levels') default = config.get('ui', 'default-zoom') @@ -333,12 +335,6 @@ class WebView(QWebView): self.cur_url = url self.url_text_changed.emit(url.toDisplayString()) - @pyqtSlot(str, str) - def on_config_changed(self, section, option): - """Update tab config when config was changed.""" - if section == 'ui' and option in ('zoom-levels', 'default-zoom'): - self._init_neighborlist() - @pyqtSlot('QMouseEvent') def on_mouse_event(self, evt): """Post a new mouseevent from a hintmanager."""