Merge remote-tracking branch 'origin/pr/4185'
This commit is contained in:
commit
108cc65bc6
@ -34,6 +34,7 @@ from qutebrowser.keyinput import keyutils
|
|||||||
val = None
|
val = None
|
||||||
instance = None
|
instance = None
|
||||||
key_instance = None
|
key_instance = None
|
||||||
|
cache = None
|
||||||
|
|
||||||
# Keeping track of all change filters to validate them later.
|
# Keeping track of all change filters to validate them later.
|
||||||
change_filters = []
|
change_filters = []
|
||||||
|
50
qutebrowser/config/configcache.py
Normal file
50
qutebrowser/config/configcache.py
Normal 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]
|
@ -28,6 +28,7 @@ from qutebrowser.config import (config, configdata, configfiles, configtypes,
|
|||||||
configexc, configcommands)
|
configexc, configcommands)
|
||||||
from qutebrowser.utils import (objreg, usertypes, log, standarddir, message,
|
from qutebrowser.utils import (objreg, usertypes, log, standarddir, message,
|
||||||
qtutils)
|
qtutils)
|
||||||
|
from qutebrowser.config import configcache
|
||||||
from qutebrowser.misc import msgbox, objects
|
from qutebrowser.misc import msgbox, objects
|
||||||
|
|
||||||
|
|
||||||
@ -44,6 +45,7 @@ def early_init(args):
|
|||||||
config.instance = config.Config(yaml_config=yaml_config)
|
config.instance = config.Config(yaml_config=yaml_config)
|
||||||
config.val = config.ConfigContainer(config.instance)
|
config.val = config.ConfigContainer(config.instance)
|
||||||
config.key_instance = config.KeyConfig(config.instance)
|
config.key_instance = config.KeyConfig(config.instance)
|
||||||
|
config.cache = configcache.ConfigCache()
|
||||||
yaml_config.setParent(config.instance)
|
yaml_config.setParent(config.instance)
|
||||||
|
|
||||||
for cf in config.change_filters:
|
for cf in config.change_filters:
|
||||||
|
@ -719,9 +719,9 @@ class TabbedBrowser(QWidget):
|
|||||||
except TabDeletedError:
|
except TabDeletedError:
|
||||||
# We can get signals for tabs we already deleted...
|
# We can get signals for tabs we already deleted...
|
||||||
return
|
return
|
||||||
start = config.val.colors.tabs.indicator.start
|
start = config.cache['colors.tabs.indicator.start']
|
||||||
stop = config.val.colors.tabs.indicator.stop
|
stop = config.cache['colors.tabs.indicator.stop']
|
||||||
system = config.val.colors.tabs.indicator.system
|
system = config.cache['colors.tabs.indicator.system']
|
||||||
color = utils.interpolate_color(start, stop, perc, system)
|
color = utils.interpolate_color(start, stop, perc, system)
|
||||||
self.widget.set_tab_indicator_color(idx, color)
|
self.widget.set_tab_indicator_color(idx, color)
|
||||||
self.widget.update_tab_title(idx)
|
self.widget.update_tab_title(idx)
|
||||||
|
@ -139,9 +139,9 @@ class TabWidget(QTabWidget):
|
|||||||
"""
|
"""
|
||||||
tab = self.widget(idx)
|
tab = self.widget(idx)
|
||||||
if tab.data.pinned:
|
if tab.data.pinned:
|
||||||
fmt = config.val.tabs.title.format_pinned
|
fmt = config.cache['tabs.title.format_pinned']
|
||||||
else:
|
else:
|
||||||
fmt = config.val.tabs.title.format
|
fmt = config.cache['tabs.title.format']
|
||||||
|
|
||||||
if (field is not None and
|
if (field is not None and
|
||||||
(fmt is None or ('{' + field + '}') not in fmt)):
|
(fmt is None or ('{' + field + '}') not in fmt)):
|
||||||
@ -604,7 +604,7 @@ class TabBar(QTabBar):
|
|||||||
minimum_size = self.minimumTabSizeHint(index)
|
minimum_size = self.minimumTabSizeHint(index)
|
||||||
height = minimum_size.height()
|
height = minimum_size.height()
|
||||||
if self.vertical:
|
if self.vertical:
|
||||||
confwidth = str(config.val.tabs.width)
|
confwidth = str(config.cache['tabs.width'])
|
||||||
if confwidth.endswith('%'):
|
if confwidth.endswith('%'):
|
||||||
main_window = objreg.get('main-window', scope='window',
|
main_window = objreg.get('main-window', scope='window',
|
||||||
window=self._win_id)
|
window=self._win_id)
|
||||||
@ -614,7 +614,7 @@ class TabBar(QTabBar):
|
|||||||
width = int(confwidth)
|
width = int(confwidth)
|
||||||
size = QSize(max(minimum_size.width(), width), height)
|
size = QSize(max(minimum_size.width(), width), height)
|
||||||
else:
|
else:
|
||||||
if config.val.tabs.pinned.shrink:
|
if config.cache['tabs.pinned.shrink']:
|
||||||
pinned = self._tab_pinned(index)
|
pinned = self._tab_pinned(index)
|
||||||
pinned_count, pinned_width = self._pinned_statistics()
|
pinned_count, pinned_width = self._pinned_statistics()
|
||||||
else:
|
else:
|
||||||
@ -652,15 +652,15 @@ class TabBar(QTabBar):
|
|||||||
tab = QStyleOptionTab()
|
tab = QStyleOptionTab()
|
||||||
self.initStyleOption(tab, idx)
|
self.initStyleOption(tab, idx)
|
||||||
|
|
||||||
# pylint: disable=bad-config-option
|
setting = 'colors.tabs'
|
||||||
setting = config.val.colors.tabs
|
|
||||||
# pylint: enable=bad-config-option
|
|
||||||
if idx == selected:
|
if idx == selected:
|
||||||
setting = setting.selected
|
setting += '.selected'
|
||||||
setting = setting.odd if (idx + 1) % 2 else setting.even
|
setting += '.odd' if (idx + 1) % 2 else '.even'
|
||||||
|
|
||||||
tab.palette.setColor(QPalette.Window, setting.bg)
|
tab.palette.setColor(QPalette.Window,
|
||||||
tab.palette.setColor(QPalette.WindowText, setting.fg)
|
config.cache[setting + '.bg'])
|
||||||
|
tab.palette.setColor(QPalette.WindowText,
|
||||||
|
config.cache[setting + '.fg'])
|
||||||
|
|
||||||
indicator_color = self.tab_indicator_color(idx)
|
indicator_color = self.tab_indicator_color(idx)
|
||||||
tab.palette.setColor(QPalette.Base, indicator_color)
|
tab.palette.setColor(QPalette.Base, indicator_color)
|
||||||
@ -805,7 +805,7 @@ class TabBarStyle(QCommonStyle):
|
|||||||
elif element == QStyle.CE_TabBarTabLabel:
|
elif element == QStyle.CE_TabBarTabLabel:
|
||||||
if not opt.icon.isNull() and layouts.icon.isValid():
|
if not opt.icon.isNull() and layouts.icon.isValid():
|
||||||
self._draw_icon(layouts, opt, p)
|
self._draw_icon(layouts, opt, p)
|
||||||
alignment = (config.val.tabs.title.alignment |
|
alignment = (config.cache['tabs.title.alignment'] |
|
||||||
Qt.AlignVCenter | Qt.TextHideMnemonic)
|
Qt.AlignVCenter | Qt.TextHideMnemonic)
|
||||||
self._style.drawItemText(p, layouts.text, alignment, opt.palette,
|
self._style.drawItemText(p, layouts.text, alignment, opt.palette,
|
||||||
opt.state & QStyle.State_Enabled,
|
opt.state & QStyle.State_Enabled,
|
||||||
@ -878,8 +878,8 @@ class TabBarStyle(QCommonStyle):
|
|||||||
Return:
|
Return:
|
||||||
A Layout object with two QRects.
|
A Layout object with two QRects.
|
||||||
"""
|
"""
|
||||||
padding = config.val.tabs.padding
|
padding = config.cache['tabs.padding']
|
||||||
indicator_padding = config.val.tabs.indicator.padding
|
indicator_padding = config.cache['tabs.indicator.padding']
|
||||||
|
|
||||||
text_rect = QRect(opt.rect)
|
text_rect = QRect(opt.rect)
|
||||||
if not text_rect.isValid():
|
if not text_rect.isValid():
|
||||||
@ -890,7 +890,7 @@ class TabBarStyle(QCommonStyle):
|
|||||||
text_rect.adjust(padding.left, padding.top, -padding.right,
|
text_rect.adjust(padding.left, padding.top, -padding.right,
|
||||||
-padding.bottom)
|
-padding.bottom)
|
||||||
|
|
||||||
indicator_width = config.val.tabs.indicator.width
|
indicator_width = config.cache['tabs.indicator.width']
|
||||||
if indicator_width == 0:
|
if indicator_width == 0:
|
||||||
indicator_rect = QRect()
|
indicator_rect = QRect()
|
||||||
else:
|
else:
|
||||||
@ -933,9 +933,9 @@ class TabBarStyle(QCommonStyle):
|
|||||||
icon_state = (QIcon.On if opt.state & QStyle.State_Selected
|
icon_state = (QIcon.On if opt.state & QStyle.State_Selected
|
||||||
else QIcon.Off)
|
else QIcon.Off)
|
||||||
# reserve space for favicon when tab bar is vertical (issue #1968)
|
# 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
|
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
|
tab_icon_size = icon_size
|
||||||
else:
|
else:
|
||||||
actual_size = opt.icon.actualSize(icon_size, icon_mode, icon_state)
|
actual_size = opt.icon.actualSize(icon_size, icon_mode, icon_state)
|
||||||
|
@ -147,6 +147,8 @@ PERFECT_FILES = [
|
|||||||
'config/configcommands.py'),
|
'config/configcommands.py'),
|
||||||
('tests/unit/config/test_configutils.py',
|
('tests/unit/config/test_configutils.py',
|
||||||
'config/configutils.py'),
|
'config/configutils.py'),
|
||||||
|
('tests/unit/config/test_configcache.py',
|
||||||
|
'config/configcache.py'),
|
||||||
|
|
||||||
('tests/unit/utils/test_qtutils.py',
|
('tests/unit/utils/test_qtutils.py',
|
||||||
'utils/qtutils.py'),
|
'utils/qtutils.py'),
|
||||||
|
@ -42,7 +42,7 @@ from PyQt5.QtNetwork import QNetworkCookieJar
|
|||||||
import helpers.stubs as stubsmod
|
import helpers.stubs as stubsmod
|
||||||
import helpers.utils
|
import helpers.utils
|
||||||
from qutebrowser.config import (config, configdata, configtypes, configexc,
|
from qutebrowser.config import (config, configdata, configtypes, configexc,
|
||||||
configfiles)
|
configfiles, configcache)
|
||||||
from qutebrowser.utils import objreg, standarddir, utils, usertypes
|
from qutebrowser.utils import objreg, standarddir, utils, usertypes
|
||||||
from qutebrowser.browser import greasemonkey
|
from qutebrowser.browser import greasemonkey
|
||||||
from qutebrowser.browser.webkit import cookies
|
from qutebrowser.browser.webkit import cookies
|
||||||
@ -253,6 +253,9 @@ def config_stub(stubs, monkeypatch, configdata_init, yaml_config_stub):
|
|||||||
container = config.ConfigContainer(conf)
|
container = config.ConfigContainer(conf)
|
||||||
monkeypatch.setattr(config, 'val', container)
|
monkeypatch.setattr(config, 'val', container)
|
||||||
|
|
||||||
|
cache = configcache.ConfigCache()
|
||||||
|
monkeypatch.setattr(config, 'cache', cache)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
configtypes.Font.monospace_fonts = container.fonts.monospace
|
configtypes.Font.monospace_fonts = container.fonts.monospace
|
||||||
except configexc.NoOptionError:
|
except configexc.NoOptionError:
|
||||||
|
47
tests/unit/config/test_configcache.py
Normal file
47
tests/unit/config/test_configcache.py
Normal 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']
|
Loading…
Reference in New Issue
Block a user