summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Bruhin <git@the-compiler.org>2015-03-13 07:58:04 +0100
committerFlorian Bruhin <git@the-compiler.org>2015-03-19 06:21:08 +0100
commit71dbdb37a26124f0e92c146efb8807c15932cfda (patch)
treecaad85a0d64b99761a8815a508b993c9a25e8243
parent6c0e470b6020205cd1976ed1106308283a240947 (diff)
downloadqutebrowser-71dbdb37a26124f0e92c146efb8807c15932cfda.tar.gz
qutebrowser-71dbdb37a26124f0e92c146efb8807c15932cfda.zip
Refactor websettings and save/restore defaults.
This makes qutebrowser.config.websettings much easier to understand, and saves all defaults so it can restore them properly when a setting is set to an empty string. Before, when we set the fonts to empty strings instead of the true default, in some cases anti-aliasing was broken. Fixes #549.
-rw-r--r--qutebrowser/config/websettings.py381
1 files changed, 276 insertions, 105 deletions
diff --git a/qutebrowser/config/websettings.py b/qutebrowser/config/websettings.py
index 131025bea..63bb848b1 100644
--- a/qutebrowser/config/websettings.py
+++ b/qutebrowser/config/websettings.py
@@ -22,176 +22,346 @@
Module attributes:
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.
"""
import os.path
from PyQt5.QtWebKit import QWebSettings
-from PyQt5.QtCore import QStandardPaths, QUrl
+from PyQt5.QtCore import QStandardPaths
from qutebrowser.config import config
-from qutebrowser.utils import usertypes, standarddir, objreg
+from qutebrowser.utils import standarddir, objreg, log, utils, debug
+
+UNSET = object()
+
+
+class Base:
+
+ """Base class for QWebSetting wrappers.
+
+ Attributes:
+ _default: The default value of this setting.
+ """
+
+ def __init__(self):
+ self._default = UNSET
+
+ def _get_qws(self, qws):
+ """Get the QWebSettings object to use.
+
+ Args:
+ qws: The QWebSettings instance to use, or None to use the global
+ instance.
+ """
+ if qws is None:
+ return QWebSettings.globalSettings()
+ else:
+ return qws
+
+ def save_default(self, qws=None):
+ """Save the default value based on the currently set one.
+
+ This does nothing if no getter is configured for this setting.
+
+ Args:
+ qws: The QWebSettings instance to use, or None to use the global
+ instance.
+ """
+ try:
+ self._default = self.get(qws)
+ except AttributeError:
+ pass
+
+ def restore_default(self, qws=None):
+ """Restore the default value from the saved one.
+
+ This does nothing if the default has never been set.
+
+ Args:
+ qws: The QWebSettings instance to use, or None to use the global
+ instance.
+ """
+ if self._default is not UNSET:
+ self._set(self._default, qws=qws)
+
+ def get(self, qws=None):
+ """Get the value of this setting.
+
+ Must be overridden by subclasses.
+
+ Args:
+ qws: The QWebSettings instance to use, or None to use the global
+ instance.
+ """
+ raise NotImplementedError
+
+ def set(self, value, qws=None):
+ """Set the value of this setting.
+
+ Args:
+ value: The value to set.
+ qws: The QWebSettings instance to use, or None to use the global
+ instance.
+ """
+ if value is None:
+ self.restore_default(qws)
+ else:
+ self._set(value, qws=qws)
+
+ def _set(self, value, qws):
+ """Inner function to set the value of this setting.
+
+ Must be overridden by subclasses.
+
+ Args:
+ value: The value to set.
+ qws: The QWebSettings instance to use, or None to use the global
+ instance.
+ """
+ raise NotImplementedError
+
+
+class Attribute(Base):
+
+ """A setting set via QWebSettings::setAttribute.
+
+ Attributes:
+ self._attribute: A QWebSettings::WebAttribute instance.
+ """
+
+ def __init__(self, attribute):
+ super().__init__()
+ self._attribute = attribute
+
+ def __repr__(self):
+ return utils.get_repr(
+ self, attribute=debug.qenum_key(QWebSettings, self._attribute),
+ constructor=True)
+
+ def get(self, qws=None):
+ return self._get_qws(qws).attribute(self._attribute)
+
+ def _set(self, value, qws=None):
+ self._get_qws(qws).setAttribute(self._attribute, value)
-MapType = usertypes.enum('MapType', ['attribute', 'setter', 'static_setter'])
+
+class Setter(Base):
+
+ """A setting set via QWebSettings getter/setter methods.
+
+ This will pass the QWebSettings instance ("self") as first argument to the
+ methods, so self._getter/self._setter are the *unbound* methods.
+
+ Attributes:
+ _getter: The unbound QWebSettings method to get this value, or None.
+ _setter: The unbound QWebSettings method to set this value.
+ _args: An iterable of the arguments to pass to the setter/getter
+ (before the value, for the setter).
+ _unpack: Whether to unpack args (True) or pass them directly (False).
+ """
+
+ def __init__(self, getter, setter, args=(), unpack=False):
+ super().__init__()
+ self._getter = getter
+ self._setter = setter
+ self._args = args
+ self._unpack = unpack
+
+ def __repr__(self):
+ return utils.get_repr(self, getter=self._getter, setter=self._setter,
+ args=self._args, unpack=self._unpack,
+ constructor=True)
+
+ def get(self, qws=None):
+ if self._getter is None:
+ raise AttributeError("No getter set!")
+ return self._getter(self._get_qws(qws), *self._args)
+
+ def _set(self, value, qws=None):
+ args = [self._get_qws(qws)]
+ args.extend(self._args)
+ if self._unpack:
+ args.extend(value)
+ else:
+ args.append(value)
+ self._setter(*args)
+
+
+class NullStringSetter(Setter):
+
+ """A setter for settings requiring a null QString as default.
+
+ This overrides save_default so None is saved for an empty string. This is
+ needed for the CSS media type, because it returns an empty Python string
+ when getting the value, but setting it to the default requires passing None
+ (a null QString) instead of an empty string.
+ """
+
+ def save_default(self, qws=None):
+ try:
+ val = self.get(qws)
+ except AttributeError:
+ pass
+ if val == '':
+ self._set(None, qws=qws)
+ else:
+ self._set(val, qws=qws)
+
+
+class GlobalSetter(Setter):
+
+ """A setting set via static QWebSettings getter/setter methods.
+
+ self._getter/self._setter are the *bound* methods.
+ """
+
+ def get(self, qws=None):
+ if qws is not None:
+ raise ValueError("qws may not be set with GlobalSetters!")
+ if self._getter is None:
+ raise AttributeError("No getter set!")
+ return self._getter(*self._args)
+
+ def _set(self, value, qws=None):
+ if qws is not None:
+ raise ValueError("qws may not be set with GlobalSetters!")
+ args = list(self._args)
+ if self._unpack:
+ args.extend(value)
+ else:
+ args.append(value)
+ self._setter(*args)
MAPPINGS = {
'content': {
'allow-images':
- (MapType.attribute, QWebSettings.AutoLoadImages),
+ Attribute(QWebSettings.AutoLoadImages),
'allow-javascript':
- (MapType.attribute, QWebSettings.JavascriptEnabled),
+ Attribute(QWebSettings.JavascriptEnabled),
'javascript-can-open-windows':
- (MapType.attribute, QWebSettings.JavascriptCanOpenWindows),
+ Attribute(QWebSettings.JavascriptCanOpenWindows),
'javascript-can-close-windows':
- (MapType.attribute, QWebSettings.JavascriptCanCloseWindows),
+ Attribute(QWebSettings.JavascriptCanCloseWindows),
'javascript-can-access-clipboard':
- (MapType.attribute, QWebSettings.JavascriptCanAccessClipboard),
+ Attribute(QWebSettings.JavascriptCanAccessClipboard),
#'allow-java':
- # (MapType.attribute, QWebSettings.JavaEnabled),
+ # Attribute(QWebSettings.JavaEnabled),
'allow-plugins':
- (MapType.attribute, QWebSettings.PluginsEnabled),
+ Attribute(QWebSettings.PluginsEnabled),
'local-content-can-access-remote-urls':
- (MapType.attribute, QWebSettings.LocalContentCanAccessRemoteUrls),
+ Attribute(QWebSettings.LocalContentCanAccessRemoteUrls),
'local-content-can-access-file-urls':
- (MapType.attribute, QWebSettings.LocalContentCanAccessFileUrls),
+ Attribute(QWebSettings.LocalContentCanAccessFileUrls),
},
'network': {
'dns-prefetch':
- (MapType.attribute, QWebSettings.DnsPrefetchEnabled),
+ Attribute(QWebSettings.DnsPrefetchEnabled),
},
'input': {
'spatial-navigation':
- (MapType.attribute, QWebSettings.SpatialNavigationEnabled),
+ Attribute(QWebSettings.SpatialNavigationEnabled),
'links-included-in-focus-chain':
- (MapType.attribute, QWebSettings.LinksIncludedInFocusChain),
+ Attribute(QWebSettings.LinksIncludedInFocusChain),
},
'fonts': {
'web-family-standard':
- (MapType.setter, lambda qws, v:
- qws.setFontFamily(QWebSettings.StandardFont, v),
- ""),
+ Setter(getter=QWebSettings.fontFamily,
+ setter=QWebSettings.setFontFamily,
+ args=[QWebSettings.StandardFont]),
'web-family-fixed':
- (MapType.setter, lambda qws, v:
- qws.setFontFamily(QWebSettings.FixedFont, v),
- ""),
+ Setter(getter=QWebSettings.fontFamily,
+ setter=QWebSettings.setFontFamily,
+ args=[QWebSettings.FixedFont]),
'web-family-serif':
- (MapType.setter, lambda qws, v:
- qws.setFontFamily(QWebSettings.SerifFont, v),
- ""),
+ Setter(getter=QWebSettings.fontFamily,
+ setter=QWebSettings.setFontFamily,
+ args=[QWebSettings.SerifFont]),
'web-family-sans-serif':
- (MapType.setter, lambda qws, v:
- qws.setFontFamily(QWebSettings.SansSerifFont, v),
- ""),
+ Setter(getter=QWebSettings.fontFamily,
+ setter=QWebSettings.setFontFamily,
+ args=[QWebSettings.SansSerifFont]),
'web-family-cursive':
- (MapType.setter, lambda qws, v:
- qws.setFontFamily(QWebSettings.CursiveFont, v),
- ""),
+ Setter(getter=QWebSettings.fontFamily,
+ setter=QWebSettings.setFontFamily,
+ args=[QWebSettings.CursiveFont]),
'web-family-fantasy':
- (MapType.setter, lambda qws, v:
- qws.setFontFamily(QWebSettings.FantasyFont, v),
- ""),
+ Setter(getter=QWebSettings.fontFamily,
+ setter=QWebSettings.setFontFamily,
+ args=[QWebSettings.FantasyFont]),
'web-size-minimum':
- (MapType.setter, lambda qws, v:
- qws.setFontSize(QWebSettings.MinimumFontSize, v)),
+ Setter(getter=QWebSettings.fontSize,
+ setter=QWebSettings.setFontSize,
+ args=[QWebSettings.MinimumFontSize]),
'web-size-minimum-logical':
- (MapType.setter, lambda qws, v:
- qws.setFontSize(QWebSettings.MinimumLogicalFontSize, v)),
+ Setter(getter=QWebSettings.fontSize,
+ setter=QWebSettings.setFontSize,
+ args=[QWebSettings.MinimumLogicalFontSize]),
'web-size-default':
- (MapType.setter, lambda qws, v:
- qws.setFontSize(QWebSettings.DefaultFontSize, v)),
+ Setter(getter=QWebSettings.fontSize,
+ setter=QWebSettings.setFontSize,
+ args=[QWebSettings.DefaultFontSize]),
'web-size-default-fixed':
- (MapType.setter, lambda qws, v:
- qws.setFontSize(QWebSettings.DefaultFixedFontSize, v)),
+ Setter(getter=QWebSettings.fontSize,
+ setter=QWebSettings.setFontSize,
+ args=[QWebSettings.DefaultFixedFontSize]),
},
'ui': {
'zoom-text-only':
- (MapType.attribute, QWebSettings.ZoomTextOnly),
+ Attribute(QWebSettings.ZoomTextOnly),
'frame-flattening':
- (MapType.attribute, QWebSettings.FrameFlatteningEnabled),
+ Attribute(QWebSettings.FrameFlatteningEnabled),
'user-stylesheet':
- (MapType.setter, lambda qws, v:
- qws.setUserStyleSheetUrl(v),
- QUrl()),
+ Setter(getter=QWebSettings.userStyleSheetUrl,
+ setter=QWebSettings.setUserStyleSheetUrl),
'css-media-type':
- (MapType.setter, lambda qws, v:
- qws.setCSSMediaType(v)),
+ NullStringSetter(getter=QWebSettings.cssMediaType,
+ setter=QWebSettings.setCSSMediaType),
#'accelerated-compositing':
- # (MapType.attribute, QWebSettings.AcceleratedCompositingEnabled),
+ # Attribute(QWebSettings.AcceleratedCompositingEnabled),
#'tiled-backing-store':
- # (MapType.attribute, QWebSettings.TiledBackingStoreEnabled),
+ # Attribute(QWebSettings.TiledBackingStoreEnabled),
},
'storage': {
'offline-storage-database':
- (MapType.attribute, QWebSettings.OfflineStorageDatabaseEnabled),
+ Attribute(QWebSettings.OfflineStorageDatabaseEnabled),
'offline-web-application-storage':
- (MapType.attribute,
- QWebSettings.OfflineWebApplicationCacheEnabled),
+ Attribute(QWebSettings.OfflineWebApplicationCacheEnabled),
'local-storage':
- (MapType.attribute, QWebSettings.LocalStorageEnabled),
+ Attribute(QWebSettings.LocalStorageEnabled),
'maximum-pages-in-cache':
- (MapType.static_setter, lambda v:
- QWebSettings.setMaximumPagesInCache(v)),
+ GlobalSetter(getter=QWebSettings.maximumPagesInCache,
+ setter=QWebSettings.setMaximumPagesInCache),
'object-cache-capacities':
- (MapType.static_setter, lambda v:
- QWebSettings.setObjectCacheCapacities(*v)),
+ GlobalSetter(getter=None,
+ setter=QWebSettings.setObjectCacheCapacities,
+ unpack=True),
'offline-storage-default-quota':
- (MapType.static_setter, lambda v:
- QWebSettings.setOfflineStorageDefaultQuota(v)),
+ GlobalSetter(getter=QWebSettings.offlineStorageDefaultQuota,
+ setter=QWebSettings.setOfflineStorageDefaultQuota),
'offline-web-application-cache-quota':
- (MapType.static_setter, lambda v:
- QWebSettings.setOfflineWebApplicationCacheQuota(v)),
+ GlobalSetter(
+ getter=QWebSettings.offlineWebApplicationCacheQuota,
+ setter=QWebSettings.setOfflineWebApplicationCacheQuota),
},
'general': {
'private-browsing':
- (MapType.attribute, QWebSettings.PrivateBrowsingEnabled),
+ Attribute(QWebSettings.PrivateBrowsingEnabled),
'developer-extras':
- (MapType.attribute, QWebSettings.DeveloperExtrasEnabled),
+ Attribute(QWebSettings.DeveloperExtrasEnabled),
'print-element-backgrounds':
- (MapType.attribute, QWebSettings.PrintElementBackgrounds),
+ Attribute(QWebSettings.PrintElementBackgrounds),
'xss-auditing':
- (MapType.attribute, QWebSettings.XSSAuditingEnabled),
+ Attribute(QWebSettings.XSSAuditingEnabled),
'site-specific-quirks':
- (MapType.attribute, QWebSettings.SiteSpecificQuirksEnabled),
+ Attribute(QWebSettings.SiteSpecificQuirksEnabled),
'default-encoding':
- (MapType.setter, lambda qws, v: qws.setDefaultTextEncoding(v), ""),
+ Setter(getter=QWebSettings.defaultTextEncoding,
+ setter=QWebSettings.setDefaultTextEncoding),
}
}
-settings = None
-UNSET = object()
-
-
-def _set_setting(typ, arg, default=UNSET, value=UNSET):
- """Set a QWebSettings setting.
-
- Args:
- typ: The type of the item.
- arg: The argument (attribute/handler)
- default: The value to use if the user set an empty string.
- value: The value to set.
- """
- if not isinstance(typ, MapType):
- raise TypeError("Type {} is no MapType member!".format(typ))
- if value is UNSET:
- raise TypeError("No value given!")
- if value is None:
- if default is UNSET:
- return
- else:
- value = default
-
- if typ == MapType.attribute:
- settings.setAttribute(arg, value)
- elif typ == MapType.setter:
- arg(settings, value)
- elif typ == MapType.static_setter:
- arg(value)
-
-
def init():
"""Initialize the global QWebSettings."""
cachedir = standarddir.get(QStandardPaths.CacheLocation)
@@ -204,12 +374,13 @@ def init():
QWebSettings.setOfflineStoragePath(
os.path.join(datadir, 'offline-storage'))
- global settings
- settings = QWebSettings.globalSettings()
for sectname, section in MAPPINGS.items():
for optname, mapping in section.items():
+ mapping.save_default()
value = config.get(sectname, optname)
- _set_setting(*mapping, value=value)
+ log.misc.debug("Setting {} -> {} to {!r}".format(sectname, optname,
+ value))
+ mapping.set(value)
objreg.get('config').changed.connect(update_settings)
@@ -220,4 +391,4 @@ def update_settings(section, option):
except KeyError:
return
value = config.get(section, option)
- _set_setting(*mapping, value=value)
+ mapping.set(value)