Move config.style into config.config and refactor it

This commit is contained in:
Florian Bruhin 2017-07-02 16:05:04 +02:00
parent 81d6406e14
commit 28670f8e48
17 changed files with 153 additions and 161 deletions

View File

@ -44,7 +44,7 @@ import qutebrowser
import qutebrowser.resources
from qutebrowser.completion.models import instances as completionmodels
from qutebrowser.commands import cmdutils, runners, cmdexc
from qutebrowser.config import style, config, websettings, configexc
from qutebrowser.config import config, websettings, configexc
from qutebrowser.browser import (urlmarks, adblock, history, browsertab,
downloads)
from qutebrowser.browser.network import proxy

View File

@ -26,7 +26,7 @@ from PyQt5.QtCore import pyqtSlot, QSize, Qt, QTimer
from PyQt5.QtWidgets import QListView, QSizePolicy, QMenu, QStyleFactory
from qutebrowser.browser import downloads
from qutebrowser.config import style
from qutebrowser.config import config
from qutebrowser.utils import qtutils, utils, objreg
@ -76,7 +76,7 @@ class DownloadView(QListView):
def __init__(self, win_id, parent=None):
super().__init__(parent)
self.setStyle(QStyleFactory.create('Fusion'))
style.set_register_stylesheet(self)
config.set_register_stylesheet(self)
self.setResizeMode(QListView.Adjust)
self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Fixed)

View File

@ -29,7 +29,7 @@ from string import ascii_lowercase
from PyQt5.QtCore import pyqtSlot, QObject, Qt, QUrl
from PyQt5.QtWidgets import QLabel
from qutebrowser.config import config, style
from qutebrowser.config import config
from qutebrowser.keyinput import modeman, modeparsers
from qutebrowser.browser import webelem
from qutebrowser.commands import userscripts, cmdexc, cmdutils, runners
@ -80,7 +80,7 @@ class HintLabel(QLabel):
self.elem = elem
self.setAttribute(Qt.WA_StyledBackground, True)
style.set_register_stylesheet(self)
config.set_register_stylesheet(self)
self._context.tab.contents_size_changed.connect(self._move_to_elem)
self._move_to_elem()

View File

