Merge remote-tracking branch 'origin/pr/4185'

This commit is contained in:
Florian Bruhin 2018-09-06 16:15:16 +02:00
commit 108cc65bc6
8 changed files with 126 additions and 21 deletions

View File

@ -34,6 +34,7 @@ from qutebrowser.keyinput import keyutils
val = None
instance = None
key_instance = None
cache = None
# Keeping track of all change filters to validate them later.
change_filters = []

View File

@ -0,0 +1,50 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2018 Jay Kamat <jaygkamat@gmail.com>
#
# 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/>.
"""Implementation of a basic config cache."""
from qutebrowser.config import config
class ConfigCache:
"""A 'high-performance' cache for the config system.
Useful for areas which call out to the config system very frequently, DO
NOT modify the value returned, DO NOT require per-url settings, do not
change frequently, and do not require partially 'expanded' config paths.
If any of these requirements are broken, you will get incorrect or slow
behavior.
"""
def __init__(self) -> None:
self._cache = {}
config.instance.changed.connect(self._on_config_changed)
def _on_config_changed(self, attr: str) -> None:
if attr in self._cache:
self._cache[attr] = config.instance.get(attr)
def __getitem__(self, attr: str):
if attr not in self._cache:
assert not config.instance.get_opt(attr).supports_pattern
self._cache[attr] = config.instance.get(attr)
return self._cache[attr]

View File

@ -28,6 +28,7 @@ from qutebrowser.config import (config, configdata, configfiles, configtypes,
configexc, configcommands)
from qutebrowser.utils import (objreg, usertypes, log, standarddir, message,
qtutils)
from qutebrowser.config import configcache
from qutebrowser.misc import msgbox, objects
@ -44,6 +45,7 @@ def early_init(args):
config.instance = config.Config(yaml_config=yaml_config)
config.val = config.ConfigContainer(config.instance)
config.key_instance = config.KeyConfig(config.instance)
config.cache = configcache.ConfigCache()
yaml_config.setParent(config.instance)
for cf in config.change_filters:

View File

@ -719,9 +719,9 @@ class TabbedBrowser(QWidget):
except TabDeletedError:
# We can get signals for tabs we already deleted...
return
start = config.val.colors.tabs.indicator.start
stop = config.val.colors.tabs.indicator.stop
system = config.val.colors.tabs.indicator.system
start = config.cache['colors.tabs.indicator.start']
stop = config.cache['colors.tabs.indicator.stop']
system = config.cache['colors.tabs.indicator.system']
color = utils.interpolate_color(start, stop, perc, system)
self.widget.set_tab_indicator_color(idx, color)
self.widget.update_tab_title(idx)

View File

