diff --git a/TODO b/TODO index f37da377e..f4a54ac4d 100644 --- a/TODO +++ b/TODO @@ -46,7 +46,6 @@ catch import errors for PyQt and QtWebKit elem = frame.findFirstElement('*:focus') somehow unfocus elements (hide blinking cursor) when insert mode is left? tabs: some more padding? -custom stylesheet Really fix URL detection properly hints diff --git a/qutebrowser/config/_conftypes.py b/qutebrowser/config/_conftypes.py index 51f9e22c3..afd9f91b8 100644 --- a/qutebrowser/config/_conftypes.py +++ b/qutebrowser/config/_conftypes.py @@ -19,8 +19,10 @@ import re import shlex +import os.path from sre_constants import error as RegexError +from PyQt5.QtCore import QUrl from PyQt5.QtGui import QColor import qutebrowser.commands.utils as cmdutils @@ -566,6 +568,32 @@ class RegexList(List): str(e)) +class File(BaseType): + + """A file on the local filesystem.""" + + def validate(self, value): + if not os.path.isfile(value): + raise ValidationError(value, "must be a valid file!") + + +class WebSettingsFile(File): + + """QWebSettings file which also can be none.""" + + def validate(self, value): + if not value: + # empty values are okay + return + super().validate(value) + + def transform(self, value): + if value is None: + return value + else: + return QUrl.fromLocalFile(value) + + class AutoSearch(BaseType): """Whether to start a search when something else than an URL is entered.""" diff --git a/qutebrowser/config/configdata.py b/qutebrowser/config/configdata.py index 50a615761..73d9bf05f 100644 --- a/qutebrowser/config/configdata.py +++ b/qutebrowser/config/configdata.py @@ -399,6 +399,10 @@ DATA = OrderedDict([ ('site-specific-quirks-enabled', SettingValue(types.Bool(), 'true'), "This setting enables WebKit's workaround for broken sites."), + + ('user-stylesheet', + SettingValue(types.WebSettingsFile(), ''), + "User stylesheet to set."), )), ('hints', sect.KeyValue( diff --git a/qutebrowser/config/websettings.py b/qutebrowser/config/websettings.py index fb141bf54..1eb2fb043 100644 --- a/qutebrowser/config/websettings.py +++ b/qutebrowser/config/websettings.py @@ -18,8 +18,9 @@ """Bridge from QWebSettings to our own settings. Module attributes: - MAPPING: A mapping from internal setting names to QWebSetting enum - constants. + ATTRIBUTES: A mapping from internal setting names to QWebSetting enum + constants. + SETTERS: A mapping from setting names to QWebSetting setter method names. settings: The global QWebSettings singleton instance. """ @@ -29,7 +30,7 @@ from PyQt5.QtWebKit import QWebSettings import qutebrowser.config.config as config -MAPPING = { +ATTRIBUTES = { # noqa 'auto-load-images': QWebSettings.AutoLoadImages, 'dns-prefetch-enabled': QWebSettings.DnsPrefetchEnabled, @@ -63,6 +64,12 @@ MAPPING = { 'site-specific-quirks-enabled': QWebSettings.SiteSpecificQuirksEnabled, } + +SETTERS = { + 'user-stylesheet': 'setUserStyleSheetUrl' +} + + settings = None @@ -70,8 +77,13 @@ def init(): """Initialize the global QWebSettings.""" global settings settings = QWebSettings.globalSettings() - for name, item in MAPPING.items(): + for name, item in ATTRIBUTES.items(): settings.setAttribute(item, config.get('webkit', name)) + for name, method in SETTERS.items(): + value = config.get('webkit', name) + if value is not None: + setter = getattr(settings, method) + setter(value) @pyqtSlot(str, str) @@ -79,4 +91,8 @@ def on_config_changed(section, option): """Update global settings when qwebsettings changed.""" if section == 'webkit': value = config.get(section, option) - settings.setAttribute(MAPPING[option], value) + if option in ATTRIBUTES: + settings.setAttribute(ATTRIBUTES[option], value) + elif option in SETTERS and value is not None: + setter = getattr(settings, SETTERS[option]) + setter(value)