@ -30,8 +30,8 @@ from PyQt5.QtCore import QRectF, QSize, Qt
from PyQt5.QtGui import (QIcon, QPalette, QTextDocument, QTextOption,
QAbstractTextDocumentLayout)
from qutebrowser.config import config, style
from qutebrowser.utils import qtutils
from qutebrowser.config import config
from qutebrowser.utils import qtutils, jinja
class CompletionItemDelegate(QStyledItemDelegate):
@ -187,12 +187,15 @@ class CompletionItemDelegate(QStyledItemDelegate):
self._doc = QTextDocument(self)
self._doc.setDefaultFont(self._opt.font)
self._doc.setDefaultTextOption(text_option)
self._doc.setDefaultStyleSheet(style.get_stylesheet("""
self._doc.setDocumentMargin(2)
stylesheet = """
.highlight {
color: {{ conf.colors.completion.match.fg }};
}
"""))
self._doc.setDocumentMargin(2)
"""
template = jinja.environment.from_string(stylesheet)
self._doc.setDefaultStyleSheet(template.render(conf=config.val))
if index.parent().isValid():
pattern = index.model().pattern

View File

@ -26,7 +26,7 @@ subclasses to provide completions.
from PyQt5.QtWidgets import QStyle, QTreeView, QSizePolicy, QStyleFactory
from PyQt5.QtCore import pyqtSlot, pyqtSignal, Qt, QItemSelectionModel, QSize
from qutebrowser.config import config, style
from qutebrowser.config import config
from qutebrowser.completion import completiondelegate
from qutebrowser.completion.models import base
from qutebrowser.utils import utils, usertypes
@ -118,7 +118,7 @@ class CompletionView(QTreeView):
self._delegate = completiondelegate.CompletionItemDelegate(self)
self.setItemDelegate(self._delegate)
self.setStyle(QStyleFactory.create('Fusion'))
style.set_register_stylesheet(self)
config.set_register_stylesheet(self)
self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
self.setHeaderHidden(True)
self.setAlternatingRowColors(True)

View File

@ -24,11 +24,12 @@ import os.path
import contextlib
import functools
from PyQt5.QtCore import pyqtSignal, QObject, QUrl
import sip
from PyQt5.QtCore import pyqtSignal, pyqtSlot, QObject, QUrl
from qutebrowser.config import configdata, configexc, configtypes, configfiles
from qutebrowser.utils import (utils, objreg, message, standarddir, log,
usertypes)
usertypes, jinja)
from qutebrowser.commands import cmdexc, cmdutils, runners
@ -539,6 +540,67 @@ class ConfigContainer:
return attr
def set_register_stylesheet(obj, *, stylesheet=None, update=True):
"""Set the stylesheet for an object based on it's STYLESHEET attribute.
Also, register an update when the config is changed.
Args:
obj: The object to set the stylesheet for and register.
Must have a STYLESHEET attribute if stylesheet is not given.
stylesheet: The stylesheet to use.
update: Whether to update the stylesheet on config changes.
"""
observer = StyleSheetObserver(obj, stylesheet=stylesheet)
observer.register(update=update)
class StyleSheetObserver(QObject):
"""Set the stylesheet on the given object and update it on changes.
Attributes:
_obj: The object to observe.
_stylesheet: The stylesheet template to use.
"""
def __init__(self, obj, stylesheet):
super().__init__(parent=obj)
self._obj = obj
if stylesheet is None:
self._stylesheet = obj.STYLESHEET
else:
self._stylesheet = stylesheet
def _get_stylesheet(self):
"""Format a stylesheet based on a template.
Return:
The formatted template as string.
"""
template = jinja.environment.from_string(self._stylesheet)
return template.render(conf=val)
@pyqtSlot()
def _update_stylesheet(self):
"""Update the stylesheet for obj."""
if not sip.isdeleted(self._obj):
self._obj.setStyleSheet(self._get_stylesheet())
def register(self, update):
"""Do a first update and listen for more.
Args:
update: if False, don't listen for future updates.
"""
qss = self._get_stylesheet()
log.config.vdebug("stylesheet for {}: {}".format(
self._obj.__class__.__name__, qss))
self._obj.setStyleSheet(qss)
if update:
instance.changed.connect(self._update_stylesheet)
def init(parent=None):
"""Initialize the config.

View File

@ -1,62 +0,0 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2017 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# 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 <http://www.gnu.org/licenses/>.
"""Utilities related to the look&feel of qutebrowser."""
import functools
import sip
from qutebrowser.config import config
from qutebrowser.utils import log, jinja
def get_stylesheet(template_str):
"""Format a stylesheet based on a template.
Args:
template_str: The stylesheet template as string.
Return:
The formatted template as string.
"""
template = jinja.environment.from_string(template_str)
return template.render(conf=config.val)
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.
Args:
obj: The object to set the stylesheet for and register.
Must have a STYLESHEET attribute.
"""
qss = get_stylesheet(obj.STYLESHEET)
log.config.vdebug("stylesheet for {}: {}".format(
obj.__class__.__name__, qss))
obj.setStyleSheet(qss)
config.instance.changed.connect(functools.partial(_update_stylesheet, obj))
def _update_stylesheet(obj):
"""Update the stylesheet for obj."""
if not sip.isdeleted(obj):
obj.setStyleSheet(get_stylesheet(obj.STYLESHEET))

View File

@ -23,7 +23,7 @@
from PyQt5.QtCore import pyqtSlot, pyqtSignal, QTimer, Qt, QSize
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QLabel, QSizePolicy
from qutebrowser.config import config, style
from qutebrowser.config import config
from qutebrowser.utils import usertypes
@ -65,7 +65,7 @@ class Message(QLabel):
raise ValueError("Invalid level {!r}".format(level))
# We don't bother with set_register_stylesheet here as it's short-lived
# anyways.
self.setStyleSheet(style.get_stylesheet(stylesheet))
config.set_register_stylesheet(self, stylesheet=stylesheet, update=False)
class MessageView(QWidget):

View File

@ -30,7 +30,7 @@ from PyQt5.QtWidgets import (QWidget, QGridLayout, QVBoxLayout, QLineEdit,
QLabel, QFileSystemModel, QTreeView, QSizePolicy)
from qutebrowser.browser import downloads
from qutebrowser.config import style, config
from qutebrowser.config import config
from qutebrowser.utils import usertypes, log, utils, qtutils, objreg, message
from qutebrowser.keyinput import modeman
from qutebrowser.commands import cmdutils, cmdexc
@ -268,7 +268,7 @@ class PromptContainer(QWidget):
self.setObjectName('PromptContainer')
self.setAttribute(Qt.WA_StyledBackground, True)
style.set_register_stylesheet(self)
config.set_register_stylesheet(self)
message.global_bridge.prompt_done.connect(self._on_prompt_done)
prompt_queue.show_prompts.connect(self._on_show_prompts)

View File

@ -23,7 +23,7 @@ from PyQt5.QtCore import pyqtSignal, pyqtSlot, pyqtProperty, Qt, QSize, QTimer
from PyQt5.QtWidgets import QWidget, QHBoxLayout, QStackedLayout, QSizePolicy
from qutebrowser.browser import browsertab
from qutebrowser.config import config, style
from qutebrowser.config import config
from qutebrowser.utils import usertypes, log, objreg, utils
from qutebrowser.mainwindow.statusbar import (command, progress, keystring,
percentage, url, tabindex)
@ -147,7 +147,7 @@ class StatusBar(QWidget):
objreg.register('statusbar', self, scope='window', window=win_id)
self.setObjectName(self.__class__.__name__)
self.setAttribute(Qt.WA_StyledBackground)
style.set_register_stylesheet(self)
config.set_register_stylesheet(self)
self.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Fixed)
@ -259,7 +259,7 @@ class StatusBar(QWidget):
self._color_flags.caret = ColorFlags.CaretMode.on
else:
self._color_flags.caret = ColorFlags.CaretMode.off
self.setStyleSheet(style.get_stylesheet(self.STYLESHEET))
config.set_register_stylesheet(self, update=False)
def _set_mode_text(self, mode):
"""Set the mode text."""

