diff --git a/qutebrowser/app.py b/qutebrowser/app.py index a89c97080..1e398ffb0 100644 --- a/qutebrowser/app.py +++ b/qutebrowser/app.py @@ -47,6 +47,7 @@ from PyQt5.QtCore import pyqtSlot, QTimer, QEventLoop import qutebrowser import qutebrowser.commands.utils as cmdutils +import qutebrowser.config.style as style import qutebrowser.config.config as config import qutebrowser.network.qutescheme as qutescheme import qutebrowser.utils.message as message @@ -130,10 +131,11 @@ class QuteBrowser(QApplication): self.mainwindow.status.keystring.setText) message.bridge.error.connect(self.mainwindow.status.disp_error) message.bridge.info.connect(self.mainwindow.status.disp_tmp_text) + self.config.style_changed.connect(style.invalidate_caches) self.config.changed.connect(self.mainwindow.tabs.on_config_changed) self.config.changed.connect( self.mainwindow.completion.on_config_changed) - self.config.changed.connect(self.mainwindow.resize_completion) + self.config.changed.connect(self.mainwindow.on_config_changed) self.mainwindow.show() self._python_hacks() diff --git a/qutebrowser/config/config.py b/qutebrowser/config/config.py index 44702bd45..6f34d1ffc 100644 --- a/qutebrowser/config/config.py +++ b/qutebrowser/config/config.py @@ -86,9 +86,12 @@ class Config(QObject): Signals: changed: Gets emitted when the config has changed. Args: the changed section and option. + style_changed: When style caches need to be invalidated. + Args: the changed section and option. """ changed = pyqtSignal(str, str) + style_changed = pyqtSignal(str, str) def __init__(self, configdir, fname, parent=None): super().__init__(parent) @@ -287,6 +290,7 @@ class Config(QObject): Emit: changed: If the config was changed. + style_changed: When style caches need to be invalidated. """ if value: value = self._interpolation.before_set(self, section, option, @@ -300,6 +304,8 @@ class Config(QObject): except KeyError: raise NoOptionError(option, section) else: + if section in ['colors', 'fonts']: + self.style_changed.emit(section, option) self.changed.emit(section, option) def save(self): diff --git a/qutebrowser/config/style.py b/qutebrowser/config/style.py index cae46c947..a5db4f791 100644 --- a/qutebrowser/config/style.py +++ b/qutebrowser/config/style.py @@ -17,6 +17,8 @@ """Utilities related to the look&feel of qutebrowser.""" +from functools import partial + import qutebrowser.config.config as config _colordict = None @@ -40,6 +42,31 @@ def get_stylesheet(template): return template.strip().format(color=_colordict, font=_fontdict) +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. + """ + obj.setStyleSheet(get_stylesheet(obj.STYLESHEET)) + config.config.changed.connect(partial(_update_stylesheet, obj)) + + +def _update_stylesheet(obj, section, option): + """Update the stylesheet for obj.""" + # pylint: disable=unused-argument + obj.setStyleSheet(get_stylesheet(obj.STYLESHEET)) + + +def invalidate_caches(section, option): + """Invalidate cached dicts.""" + # pylint: disable=unused-argument + global _colordict, _fontdict + if section == 'colors': + _colordict = None + elif section == 'fonts': + _fontdict = None + + class ColorDict(dict): """A dict aimed at Qt stylesheet colors.""" diff --git a/qutebrowser/widgets/completion.py b/qutebrowser/widgets/completion.py index e03bbd3f9..efd5b9f43 100644 --- a/qutebrowser/widgets/completion.py +++ b/qutebrowser/widgets/completion.py @@ -35,7 +35,7 @@ import qutebrowser.config.config as config import qutebrowser.commands.utils as cmdutils from qutebrowser.config.configdata import configdata from qutebrowser.models.completion import ROLE_MARKS -from qutebrowser.config.style import get_stylesheet +from qutebrowser.config.style import set_register_stylesheet, get_stylesheet from qutebrowser.commands.parsers import split_cmdline from qutebrowser.models.completionfilter import CompletionFilterModel from qutebrowser.models.commandcompletion import CommandCompletionModel @@ -55,7 +55,7 @@ class CompletionView(QTreeView): Attributes: _model: The currently active filter model. _lastmodel: The model set in the last iteration. - _STYLESHEET: The stylesheet template for the CompletionView. + STYLESHEET: The stylesheet template for the CompletionView. _completion_models: dict of available completion models. _ignore_next: Whether to ignore the next cmd_text_changed signal. _enabled: Whether showing the CompletionView is enabled. @@ -69,7 +69,7 @@ class CompletionView(QTreeView): we're currently completing. """ - _STYLESHEET = """ + STYLESHEET = """ QTreeView {{ {font[completion]} {color[completion.fg]} @@ -119,7 +119,7 @@ class CompletionView(QTreeView): self._delegate = _CompletionItemDelegate(self) self.setItemDelegate(self._delegate) - self.setStyleSheet(get_stylesheet(self._STYLESHEET)) + set_register_stylesheet(self) self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Minimum) self.setHeaderHidden(True) self.setIndentation(0) diff --git a/qutebrowser/widgets/mainwindow.py b/qutebrowser/widgets/mainwindow.py index 488fdd538..6e08bef9c 100644 --- a/qutebrowser/widgets/mainwindow.py +++ b/qutebrowser/widgets/mainwindow.py @@ -97,6 +97,11 @@ class MainWindow(QWidget): #self.tabWidget.setCurrentIndex(0) #QtCore.QMetaObject.connectSlotsByName(MainWindow) + def on_config_changed(self, section, option): + """Resize completion if config changed.""" + if section == 'general' and option == 'completion_height': + self.resize_completion() + def resize_completion(self): """Adjust completion according to config.""" confheight = str(config.config.get('general', 'completion_height')) diff --git a/qutebrowser/widgets/statusbar.py b/qutebrowser/widgets/statusbar.py index be98592e2..6fa7a8105 100644 --- a/qutebrowser/widgets/statusbar.py +++ b/qutebrowser/widgets/statusbar.py @@ -25,7 +25,7 @@ from PyQt5.QtWidgets import (QWidget, QLineEdit, QProgressBar, QLabel, QShortcut) from PyQt5.QtGui import QPainter, QKeySequence, QValidator -from qutebrowser.config.style import get_stylesheet +from qutebrowser.config.style import set_register_stylesheet, get_stylesheet import qutebrowser.commands.keys as keys from qutebrowser.utils.url import urlstring from qutebrowser.utils.usertypes import NeighborList @@ -47,7 +47,7 @@ class StatusBar(QWidget): _stack: The QStackedLayout with cmd/txt widgets. _error: If there currently is an error, accessed through the error property. - _STYLESHEET: The stylesheet template. + STYLESHEET: The stylesheet template. Signals: resized: Emitted when the statusbar has resized, so the completion @@ -60,7 +60,7 @@ class StatusBar(QWidget): resized = pyqtSignal('QRect') moved = pyqtSignal('QPoint') - _STYLESHEET = """ + STYLESHEET = """ QWidget#StatusBar[error="false"] {{ {color[statusbar.bg]} }} @@ -79,7 +79,7 @@ class StatusBar(QWidget): super().__init__(parent) self.setObjectName(self.__class__.__name__) self.setAttribute(Qt.WA_StyledBackground) - self.setStyleSheet(get_stylesheet(self._STYLESHEET)) + set_register_stylesheet(self) self.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Fixed) @@ -132,7 +132,7 @@ class StatusBar(QWidget): updated by Qt properly. """ self._error = val - self.setStyleSheet(get_stylesheet(self._STYLESHEET)) + self.setStyleSheet(get_stylesheet(self.STYLESHEET)) def _show_cmd_widget(self): """Show command widget instead of temporary text.""" @@ -429,11 +429,11 @@ class _Progress(QProgressBar): """The progress bar part of the status bar. Attributes: - _STYLESHEET: The stylesheet template. + STYLESHEET: The stylesheet template. """ # FIXME for some reason, margin-left is not shown - _STYLESHEET = """ + STYLESHEET = """ QProgressBar {{ border-radius: 0px; border: 2px solid transparent; @@ -448,7 +448,7 @@ class _Progress(QProgressBar): def __init__(self, parent): super().__init__(parent) - self.setStyleSheet(get_stylesheet(self._STYLESHEET)) + set_register_stylesheet(self) self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Ignored) self.setTextVisible(False) self.hide() @@ -618,10 +618,10 @@ class _Url(TextBase): _old_urltype: The type of the URL displayed before the hover URL. _urltype: The current URL type. One of normal/ok/error/warn/hover. Accessed via the urltype property. - _STYLESHEET: The stylesheet template. + STYLESHEET: The stylesheet template. """ - _STYLESHEET = """ + STYLESHEET = """ QLabel#Url[urltype="normal"] {{ {color[statusbar.url.fg]} }} @@ -652,7 +652,7 @@ class _Url(TextBase): """ super().__init__(bar, elidemode) self.setObjectName(self.__class__.__name__) - self.setStyleSheet(get_stylesheet(self._STYLESHEET)) + set_register_stylesheet(self) self._urltype = None self._old_urltype = None self._old_url = None @@ -667,7 +667,7 @@ class _Url(TextBase): def urltype(self, val): """Setter for self.urltype, so it can be used as Qt property.""" self._urltype = val - self.setStyleSheet(get_stylesheet(self._STYLESHEET)) + self.setStyleSheet(get_stylesheet(self.STYLESHEET)) @pyqtSlot(bool) def on_loading_finished(self, ok): diff --git a/qutebrowser/widgets/tabbar.py b/qutebrowser/widgets/tabbar.py index 98f3ea562..ff0edb97b 100644 --- a/qutebrowser/widgets/tabbar.py +++ b/qutebrowser/widgets/tabbar.py @@ -17,11 +17,11 @@ """The tab widget used for TabbedBrowser from browser.py.""" -from PyQt5.QtCore import Qt +from PyQt5.QtCore import pyqtSlot, Qt from PyQt5.QtWidgets import QTabWidget, QTabBar, QSizePolicy import qutebrowser.config.config as config -from qutebrowser.config.style import get_stylesheet +from qutebrowser.config.style import set_register_stylesheet from qutebrowser.utils.style import Style @@ -30,13 +30,13 @@ class TabWidget(QTabWidget): """The tabwidget used for TabbedBrowser. Attributes: - _STYLESHEET: The stylesheet template to be used. + STYLESHEET: The stylesheet template to be used. """ # FIXME there is still some ugly 1px white stripe from somewhere if we do # background-color: grey for QTabBar... - _STYLESHEET = """ + STYLESHEET = """ QTabWidget::pane {{ position: absolute; top: 0px; @@ -68,7 +68,7 @@ class TabWidget(QTabWidget): super().__init__(parent) self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) self.setStyle(Style(self.style())) - self.setStyleSheet(get_stylesheet(self._STYLESHEET)) + set_register_stylesheet(self) self.setDocumentMode(True) self.setElideMode(Qt.ElideRight) self._init_config() @@ -96,3 +96,10 @@ class TabWidget(QTabWidget): self.tabBar().setSelectionBehaviorOnRemove(select_conv[selstr]) except KeyError: pass + + @pyqtSlot(str, str) + def on_config_changed(self, section, option): + """Update attributes when config changed.""" + # pylint: disable=unused-argument + if section == 'tabbar': + self._init_config() diff --git a/qutebrowser/widgets/tabbedbrowser.py b/qutebrowser/widgets/tabbedbrowser.py index 36d946864..94d10defd 100644 --- a/qutebrowser/widgets/tabbedbrowser.py +++ b/qutebrowser/widgets/tabbedbrowser.py @@ -142,6 +142,7 @@ class TabbedBrowser(TabWidget): @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)