diff --git a/qutebrowser/app.py b/qutebrowser/app.py index e72713703..a8aecb562 100644 --- a/qutebrowser/app.py +++ b/qutebrowser/app.py @@ -48,6 +48,7 @@ from PyQt5.QtCore import pyqtSlot, QTimer, QEventLoop import qutebrowser import qutebrowser.commands.utils as cmdutils import qutebrowser.config.config as config +import qutebrowser.config.style as style import qutebrowser.network.qutescheme as qutescheme from qutebrowser.widgets.mainwindow import MainWindow from qutebrowser.widgets.crash import CrashDialog @@ -97,6 +98,7 @@ class QuteBrowser(QApplication): else: confdir = self._args.confdir config.init(confdir) + style.init() self.commandparser = cmdutils.CommandParser() self.searchparser = cmdutils.SearchParser() diff --git a/qutebrowser/config/config.py b/qutebrowser/config/config.py index 9b319545f..f9412b0f1 100644 --- a/qutebrowser/config/config.py +++ b/qutebrowser/config/config.py @@ -28,8 +28,6 @@ from qutebrowser.utils.misc import read_file config = None state = None -colordict = {} -fontdict = {} # Special value for an unset fallback, so None can be passed as fallback. _UNSET = object() @@ -42,119 +40,10 @@ def init(confdir): confdir: The directory where the configs are stored in. """ - global config, state, colordict, fontdict + global config, state logging.debug("Config init, confdir {}".format(confdir)) config = Config(confdir, 'qutebrowser.conf', read_file('qutebrowser.conf')) state = Config(confdir, 'state', always_save=True) - try: - colordict = ColorDict(config['colors']) - except KeyError: - colordict = ColorDict() - fontdict = FontDict(config['fonts']) - - -def get_stylesheet(template): - """Format a stylesheet based on a template. - - Args: - template: The stylesheet template as string. - - Return: - The formatted template as string. - - """ - return template.strip().format(color=colordict, font=fontdict) - - -class ColorDict(dict): - - """A dict aimed at Qt stylesheet colors.""" - - # FIXME we should validate colors in __setitem__ based on: - # http://qt-project.org/doc/qt-4.8/stylesheet-reference.html#brush - # http://www.w3.org/TR/CSS21/syndata.html#color-units - - def __getitem__(self, key): - """Override dict __getitem__. - - Args: - key: The key to get from the dict. - - Return: - If a value wasn't found, return an empty string. - (Color not defined, so no output in the stylesheet) - - If the key has a .fg. element in it, return color: X;. - If the key has a .bg. element in it, return background-color: X;. - - In all other cases, return the plain value. - - """ - try: - val = super().__getitem__(key) - except KeyError: - return '' - if 'fg' in key.split('.'): - return 'color: {};'.format(val) - elif 'bg' in key.split('.'): - return 'background-color: {};'.format(val) - else: - return val - - def getraw(self, key): - """Get a value without the transformations done in __getitem__. - - Args: - key: The key to get from the dict. - - Return: - A value, or None if the value wasn't found. - - """ - try: - return super().__getitem__(key) - except KeyError: - return None - - -class FontDict(dict): - - """A dict aimed at Qt stylesheet fonts.""" - - def __getitem__(self, key): - """Override dict __getitem__. - - Args: - key: The key to get from the dict. - - Return: - If a value wasn't found, return an empty string. - (Color not defined, so no output in the stylesheet) - - In all other cases, return font: . - - """ - try: - val = super().__getitem__(key) - except KeyError: - return '' - else: - return 'font: {};'.format(val) - - def getraw(self, key): - """Get a value without the transformations done in __getitem__. - - Args: - key: The key to get from the dict. - - Return: - A value, or None if the value wasn't found. - - """ - try: - return super().__getitem__(key) - except KeyError: - return None class Config(ConfigParser): diff --git a/qutebrowser/config/style.py b/qutebrowser/config/style.py new file mode 100644 index 000000000..119cbddbe --- /dev/null +++ b/qutebrowser/config/style.py @@ -0,0 +1,136 @@ +# 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 . + +"""Utilities related to the look&feel of qutebrowser.""" + +import qutebrowser.config.config as config + +colordict = {} +fontdict = {} + +def init(): + """Initialize the global objects based on the config.""" + global colordict, fontdict + try: + colordict = ColorDict(config.config['colors']) + except KeyError: + colordict = ColorDict() + fontdict = FontDict(config.config['fonts']) + + +def get_stylesheet(template): + """Format a stylesheet based on a template. + + Args: + template: The stylesheet template as string. + + Return: + The formatted template as string. + + """ + return template.strip().format(color=colordict, font=fontdict) + + +class ColorDict(dict): + + """A dict aimed at Qt stylesheet colors.""" + + # FIXME we should validate colors in __setitem__ based on: + # http://qt-project.org/doc/qt-4.8/stylesheet-reference.html#brush + # http://www.w3.org/TR/CSS21/syndata.html#color-units + + def __getitem__(self, key): + """Override dict __getitem__. + + Args: + key: The key to get from the dict. + + Return: + If a value wasn't found, return an empty string. + (Color not defined, so no output in the stylesheet) + + If the key has a .fg. element in it, return color: X;. + If the key has a .bg. element in it, return background-color: X;. + + In all other cases, return the plain value. + + """ + try: + val = super().__getitem__(key) + except KeyError: + return '' + if 'fg' in key.split('.'): + return 'color: {};'.format(val) + elif 'bg' in key.split('.'): + return 'background-color: {};'.format(val) + else: + return val + + def getraw(self, key): + """Get a value without the transformations done in __getitem__. + + Args: + key: The key to get from the dict. + + Return: + A value, or None if the value wasn't found. + + """ + try: + return super().__getitem__(key) + except KeyError: + return None + + +class FontDict(dict): + + """A dict aimed at Qt stylesheet fonts.""" + + def __getitem__(self, key): + """Override dict __getitem__. + + Args: + key: The key to get from the dict. + + Return: + If a value wasn't found, return an empty string. + (Color not defined, so no output in the stylesheet) + + In all other cases, return font: . + + """ + try: + val = super().__getitem__(key) + except KeyError: + return '' + else: + return 'font: {};'.format(val) + + def getraw(self, key): + """Get a value without the transformations done in __getitem__. + + Args: + key: The key to get from the dict. + + Return: + A value, or None if the value wasn't found. + + """ + try: + return super().__getitem__(key) + except KeyError: + return None diff --git a/qutebrowser/widgets/completion.py b/qutebrowser/widgets/completion.py index d9f97592b..dd4961715 100644 --- a/qutebrowser/widgets/completion.py +++ b/qutebrowser/widgets/completion.py @@ -32,6 +32,7 @@ from PyQt5.QtGui import (QIcon, QPalette, QTextDocument, QTextOption, QTextCursor) import qutebrowser.config.config as config +from qutebrowser.config.style import get_stylesheet from qutebrowser.models.completionfilter import CompletionFilterModel from qutebrowser.models.commandcompletion import CommandCompletionModel @@ -114,7 +115,7 @@ class CompletionView(QTreeView): self.setmodel('command') self._delegate = _CompletionItemDelegate(self) self.setItemDelegate(self._delegate) - self.setStyleSheet(config.get_stylesheet(self._STYLESHEET)) + self.setStyleSheet(get_stylesheet(self._STYLESHEET)) self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Minimum) self.setHeaderHidden(True) self.setIndentation(0) @@ -401,7 +402,7 @@ class _CompletionItemDelegate(QStyledItemDelegate): self._doc.setHtml('{}'.format(html.escape(self._opt.text))) self._doc.setDefaultFont(self._opt.font) self._doc.setDefaultTextOption(text_option) - self._doc.setDefaultStyleSheet(config.get_stylesheet(""" + self._doc.setDefaultStyleSheet(get_stylesheet(""" .highlight {{ {color[completion.match.fg]} }} diff --git a/qutebrowser/widgets/statusbar.py b/qutebrowser/widgets/statusbar.py index 65b54d130..12ee66a49 100644 --- a/qutebrowser/widgets/statusbar.py +++ b/qutebrowser/widgets/statusbar.py @@ -26,6 +26,7 @@ from PyQt5.QtWidgets import (QWidget, QLineEdit, QProgressBar, QLabel, from PyQt5.QtGui import QPainter, QKeySequence, QValidator import qutebrowser.config.config as config +from qutebrowser.config.style import get_stylesheet import qutebrowser.commands.keys as keys from qutebrowser.utils.url import urlstring from qutebrowser.utils.usertypes import NeighborList @@ -79,7 +80,7 @@ class StatusBar(QWidget): super().__init__(parent) self.setObjectName(self.__class__.__name__) self.setAttribute(Qt.WA_StyledBackground) - self.setStyleSheet(config.get_stylesheet(self._STYLESHEET)) + self.setStyleSheet(get_stylesheet(self._STYLESHEET)) self.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Fixed) @@ -133,7 +134,7 @@ class StatusBar(QWidget): """ self._error = val - self.setStyleSheet(config.get_stylesheet(self._STYLESHEET)) + self.setStyleSheet(get_stylesheet(self._STYLESHEET)) def _show_cmd_widget(self): """Show command widget instead of temporary text.""" @@ -453,7 +454,7 @@ class _Progress(QProgressBar): def __init__(self, parent): super().__init__(parent) - self.setStyleSheet(config.get_stylesheet(self._STYLESHEET)) + self.setStyleSheet(get_stylesheet(self._STYLESHEET)) self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Ignored) self.setTextVisible(False) self.hide() @@ -665,7 +666,7 @@ class _Url(TextBase): """ super().__init__(bar, elidemode) self.setObjectName(self.__class__.__name__) - self.setStyleSheet(config.get_stylesheet(self._STYLESHEET)) + self.setStyleSheet(get_stylesheet(self._STYLESHEET)) self._urltype = None self._old_urltype = None self._old_url = None @@ -680,7 +681,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(config.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 2e4b0b40e..d3cde6838 100644 --- a/qutebrowser/widgets/tabbar.py +++ b/qutebrowser/widgets/tabbar.py @@ -21,6 +21,7 @@ from PyQt5.QtCore import Qt from PyQt5.QtWidgets import QTabWidget, QTabBar, QSizePolicy import qutebrowser.config.config as config +from qutebrowser.config.style import get_stylesheet from qutebrowser.utils.style import Style @@ -68,7 +69,7 @@ class TabWidget(QTabWidget): super().__init__(parent) self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) self.setStyle(Style(self.style())) - self.setStyleSheet(config.get_stylesheet(self._STYLESHEET)) + self.setStyleSheet(get_stylesheet(self._STYLESHEET)) self.setDocumentMode(True) self.setElideMode(Qt.ElideRight) self._init_config()