View File

@ -22,7 +22,7 @@
from PyQt5.QtCore import pyqtSlot, QSize
from PyQt5.QtWidgets import QProgressBar, QSizePolicy
from qutebrowser.config import style
from qutebrowser.config import config
from qutebrowser.utils import utils, usertypes
@ -45,7 +45,7 @@ class Progress(QProgressBar):
def __init__(self, parent=None):
super().__init__(parent)
style.set_register_stylesheet(self)
config.set_register_stylesheet(self)
self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
self.setTextVisible(False)
self.hide()

View File

@ -22,7 +22,7 @@
from PyQt5.QtCore import pyqtSlot, pyqtProperty, Qt, QUrl
from qutebrowser.mainwindow.statusbar import textbase
from qutebrowser.config import style
from qutebrowser.config import config
from qutebrowser.utils import usertypes, urlutils
@ -81,7 +81,7 @@ class UrlText(textbase.TextBase):
"""Override TextBase.__init__ to elide in the middle by default."""
super().__init__(parent, Qt.ElideMiddle)
self.setObjectName(self.__class__.__name__)
style.set_register_stylesheet(self)
config.set_register_stylesheet(self)
self._hover_url = None
self._normal_url = None
self._normal_url_type = UrlType.normal
@ -109,7 +109,7 @@ class UrlText(textbase.TextBase):
else:
self.setText('')
self._urltype = UrlType.normal
self.setStyleSheet(style.get_stylesheet(self.STYLESHEET))
config.set_register_stylesheet(self, update=False)
@pyqtSlot(str)
def on_load_status_changed(self, status_str):

View File

@ -30,7 +30,7 @@ import fnmatch
from PyQt5.QtWidgets import QLabel, QSizePolicy
from PyQt5.QtCore import pyqtSlot, pyqtSignal, Qt
from qutebrowser.config import config, style
from qutebrowser.config import config
from qutebrowser.utils import objreg, utils, usertypes
@ -68,7 +68,7 @@ class KeyHintView(QLabel):
self.hide()
self._show_timer = usertypes.Timer(self, 'keyhint_show')
self._show_timer.timeout.connect(self.show)
style.set_register_stylesheet(self)
config.set_register_stylesheet(self)
def __repr__(self):
return utils.get_repr(self, win_id=self._win_id)