@ -139,9 +139,9 @@ class TabWidget(QTabWidget):
"""
tab = self.widget(idx)
if tab.data.pinned:
fmt = config.val.tabs.title.format_pinned
fmt = config.cache['tabs.title.format_pinned']
else:
fmt = config.val.tabs.title.format
fmt = config.cache['tabs.title.format']
if (field is not None and
(fmt is None or ('{' + field + '}') not in fmt)):
@ -604,7 +604,7 @@ class TabBar(QTabBar):
minimum_size = self.minimumTabSizeHint(index)
height = minimum_size.height()
if self.vertical:
confwidth = str(config.val.tabs.width)
confwidth = str(config.cache['tabs.width'])
if confwidth.endswith('%'):
main_window = objreg.get('main-window', scope='window',
window=self._win_id)
@ -614,7 +614,7 @@ class TabBar(QTabBar):
width = int(confwidth)
size = QSize(max(minimum_size.width(), width), height)
else:
if config.val.tabs.pinned.shrink:
if config.cache['tabs.pinned.shrink']:
pinned = self._tab_pinned(index)
pinned_count, pinned_width = self._pinned_statistics()
else:
@ -652,15 +652,15 @@ class TabBar(QTabBar):
tab = QStyleOptionTab()
self.initStyleOption(tab, idx)
# pylint: disable=bad-config-option
setting = config.val.colors.tabs
# pylint: enable=bad-config-option
setting = 'colors.tabs'
if idx == selected:
setting = setting.selected
setting = setting.odd if (idx + 1) % 2 else setting.even
setting += '.selected'
setting += '.odd' if (idx + 1) % 2 else '.even'
tab.palette.setColor(QPalette.Window, setting.bg)
tab.palette.setColor(QPalette.WindowText, setting.fg)
tab.palette.setColor(QPalette.Window,
config.cache[setting + '.bg'])
tab.palette.setColor(QPalette.WindowText,
config.cache[setting + '.fg'])
indicator_color = self.tab_indicator_color(idx)
tab.palette.setColor(QPalette.Base, indicator_color)
@ -805,7 +805,7 @@ class TabBarStyle(QCommonStyle):
elif element == QStyle.CE_TabBarTabLabel:
if not opt.icon.isNull() and layouts.icon.isValid():
self._draw_icon(layouts, opt, p)
alignment = (config.val.tabs.title.alignment |
alignment = (config.cache['tabs.title.alignment'] |
Qt.AlignVCenter | Qt.TextHideMnemonic)
self._style.drawItemText(p, layouts.text, alignment, opt.palette,
opt.state & QStyle.State_Enabled,
@ -878,8 +878,8 @@ class TabBarStyle(QCommonStyle):
Return:
A Layout object with two QRects.
"""
padding = config.val.tabs.padding
indicator_padding = config.val.tabs.indicator.padding
padding = config.cache['tabs.padding']
indicator_padding = config.cache['tabs.indicator.padding']
text_rect = QRect(opt.rect)
if not text_rect.isValid():
@ -890,7 +890,7 @@ class TabBarStyle(QCommonStyle):
text_rect.adjust(padding.left, padding.top, -padding.right,
-padding.bottom)
indicator_width = config.val.tabs.indicator.width
indicator_width = config.cache['tabs.indicator.width']
if indicator_width == 0:
indicator_rect = QRect()
else:
@ -933,9 +933,9 @@ class TabBarStyle(QCommonStyle):
icon_state = (QIcon.On if opt.state & QStyle.State_Selected
else QIcon.Off)
# reserve space for favicon when tab bar is vertical (issue #1968)
position = config.val.tabs.position
position = config.cache['tabs.position']
if (position in [QTabWidget.East, QTabWidget.West] and
config.val.tabs.favicons.show != 'never'):
config.cache['tabs.favicons.show'] != 'never'):
tab_icon_size = icon_size
else:
actual_size = opt.icon.actualSize(icon_size, icon_mode, icon_state)

View File

@ -147,6 +147,8 @@ PERFECT_FILES = [
'config/configcommands.py'),
('tests/unit/config/test_configutils.py',
'config/configutils.py'),
('tests/unit/config/test_configcache.py',
'config/configcache.py'),
('tests/unit/utils/test_qtutils.py',
'utils/qtutils.py'),

View File

@ -42,7 +42,7 @@ from PyQt5.QtNetwork import QNetworkCookieJar
import helpers.stubs as stubsmod
import helpers.utils
from qutebrowser.config import (config, configdata, configtypes, configexc,
configfiles)
configfiles, configcache)
from qutebrowser.utils import objreg, standarddir, utils, usertypes
from qutebrowser.browser import greasemonkey
from qutebrowser.browser.webkit import cookies
@ -253,6 +253,9 @@ def config_stub(stubs, monkeypatch, configdata_init, yaml_config_stub):
container = config.ConfigContainer(conf)
monkeypatch.setattr(config, 'val', container)
cache = configcache.ConfigCache()
monkeypatch.setattr(config, 'cache', cache)
try:
configtypes.Font.monospace_fonts = container.fonts.monospace
except configexc.NoOptionError:

View File

@ -0,0 +1,47 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2018 Jay Kamat <jaygkamat@gmail.com>:
#
# 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.configcache."""
import pytest
from qutebrowser.config import config
def test_configcache_except_pattern(config_stub):
with pytest.raises(AssertionError):
assert config.cache['content.javascript.enabled']
def test_configcache_error_set(config_stub):
with pytest.raises(TypeError):
config.cache['content.javascript.enabled'] = True
def test_configcache_get(config_stub):
assert len(config.cache._cache) == 0
assert not config.cache['auto_save.session']
assert len(config.cache._cache) == 1
assert not config.cache['auto_save.session']
def test_configcache_get_after_set(config_stub):
assert not config.cache['auto_save.session']
config_stub.val.auto_save.session = True
assert config.cache['auto_save.session']