Don't use stylesheets anymore for QTabWidget.

When using stylesheets there, all children (i.e. the QWebView) use
QStyleSheetStyle as well, which means the bug at [1] will annoy us.

We had to write our own font parsing as we can't use stylesheets, but at least
the bug is gone...

https://bugreports.qt-project.org/browse/QTBUG-40263
This commit is contained in:
Florian Bruhin 2014-08-04 17:00:01 +02:00
parent ee1b136807
commit 95df8a045c
3 changed files with 68 additions and 24 deletions

View File

@ -940,7 +940,7 @@ DATA = OrderedDict([
"Font used in the completion widget."), "Font used in the completion widget."),
('tabbar', ('tabbar',
SettingValue(types.Font(), '8pt ${_monospace}'), SettingValue(types.QtFont(), '8pt ${_monospace}'),
"Font used in the tabbar."), "Font used in the tabbar."),
('statusbar', ('statusbar',

View File

@ -25,13 +25,30 @@ import os.path
from sre_constants import error as RegexError from sre_constants import error as RegexError
from PyQt5.QtCore import QUrl, QStandardPaths from PyQt5.QtCore import QUrl, QStandardPaths
from PyQt5.QtGui import QColor from PyQt5.QtGui import QColor, QFont
from PyQt5.QtNetwork import QNetworkProxy from PyQt5.QtNetwork import QNetworkProxy
import qutebrowser.commands.utils as cmdutils import qutebrowser.commands.utils as cmdutils
from qutebrowser.utils.misc import get_standard_dir from qutebrowser.utils.misc import get_standard_dir
QSS_FONT_REGEX = re.compile(r"""
^(
(
# style
(?P<style>normal|italic|oblique) |
# weight (named | 100..900)
(
(?P<weight>[123456789]00) |
(?P<namedweight>normal|bold)
) |
# size (<float>pt | <int>px)
(?P<size>[0-9]+((\.[0-9]+)?[pP][tT]|[pP][xX]))
)\ # size/weight/style are space-separated
)* # 0-inf size/weight/style tags
(?P<family>[A-Za-z, "]*)$ # mandatory font family""", re.VERBOSE)
class ValidationError(ValueError): class ValidationError(ValueError):
"""Exception raised when a value for a config type was invalid. """Exception raised when a value for a config type was invalid.
@ -530,8 +547,45 @@ class Font(BaseType):
typestr = 'font' typestr = 'font'
def validate(self, value): def validate(self, value):
# We can't really validate anything here if not QSS_FONT_REGEX.match(value):
pass raise ValidationError(value, "must be a valid font")
class QtFont(Font):
"""A Font which gets converted to q QFont."""
def transform(self, value):
style_map = {
'normal': QFont.StyleNormal,
'italic': QFont.StyleItalic,
'oblique': QFont.StyleOblique,
}
weight_map = {
'normal': QFont.Normal,
'bold': QFont.Bold,
}
font = QFont()
match = QSS_FONT_REGEX.match(value)
style = match.group('style')
weight = match.group('weight')
namedweight = match.group('weight')
size = match.group('size')
family = match.group('family')
if style:
font.setStyle(style_map[style])
if namedweight:
font.setWeight(weight_map[namedweight])
if weight:
# based on qcssparser.cpp:setFontWeightFromValue
font.setWeight(min(int(weight) / 8, 99))
if size:
if size.lower().endswith('pt'):
font.setPointSizeF(float(size[:-2]))
elif size.lower().endswith('px'):
font.setPointSizeF(int(size[:-2]))
font.setFamily(family)
return font
class Regex(BaseType): class Regex(BaseType):

View File

@ -32,7 +32,6 @@ from PyQt5.QtWidgets import (QTabWidget, QTabBar, QSizePolicy, QCommonStyle,
QApplication) QApplication)
from PyQt5.QtGui import QIcon, QPalette, QColor from PyQt5.QtGui import QIcon, QPalette, QColor
from qutebrowser.config.style import set_register_stylesheet
from qutebrowser.utils.qt import qt_ensure_valid from qutebrowser.utils.qt import qt_ensure_valid
import qutebrowser.config.config as config import qutebrowser.config.config as config
@ -42,23 +41,7 @@ PM_TabBarPadding = QStyle.PM_CustomBase
class TabWidget(QTabWidget): class TabWidget(QTabWidget):
"""The tabwidget used for TabbedBrowser. """The tabwidget used for TabbedBrowser."""
Class attributes:
STYLESHEET: The stylesheet template to be used.
"""
STYLESHEET = """
QTabWidget::pane {{
position: absolute;
top: 0px;
}}
QTabBar {{
{font[tabbar]}
{color[tab.bg.bar]}
}}
"""
def __init__(self, parent): def __init__(self, parent):
super().__init__(parent) super().__init__(parent)
@ -66,7 +49,6 @@ class TabWidget(QTabWidget):
self.setTabBar(bar) self.setTabBar(bar)
bar.tabCloseRequested.connect(self.tabCloseRequested) bar.tabCloseRequested.connect(self.tabCloseRequested)
self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
set_register_stylesheet(self)
self.setDocumentMode(True) self.setDocumentMode(True)
self.setElideMode(Qt.ElideRight) self.setElideMode(Qt.ElideRight)
self.setUsesScrollButtons(True) self.setUsesScrollButtons(True)
@ -98,8 +80,9 @@ class TabWidget(QTabWidget):
tabbar.refresh() tabbar.refresh()
@pyqtSlot(str, str) @pyqtSlot(str, str)
def on_config_changed(self, section, _option): def on_config_changed(self, section, option):
"""Update attributes when config changed.""" """Update attributes when config changed."""
self.tabBar().on_config_changed(section, option)
if section == 'tabbar': if section == 'tabbar':
self._init_config() self._init_config()
@ -119,6 +102,7 @@ class TabBar(QTabBar):
def __init__(self, parent=None): def __init__(self, parent=None):
super().__init__(parent) super().__init__(parent)
self.setStyle(TabBarStyle(self.style())) self.setStyle(TabBarStyle(self.style()))
self.setFont(config.get('fonts', 'tabbar'))
self.vertical = False self.vertical = False
def __repr__(self): def __repr__(self):
@ -141,6 +125,12 @@ class TabBar(QTabBar):
self.setTabData(idx, color) self.setTabData(idx, color)
self.update(self.tabRect(idx)) self.update(self.tabRect(idx))
@pyqtSlot(str, str)
def on_config_changed(self, section, option):
"""Update attributes when config changed."""
if section == 'fonts' and option == 'tabbar':
self.setFont(config.get('fonts', 'tabbar'))
def mousePressEvent(self, e): def mousePressEvent(self, e):
"""Override mousePressEvent to close tabs if configured.""" """Override mousePressEvent to close tabs if configured."""
button = config.get('tabbar', 'close-mouse-button') button = config.get('tabbar', 'close-mouse-button')