View File

@ -37,7 +37,7 @@ from PyQt5.QtWidgets import QApplication # pylint: disable=unused-import
from qutebrowser.browser import qutescheme
from qutebrowser.utils import log, objreg, usertypes, message, debug, utils
from qutebrowser.commands import cmdutils, runners, cmdexc
from qutebrowser.config import style, configdata
from qutebrowser.config import configdata
from qutebrowser.misc import consolewidget

View File

@ -444,9 +444,9 @@ class ConfigStub(QObject):
"""Set a value in the config."""
try:
self.data[name] = value
self.changed.emit(name)
except KeyError:
raise configexc.NoOptionError(name)
self.changed.emit(name)
class UrlMarkManagerStub(QObject):

View File

@ -18,4 +18,62 @@
"""Tests for qutebrowser.config.config."""
import pytest
from PyQt5.QtCore import QObject
from qutebrowser.config import config
class Obj(QObject):
def __init__(self, stylesheet=None, parent=None):
super().__init__(parent)
if stylesheet is not None:
self.STYLESHEET = stylesheet # pylint: disable=invalid-name
self.rendered_stylesheet = None
def setStyleSheet(self, stylesheet):
self.rendered_stylesheet = stylesheet
def test_get_stylesheet(config_stub):
config_stub.val.colors.completion.bg = 'magenta'
observer = config.StyleSheetObserver(
Obj(), stylesheet="{{ conf.colors.completion.bg }}")
assert observer._get_stylesheet() == 'magenta'
@pytest.mark.parametrize('delete', [True, False])
@pytest.mark.parametrize('stylesheet_param', [True, False])
@pytest.mark.parametrize('update', [True, False])
def test_set_register_stylesheet(delete, stylesheet_param, update, qtbot,
config_stub, caplog):
config_stub.val.colors.completion.fg = 'magenta'
stylesheet = "{{ conf.colors.completion.fg }}"
with caplog.at_level(9): # VDEBUG
if stylesheet_param:
obj = Obj()
config.set_register_stylesheet(obj, stylesheet=stylesheet,
update=update)
else:
obj = Obj(stylesheet)
config.set_register_stylesheet(obj, update=update)
assert len(caplog.records) == 1
assert caplog.records[0].message == 'stylesheet for Obj: magenta'
assert obj.rendered_stylesheet == 'magenta'
if delete:
with qtbot.waitSignal(obj.destroyed):
obj.deleteLater()
config_stub.val.colors.completion.fg = 'yellow'
if delete or not update:
expected = 'magenta'
else:
expected = 'yellow'
assert obj.rendered_stylesheet == expected

View File

@ -1,69 +0,0 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2015-2017 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# 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 <http://www.gnu.org/licenses/>.
"""Tests for qutebrowser.config.style."""
import logging
import pytest
from PyQt5.QtCore import QObject
from qutebrowser.config import style
def test_get_stylesheet(config_stub):
config_stub.val.colors.completion.bg = 'magenta'
rendered = style.get_stylesheet("{{ conf.colors.completion.bg }}")
assert rendered == 'magenta'
class Obj(QObject):
def __init__(self, stylesheet, parent=None):
super().__init__(parent)
self.STYLESHEET = stylesheet # pylint: disable=invalid-name
self.rendered_stylesheet = None
def setStyleSheet(self, stylesheet):
self.rendered_stylesheet = stylesheet
@pytest.mark.parametrize('delete', [True, False])
def test_set_register_stylesheet(delete, qtbot, config_stub, caplog):
config_stub.val.colors.completion.fg = 'magenta'
obj = Obj("{{ conf.colors.completion.fg }}")
with caplog.at_level(9): # VDEBUG
style.set_register_stylesheet(obj)
assert len(caplog.records) == 1
assert caplog.records[0].message == 'stylesheet for Obj: magenta'
assert obj.rendered_stylesheet == 'magenta'
if delete:
with qtbot.waitSignal(obj.destroyed):
obj.deleteLater()
config_stub.val.colors.completion.fg = 'yellow'
if delete:
expected = 'magenta'
else:
expected = 'yellow'
assert obj.rendered_stylesheet == expected