summaryrefslogtreecommitdiffstats
path: root/src/widgets/styles/qstylesheetstyle.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/widgets/styles/qstylesheetstyle.cpp')
-rw-r--r--src/widgets/styles/qstylesheetstyle.cpp990
1 files changed, 579 insertions, 411 deletions
diff --git a/src/widgets/styles/qstylesheetstyle.cpp b/src/widgets/styles/qstylesheetstyle.cpp
index b02e4011b2..655b224617 100644
--- a/src/widgets/styles/qstylesheetstyle.cpp
+++ b/src/widgets/styles/qstylesheetstyle.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qglobal.h>
#include "qstylesheetstyle_p.h"
@@ -95,7 +59,7 @@
#include <private/qstyleanimation_p.h>
#endif
#if QT_CONFIG(tabbar)
-#include <qtabbar.h>
+#include <private/qtabbar_p.h>
#endif
#include <QMetaProperty>
#if QT_CONFIG(mainwindow)
@@ -134,6 +98,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
using namespace QCss;
@@ -151,7 +117,7 @@ static QStyleSheetStyleCaches *styleSheetCaches = nullptr;
* the QStyleSheetStyle is a proxy. If used with others proxy style, we may end up with something like:
* QStyleSheetStyle -> ProxyStyle -> QStyleSheetStyle -> OriginalStyle
* Recursion may happen if the style call the widget()->style() again.
- * Not to mention the performence penalty of having two lookup of rules.
+ * Not to mention the performance penalty of having two lookup of rules.
*
* The first instance of QStyleSheetStyle will set globalStyleSheetStyle to itself. The second one
* will notice the globalStyleSheetStyle is not istelf and call its base style directly.
@@ -172,8 +138,6 @@ class QStyleSheetStyleRecursionGuard
if (globalStyleSheetStyle != 0 && globalStyleSheetStyle != this) { RETURN; } \
QStyleSheetStyleRecursionGuard recursion_guard(this);
-#define ceil(x) ((int)(x) + ((x) > 0 && (x) != (int)(x)))
-
enum PseudoElement {
PseudoElement_None,
PseudoElement_DownArrow,
@@ -470,15 +434,26 @@ struct QStyleSheetBoxData : public QSharedData
struct QStyleSheetPaletteData : public QSharedData
{
- QStyleSheetPaletteData(const QBrush &fg, const QBrush &sfg, const QBrush &sbg,
- const QBrush &abg)
- : foreground(fg), selectionForeground(sfg), selectionBackground(sbg),
- alternateBackground(abg) { }
+ QStyleSheetPaletteData(const QBrush &foreground,
+ const QBrush &selectedForeground,
+ const QBrush &selectedBackground,
+ const QBrush &alternateBackground,
+ const QBrush &placeHolderTextForeground,
+ const QBrush &accent)
+ : foreground(foreground)
+ , selectionForeground(selectedForeground)
+ , selectionBackground(selectedBackground)
+ , alternateBackground(alternateBackground)
+ , placeholderForeground(placeHolderTextForeground)
+ , accent(accent)
+ { }
QBrush foreground;
QBrush selectionForeground;
QBrush selectionBackground;
QBrush alternateBackground;
+ QBrush placeholderForeground;
+ QBrush accent;
};
struct QStyleSheetGeometryData : public QSharedData
@@ -650,7 +625,7 @@ public:
Q_DECLARE_TYPEINFO(QRenderRule, Q_RELOCATABLE_TYPE);
///////////////////////////////////////////////////////////////////////////////////////////
-static const char knownStyleHints[][45] = {
+static constexpr std::array<const char*, 90> knownStyleHints = {
"activate-on-singleclick",
"alignment",
"arrow-keys-navigate-into-children",
@@ -743,13 +718,10 @@ static const char knownStyleHints[][45] = {
"widget-animation-duration"
};
-static const int numKnownStyleHints = sizeof(knownStyleHints)/sizeof(knownStyleHints[0]);
-
-static QList<QVariant> subControlLayout(const QString& layout)
+static QList<QVariant> subControlLayout(QByteArrayView layout)
{
QList<QVariant> buttons;
- for (int i = 0; i < layout.count(); i++) {
- int button = layout[i].toLatin1();
+ for (int button : layout) {
switch (button) {
case 'm':
buttons.append(PseudoElement_MdiMinButton);
@@ -804,17 +776,16 @@ QHash<QStyle::SubControl, QRect> QStyleSheetStyle::titleBarLayout(const QWidget
const bool isMaximized = tb->titleBarState & Qt::WindowMaximized;
QRenderRule subRule = renderRule(w, tb);
QRect cr = subRule.contentsRect(tb->rect);
- QList<QVariant> layout = subRule.styleHint(QLatin1String("button-layout")).toList();
+ QList<QVariant> layout = subRule.styleHint("button-layout"_L1).toList();
if (layout.isEmpty())
- layout = subControlLayout(QLatin1String("I(T)HSmMX"));
+ layout = subControlLayout("I(T)HSmMX"_L1);
int offsets[3] = { 0, 0, 0 };
enum Where { Left, Right, Center, NoWhere } where = Left;
QList<ButtonInfo> infos;
- const int numLayouts = layout.size();
- infos.reserve(numLayouts);
- for (int i = 0; i < numLayouts; i++) {
- const int element = layout[i].toInt();
+ infos.reserve(layout.size());
+ for (const QVariant &val : std::as_const(layout)) {
+ const int element = val.toInt();
if (element == '(') {
where = Center;
} else if (element == ')') {
@@ -873,8 +844,7 @@ QHash<QStyle::SubControl, QRect> QStyleSheetStyle::titleBarLayout(const QWidget
}
}
- for (int i = 0; i < infos.size(); i++) {
- const ButtonInfo &info = infos[i];
+ for (const ButtonInfo &info : std::as_const(infos)) {
QRect lr = cr;
switch (info.where) {
case Center: {
@@ -990,10 +960,17 @@ QRenderRule::QRenderRule(const QList<Declaration> &declarations, const QObject *
bg = new QStyleSheetBackgroundData(brush, pixmap, repeat, alignment, origin, attachment, clip);
}
- QBrush sfg, fg;
- QBrush sbg, abg;
- if (v.extractPalette(&fg, &sfg, &sbg, &abg))
- pal = new QStyleSheetPaletteData(fg, sfg, sbg, abg);
+ QBrush foreground;
+ QBrush selectedForeground;
+ QBrush selectedBackground;
+ QBrush alternateBackground;
+ QBrush placeHolderTextForeground;
+ QBrush accent;
+ if (v.extractPalette(&foreground, &selectedForeground, &selectedBackground,
+ &alternateBackground, &placeHolderTextForeground, &accent)) {
+ pal = new QStyleSheetPaletteData(foreground, selectedForeground, selectedBackground,
+ alternateBackground, placeHolderTextForeground, accent);
+ }
QIcon imgIcon;
alignment = Qt::AlignCenter;
@@ -1014,7 +991,7 @@ QRenderRule::QRenderRule(const QList<Declaration> &declarations, const QObject *
palette = QToolTip::palette();
#endif
- for (int i = 0; i < declarations.count(); i++) {
+ for (int i = 0; i < declarations.size(); i++) {
const Declaration& decl = declarations.at(i);
if (decl.d->propertyId == BorderImage) {
QString uri;
@@ -1022,7 +999,7 @@ QRenderRule::QRenderRule(const QList<Declaration> &declarations, const QObject *
int cuts[4];
decl.borderImageValue(&uri, cuts, &horizStretch, &vertStretch);
- if (uri.isEmpty() || uri == QLatin1String("none")) {
+ if (uri.isEmpty() || uri == "none"_L1) {
if (bd && bd->bi)
bd->bi->pixmap = QPixmap();
} else {
@@ -1044,38 +1021,66 @@ QRenderRule::QRenderRule(const QList<Declaration> &declarations, const QObject *
int role = decl.d->values.at(0).variant.toInt();
if (role >= Value_FirstColorRole && role <= Value_LastColorRole)
defaultBackground = palette.color((QPalette::ColorRole)(role-Value_FirstColorRole));
- } else if (decl.d->property.startsWith(QLatin1String("qproperty-"), Qt::CaseInsensitive)) {
+ } else if (decl.d->property.startsWith("qproperty-"_L1, Qt::CaseInsensitive)) {
// intentionally left blank...
} else if (decl.d->propertyId == UnknownProperty) {
bool knownStyleHint = false;
- for (int i = 0; i < numKnownStyleHints; i++) {
- QLatin1String styleHint(knownStyleHints[i]);
+ for (const auto sh : knownStyleHints) {
+ QLatin1StringView styleHint(sh);
if (decl.d->property.compare(styleHint) == 0) {
- QString hintName = QString(styleHint);
- QVariant hintValue;
- if (hintName.endsWith(QLatin1String("alignment"))) {
- hintValue = (int) decl.alignmentValue();
- } else if (hintName.endsWith(QLatin1String("color"))) {
- hintValue = (int) decl.colorValue().rgba();
- } else if (hintName.endsWith(QLatin1String("size"))) {
- hintValue = decl.sizeValue();
- } else if (hintName.endsWith(QLatin1String("icon"))) {
- hintValue = decl.iconValue();
- } else if (hintName == QLatin1String("button-layout")
- && decl.d->values.count() != 0 && decl.d->values.at(0).type == Value::String) {
- hintValue = subControlLayout(decl.d->values.at(0).variant.toString());
- } else {
- int integer;
- decl.intValue(&integer);
- hintValue = integer;
- }
- styleHints[decl.d->property] = hintValue;
- knownStyleHint = true;
- break;
+ QString hintName = QString(styleHint);
+ QVariant hintValue;
+ if (hintName.endsWith("alignment"_L1)) {
+ hintValue = (int) decl.alignmentValue();
+ } else if (hintName.endsWith("color"_L1)) {
+ hintValue = (int) decl.colorValue().rgba();
+ } else if (hintName.endsWith("size"_L1)) {
+ // Check only for the 'em' case
+ const QString valueString = decl.d->values.at(0).variant.toString();
+ const bool isEmSize = valueString.endsWith(u"em", Qt::CaseInsensitive);
+ if (isEmSize || valueString.endsWith(u"ex", Qt::CaseInsensitive)) {
+ // 1em == size of font; 1ex == xHeight of font
+ // See lengthValueFromData helper in qcssparser.cpp
+ QFont fontForSize(font);
+ // if no font is specified, then use the widget font if possible
+ if (const QWidget *widget; !hasFont && (widget = qobject_cast<const QWidget*>(object)))
+ fontForSize = widget->font();
+
+ const QFontMetrics fontMetrics(fontForSize);
+ qreal pixelSize = isEmSize ? fontMetrics.height() : fontMetrics.xHeight();
+
+ // Transform size according to the 'em'/'ex' value
+ qreal emexSize = {};
+ if (decl.realValue(&emexSize, isEmSize ? "em" : "ex") && emexSize > 0) {
+ pixelSize *= emexSize;
+ const QSizeF newSize(pixelSize, pixelSize);
+ decl.d->parsed = QVariant::fromValue<QSizeF>(newSize);
+ hintValue = newSize;
+ } else {
+ qWarning("Invalid '%s' size for %s. Skipping.",
+ isEmSize ? "em" : "ex", qPrintable(valueString));
+ }
+ } else {
+ // Normal case where we receive a 'px' or 'pt' unit
+ hintValue = decl.sizeValue();
+ }
+ } else if (hintName.endsWith("icon"_L1)) {
+ hintValue = decl.iconValue();
+ } else if (hintName == "button-layout"_L1 && decl.d->values.size() != 0
+ && decl.d->values.at(0).type == QCss::Value::String) {
+ hintValue = subControlLayout(decl.d->values.at(0).variant.toString().toLatin1());
+ } else {
+ int integer;
+ decl.intValue(&integer);
+ hintValue = integer;
+ }
+ styleHints[decl.d->property] = hintValue;
+ knownStyleHint = true;
+ break;
}
}
if (!knownStyleHint)
- qDebug("Unknown property %s", qPrintable(decl.d->property));
+ qWarning("Unknown property %s", qPrintable(decl.d->property));
}
}
@@ -1390,7 +1395,7 @@ void QRenderRule::drawBackground(QPainter *p, const QRect& rect, const QPoint& o
// ### fix for gradients
const QPainterPath &borderPath = borderClip(originRect(rect, origin));
if (!borderPath.isEmpty()) {
- // Drawn intead of being used as clipping path for better visual quality
+ // Drawn instead of being used as clipping path for better visual quality
bool wasAntialiased = p->renderHints() & QPainter::Antialiasing;
p->setRenderHint(QPainter::Antialiasing);
p->fillPath(borderPath, brush);
@@ -1455,6 +1460,16 @@ void QRenderRule::configurePalette(QPalette *p, QPalette::ColorRole fr, QPalette
p->setBrush(QPalette::AlternateBase, pal->alternateBackground);
}
+void setDefault(QPalette *palette, QPalette::ColorGroup group, QPalette::ColorRole role,
+ const QBrush &defaultBrush, const QWidget *widget)
+{
+ const QPalette &widgetPalette = widget->palette();
+ if (widgetPalette.isBrushSet(group, role))
+ palette->setBrush(group, role, widgetPalette.brush(group, role));
+ else
+ palette->setBrush(group, role, defaultBrush);
+}
+
void QRenderRule::configurePalette(QPalette *p, QPalette::ColorGroup cg, const QWidget *w, bool embedded)
{
if (bg && bg->brush.style() != Qt::NoBrush) {
@@ -1476,11 +1491,15 @@ void QRenderRule::configurePalette(QPalette *p, QPalette::ColorGroup cg, const Q
return;
if (pal->foreground.style() != Qt::NoBrush) {
- p->setBrush(cg, QPalette::ButtonText, pal->foreground);
- p->setBrush(cg, w->foregroundRole(), pal->foreground);
- p->setBrush(cg, QPalette::WindowText, pal->foreground);
- p->setBrush(cg, QPalette::Text, pal->foreground);
- p->setBrush(cg, QPalette::PlaceholderText, pal->foreground);
+ setDefault(p, cg, QPalette::ButtonText, pal->foreground, w);
+ setDefault(p, cg, w->foregroundRole(), pal->foreground, w);
+ setDefault(p, cg, QPalette::WindowText, pal->foreground, w);
+ setDefault(p, cg, QPalette::Text, pal->foreground, w);
+ QColor phColor(pal->foreground.color());
+ phColor.setAlpha((phColor.alpha() + 1) / 2);
+ QBrush placeholder = pal->foreground;
+ placeholder.setColor(phColor);
+ setDefault(p, cg, QPalette::PlaceholderText, placeholder, w);
}
if (pal->selectionBackground.style() != Qt::NoBrush)
p->setBrush(cg, QPalette::Highlight, pal->selectionBackground);
@@ -1488,6 +1507,10 @@ void QRenderRule::configurePalette(QPalette *p, QPalette::ColorGroup cg, const Q
p->setBrush(cg, QPalette::HighlightedText, pal->selectionForeground);
if (pal->alternateBackground.style() != Qt::NoBrush)
p->setBrush(cg, QPalette::AlternateBase, pal->alternateBackground);
+ if (pal->placeholderForeground.style() != Qt::NoBrush)
+ p->setBrush(cg, QPalette::PlaceholderText, pal->placeholderForeground);
+ if (pal->accent.style() != Qt::NoBrush)
+ p->setBrush(cg, QPalette::Accent, pal->accent);
}
bool QRenderRule::hasModification() const
@@ -1533,48 +1556,62 @@ public:
const QMetaObject *metaObject = OBJECT_PTR(node)->metaObject();
#if QT_CONFIG(tooltip)
if (qstrcmp(metaObject->className(), "QTipLabel") == 0)
- return QStringList(QLatin1String("QToolTip"));
+ return QStringList("QToolTip"_L1);
#endif
QStringList result;
do {
- result += QString::fromLatin1(metaObject->className()).replace(QLatin1Char(':'), QLatin1Char('-'));
+ result += QString::fromLatin1(metaObject->className()).replace(u':', u'-');
metaObject = metaObject->superClass();
} while (metaObject != nullptr);
return result;
}
- QString attribute(NodePtr node, const QString& name) const override
+ QString attributeValue(NodePtr node, const QCss::AttributeSelector& aSelector) const override
{
if (isNullNode(node))
return QString();
+ const QString &name = aSelector.name;
QHash<QString, QString> &cache = m_attributeCache[OBJECT_PTR(node)];
QHash<QString, QString>::const_iterator cacheIt = cache.constFind(name);
if (cacheIt != cache.constEnd())
return cacheIt.value();
+ QVariant value;
+ QString valueStr;
QObject *obj = OBJECT_PTR(node);
- QVariant value = obj->property(name.toLatin1());
- if (!value.isValid()) {
- if (name == QLatin1String("class")) {
- QString className = QString::fromLatin1(obj->metaObject()->className());
- if (className.contains(QLatin1Char(':')))
- className.replace(QLatin1Char(':'), QLatin1Char('-'));
- cache[name] = className;
- return className;
- } else if (name == QLatin1String("style")) {
- QWidget *w = qobject_cast<QWidget *>(obj);
- QStyleSheetStyle *proxy = w ? qt_styleSheet(w->style()) : nullptr;
- if (proxy) {
- QString styleName = QString::fromLatin1(proxy->baseStyle()->metaObject()->className());
- cache[name] = styleName;
- return styleName;
+ const int propertyIndex = obj->metaObject()->indexOfProperty(name.toLatin1());
+ if (propertyIndex == -1) {
+ value = obj->property(name.toLatin1()); // might be a dynamic property
+ if (!value.isValid()) {
+ if (name == "class"_L1) {
+ QString className = QString::fromLatin1(obj->metaObject()->className());
+ if (className.contains(u':'))
+ className.replace(u':', u'-');
+ valueStr = className;
+ } else if (name == "style"_L1) {
+ QWidget *w = qobject_cast<QWidget *>(obj);
+ QStyleSheetStyle *proxy = w ? qt_styleSheet(w->style()) : nullptr;
+ if (proxy)
+ valueStr = QString::fromLatin1(proxy->baseStyle()->metaObject()->className());
}
}
+ } else {
+ const QMetaProperty property = obj->metaObject()->property(propertyIndex);
+ value = property.read(obj);
+ // support Qt 5 selector syntax, which required the integer enum value
+ if (property.isEnumType()) {
+ bool isNumber;
+ aSelector.value.toInt(&isNumber);
+ if (isNumber)
+ value.convert(QMetaType::fromType<int>());
+ }
+ }
+ if (value.isValid()) {
+ valueStr = (value.userType() == QMetaType::QStringList
+ || value.userType() == QMetaType::QVariantList)
+ ? value.toStringList().join(u' ')
+ : value.toString();
}
- QString valueStr = (value.userType() == QMetaType::QStringList
- || value.userType() == QMetaType::QVariantList)
- ? value.toStringList().join(QLatin1Char(' '))
- : value.toString();
cache[name] = valueStr;
return valueStr;
}
@@ -1585,11 +1622,11 @@ public:
const QMetaObject *metaObject = OBJECT_PTR(node)->metaObject();
#if QT_CONFIG(tooltip)
if (qstrcmp(metaObject->className(), "QTipLabel") == 0)
- return nodeName == QLatin1String("QToolTip");
+ return nodeName == "QToolTip"_L1;
#endif
do {
- const ushort *uc = (const ushort *)nodeName.constData();
- const ushort *e = uc + nodeName.length();
+ const auto *uc = reinterpret_cast<const char16_t *>(nodeName.constData());
+ const auto *e = uc + nodeName.size();
const uchar *c = (const uchar *)metaObject->className();
while (*c && uc != e && (*uc == *c || (*c == ':' && *uc == '-'))) {
++uc;
@@ -1639,7 +1676,8 @@ QList<QCss::StyleRule> QStyleSheetStyle::styleRules(const QObject *obj) const
defaultSs = getDefaultStyleSheet();
QStyle *bs = baseStyle();
styleSheetCaches->styleSheetCache.insert(bs, defaultSs);
- QObject::connect(bs, SIGNAL(destroyed(QObject*)), styleSheetCaches, SLOT(styleDestroyed(QObject*)), Qt::UniqueConnection);
+ QObject::connect(bs, &QStyle::destroyed, styleSheetCaches,
+ &QStyleSheetStyleCaches::styleDestroyed);
} else {
defaultSs = defaultCacheIt.value();
}
@@ -1650,7 +1688,7 @@ QList<QCss::StyleRule> QStyleSheetStyle::styleRules(const QObject *obj) const
QHash<const void *, StyleSheet>::const_iterator appCacheIt = styleSheetCaches->styleSheetCache.constFind(qApp);
if (appCacheIt == styleSheetCaches->styleSheetCache.constEnd()) {
QString ss = qApp->styleSheet();
- if (ss.startsWith(QLatin1String("file:///")))
+ if (ss.startsWith("file:///"_L1))
ss.remove(0, 8);
parser.init(ss, qApp->styleSheet() != ss);
if (Q_UNLIKELY(!parser.parse(&appSs)))
@@ -1674,7 +1712,7 @@ QList<QCss::StyleRule> QStyleSheetStyle::styleRules(const QObject *obj) const
if (objCacheIt == styleSheetCaches->styleSheetCache.constEnd()) {
parser.init(styleSheet);
if (!parser.parse(&ss)) {
- parser.init(QLatin1String("* {") + styleSheet + QLatin1Char('}'));
+ parser.init("* {"_L1 + styleSheet + u'}');
if (Q_UNLIKELY(!parser.parse(&ss)))
qWarning() << "Could not parse stylesheet of object" << o;
}
@@ -1686,8 +1724,8 @@ QList<QCss::StyleRule> QStyleSheetStyle::styleRules(const QObject *obj) const
objectSs.append(ss);
}
- for (int i = 0; i < objectSs.count(); i++)
- objectSs[i].depth = objectSs.count() - i + 2;
+ for (int i = 0; i < objectSs.size(); i++)
+ objectSs[i].depth = objectSs.size() - i + 2;
styleSelector.styleSheets += objectSs;
@@ -1704,7 +1742,7 @@ static QList<Declaration> declarations(const QList<StyleRule> &styleRules, const
quint64 pseudoClass = PseudoClass_Unspecified)
{
QList<Declaration> decls;
- for (int i = 0; i < styleRules.count(); i++) {
+ for (int i = 0; i < styleRules.size(); i++) {
const Selector& selector = styleRules.at(i).selectors.at(0);
// Rules with pseudo elements don't cascade. This is an intentional
// diversion for CSS
@@ -1811,9 +1849,9 @@ static void qt_check_if_internal_object(const QObject **obj, int *element)
Q_UNUSED(element);
#else
if (*obj && qstrcmp((*obj)->metaObject()->className(), "QDockWidgetTitleButton") == 0) {
- if ((*obj)->objectName() == QLatin1String("qt_dockwidget_closebutton")) {
+ if ((*obj)->objectName() == "qt_dockwidget_closebutton"_L1) {
*element = PseudoElement_DockWidgetCloseButton;
- } else if ((*obj)->objectName() == QLatin1String("qt_dockwidget_floatbutton")) {
+ } else if ((*obj)->objectName() == "qt_dockwidget_floatbutton"_L1) {
*element = PseudoElement_DockWidgetFloatButton;
}
*obj = (*obj)->parent();
@@ -1834,7 +1872,7 @@ QRenderRule QStyleSheetStyle::renderRule(const QObject *obj, int element, quint6
quint64 stateMask = 0;
const QList<StyleRule> rules = styleRules(obj);
- for (int i = 0; i < rules.count(); i++) {
+ for (int i = 0; i < rules.size(); i++) {
const Selector& selector = rules.at(i).selectors.at(0);
quint64 negated = 0;
stateMask |= selector.pseudoClass(&negated);
@@ -1849,7 +1887,7 @@ QRenderRule QStyleSheetStyle::renderRule(const QObject *obj, int element, quint6
}
- const QString part = QLatin1String(knownPseudoElements[element].name);
+ const QString part = QLatin1StringView(knownPseudoElements[element].name);
QList<Declaration> decls = declarations(rules, part, state);
QRenderRule newRule(decls, obj);
cache[state] = newRule;
@@ -2155,8 +2193,8 @@ bool QStyleSheetStyle::hasStyleRule(const QObject *obj, int part) const
return result;
}
- QString pseudoElement = QLatin1String(knownPseudoElements[part].name);
- for (int i = 0; i < rules.count(); i++) {
+ auto pseudoElement = QLatin1StringView(knownPseudoElements[part].name);
+ for (int i = 0; i < rules.size(); i++) {
const Selector& selector = rules.at(i).selectors.at(0);
if (pseudoElement.compare(selector.pseudoElement(), Qt::CaseInsensitive) == 0) {
cache[part] = true;
@@ -2463,11 +2501,12 @@ static QWidget *embeddedWidget(QWidget *w)
}
/** \internal
- in case w is an embedded widget, return the container widget
- (i.e, the widget for which the rules actualy apply)
- (exemple, if w is a lineedit embedded in a combobox, return the combobox)
+ Returns the widget whose style rules apply to \a w.
+
+ When \a w is an embedded widget, this is the container widget.
+ For example, if w is a line edit embedded in a combobox, this returns the combobox.
+ When \a w is not embedded, this function return \a w itself.
- if w is not embedded, return w itself
*/
static QWidget *containerWidget(const QWidget *w)
{
@@ -2555,8 +2594,9 @@ static quint64 extendedPseudoClass(const QWidget *w)
} else
if (const QPlainTextEdit *edit = qobject_cast<const QPlainTextEdit *>(w)) {
pc |= (edit->isReadOnly() ? PseudoClass_ReadOnly : PseudoClass_Editable);
- }
+ } else
#endif
+ {}
return pc;
}
@@ -2625,18 +2665,17 @@ void QStyleSheetStyle::setProperties(QWidget *w)
{
// scan decls for final occurrence of each "qproperty"
- QDuplicateTracker<QString> propertySet;
- propertySet.reserve(decls.size());
- for (int i = decls.count() - 1; i >= 0; --i) {
+ QDuplicateTracker<QString> propertySet(decls.size());
+ for (int i = decls.size() - 1; i >= 0; --i) {
const QString property = decls.at(i).d->property;
- if (!property.startsWith(QLatin1String("qproperty-"), Qt::CaseInsensitive))
+ if (!property.startsWith("qproperty-"_L1, Qt::CaseInsensitive))
continue;
if (!propertySet.hasSeen(property))
finals.append(i);
}
}
- for (int i = finals.count() - 1; i >= 0; --i) {
+ for (int i = finals.size() - 1; i >= 0; --i) {
const Declaration &decl = decls.at(finals[i]);
QStringView property = decl.d->property;
property = property.mid(10); // strip "qproperty-"
@@ -2670,6 +2709,9 @@ void QStyleSheetStyle::setProperties(QWidget *w)
default: v = decl.d->values.at(0).variant; break;
}
+ if (propertyL1 == QByteArrayView("styleSheet") && value == v)
+ continue;
+
w->setProperty(propertyL1, v);
}
}
@@ -2790,7 +2832,7 @@ static void updateObjects(const QList<const QObject *>& objects)
QCoreApplication::sendEvent(widget, &event);
QList<const QObject *> children;
children.reserve(widget->children().size() + 1);
- for (auto child: qAsConst(widget->children()))
+ for (auto child: std::as_const(widget->children()))
children.append(child);
updateObjects(children);
}
@@ -2858,7 +2900,9 @@ bool QStyleSheetStyle::initObject(const QObject *obj) const
const_cast<QWidget *>(w)->setAttribute(Qt::WA_StyleSheet, true);
}
- QObject::connect(obj, SIGNAL(destroyed(QObject*)), styleSheetCaches, SLOT(objectDestroyed(QObject*)), Qt::UniqueConnection);
+ connect(obj, &QObject::destroyed,
+ styleSheetCaches, &QStyleSheetStyleCaches::objectDestroyed,
+ Qt::UniqueConnection);
return true;
}
@@ -2872,7 +2916,7 @@ void QStyleSheetStyle::polish(QWidget *w)
if (styleSheetCaches->styleRulesCache.contains(w)) {
// the widget accessed its style pointer before polish (or repolish)
- // (exemple: the QAbstractSpinBox constructor ask for the stylehint)
+ // (example: the QAbstractSpinBox constructor ask for the stylehint)
styleSheetCaches->styleRulesCache.remove(w);
styleSheetCaches->hasStyleRuleCache.remove(w);
styleSheetCaches->renderRulesCache.remove(w);
@@ -2885,7 +2929,7 @@ void QStyleSheetStyle::polish(QWidget *w)
//set the WA_Hover attribute if one of the selector depends of the hover state
QList<StyleRule> rules = styleRules(w);
- for (int i = 0; i < rules.count(); i++) {
+ for (int i = 0; i < rules.size(); i++) {
const Selector& selector = rules.at(i).selectors.at(0);
quint64 negated = 0;
quint64 cssClass = selector.pseudoClass(&negated);
@@ -2902,10 +2946,10 @@ void QStyleSheetStyle::polish(QWidget *w)
QRenderRule rule = renderRule(sa, PseudoElement_None, PseudoClass_Enabled);
if ((rule.hasBorder() && rule.border()->hasBorderImage())
|| (rule.hasBackground() && !rule.background()->pixmap.isNull())) {
- QObject::connect(sa->horizontalScrollBar(), SIGNAL(valueChanged(int)),
- sa, SLOT(update()), Qt::UniqueConnection);
- QObject::connect(sa->verticalScrollBar(), SIGNAL(valueChanged(int)),
- sa, SLOT(update()), Qt::UniqueConnection);
+ connect(sa->horizontalScrollBar(), &QScrollBar::valueChanged,
+ sa, QOverload<>::of(&QAbstractScrollArea::update), Qt::UniqueConnection);
+ connect(sa->verticalScrollBar(), &QScrollBar::valueChanged,
+ sa, QOverload<>::of(&QAbstractScrollArea::update), Qt::UniqueConnection);
}
}
#endif
@@ -2975,7 +3019,7 @@ void QStyleSheetStyle::repolish(QWidget *w)
{
QList<const QObject *> children;
children.reserve(w->children().size() + 1);
- for (auto child: qAsConst(w->children()))
+ for (auto child: std::as_const(w->children()))
children.append(child);
children.append(w);
styleSheetCaches->styleSheetCache.remove(w);
@@ -3008,13 +3052,13 @@ void QStyleSheetStyle::unpolish(QWidget *w)
setGeometry(w);
w->setAttribute(Qt::WA_StyleSheetTarget, false);
w->setAttribute(Qt::WA_StyleSheet, false);
- QObject::disconnect(w, nullptr, this, nullptr);
+ w->disconnect(this);
#if QT_CONFIG(scrollarea)
if (QAbstractScrollArea *sa = qobject_cast<QAbstractScrollArea *>(w)) {
- QObject::disconnect(sa->horizontalScrollBar(), SIGNAL(valueChanged(int)),
- sa, SLOT(update()));
- QObject::disconnect(sa->verticalScrollBar(), SIGNAL(valueChanged(int)),
- sa, SLOT(update()));
+ disconnect(sa->horizontalScrollBar(), &QScrollBar::valueChanged,
+ sa, QOverload<>::of(&QAbstractScrollArea::update));
+ disconnect(sa->verticalScrollBar(), &QScrollBar::valueChanged,
+ sa, QOverload<>::of(&QAbstractScrollArea::update));
}
#endif
baseStyle()->unpolish(w);
@@ -3030,16 +3074,6 @@ void QStyleSheetStyle::unpolish(QApplication *app)
styleSheetCaches->styleSheetCache.remove(qApp);
}
-#if QT_CONFIG(tabbar)
-inline static bool verticalTabs(QTabBar::Shape shape)
-{
- return shape == QTabBar::RoundedWest
- || shape == QTabBar::RoundedEast
- || shape == QTabBar::TriangularWest
- || shape == QTabBar::TriangularEast;
-}
-#endif // QT_CONFIG(tabbar)
-
void QStyleSheetStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, QPainter *p,
const QWidget *w) const
{
@@ -3243,7 +3277,6 @@ void QStyleSheetStyle::drawComplexControl(ComplexControl cc, const QStyleOptionC
rule.configurePalette(&toolOpt.palette, QPalette::ButtonText, QPalette::Button);
toolOpt.font = rule.font.resolve(toolOpt.font);
toolOpt.rect = rule.borderRect(opt->rect);
- bool customArrow = tool->features & QStyleOptionToolButton::Arrow;
const auto customArrowElement = [tool]{
switch (tool->arrowType) {
case Qt::DownArrow: return PseudoElement_DownArrow;
@@ -3254,9 +3287,29 @@ void QStyleSheetStyle::drawComplexControl(ComplexControl cc, const QStyleOptionC
}
return PseudoElement_None;
};
- bool customDropDown = tool->features & QStyleOptionToolButton::MenuButtonPopup;
+ // if arrow/menu/indicators are requested, either draw them using the available rule,
+ // or let the base style draw them; but not both
+ const bool drawArrow = tool->features & QStyleOptionToolButton::Arrow;
+ bool customArrow = drawArrow && hasStyleRule(w, customArrowElement());
+ if (customArrow) {
+ toolOpt.features &= ~QStyleOptionToolButton::Arrow;
+ toolOpt.text = QString(); // we need to draw the arrow and the text ourselves
+ }
+ bool drawDropDown = tool->features & QStyleOptionToolButton::MenuButtonPopup;
+ bool customDropDown = drawDropDown && hasStyleRule(w, PseudoElement_ToolButtonMenu);
bool customDropDownArrow = false;
- bool customMenuIndicator = !customDropDown && (tool->features & QStyleOptionToolButton::HasMenu);
+ bool drawMenuIndicator = tool->features & QStyleOptionToolButton::HasMenu;
+ if (customDropDown) {
+ toolOpt.subControls &= ~QStyle::SC_ToolButtonMenu;
+ customDropDownArrow = hasStyleRule(w, PseudoElement_ToolButtonMenuArrow);
+ if (customDropDownArrow)
+ toolOpt.features &= ~(QStyleOptionToolButton::Menu | QStyleOptionToolButton::HasMenu);
+ }
+ const bool customMenuIndicator = (!drawDropDown && drawMenuIndicator)
+ && hasStyleRule(w, PseudoElement_ToolButtonMenuIndicator);
+ if (customMenuIndicator)
+ toolOpt.features &= ~QStyleOptionToolButton::HasMenu;
+
if (rule.hasNativeBorder()) {
if (tool->subControls & SC_ToolButton) {
//in some case (eg. the button is "auto raised") the style doesn't draw the background
@@ -3270,28 +3323,23 @@ void QStyleSheetStyle::drawComplexControl(ComplexControl cc, const QStyleOptionC
if (!(bflags & (State_Sunken | State_On | State_Raised)))
rule.drawBackground(p, toolOpt.rect);
}
- customArrow = customArrow && hasStyleRule(w, customArrowElement());
- if (customArrow)
- toolOpt.features &= ~QStyleOptionToolButton::Arrow;
- customDropDown = customDropDown && hasStyleRule(w, PseudoElement_ToolButtonMenu);
- if (customDropDown) {
- toolOpt.subControls &= ~QStyle::SC_ToolButtonMenu;
- customDropDownArrow = hasStyleRule(w, PseudoElement_ToolButtonMenuArrow);
- if (customDropDownArrow)
- toolOpt.features &= ~(QStyleOptionToolButton::Menu | QStyleOptionToolButton::HasMenu);
- }
- customMenuIndicator = customMenuIndicator && hasStyleRule(w, PseudoElement_ToolButtonMenuIndicator);
- if (customMenuIndicator)
- toolOpt.features &= ~QStyleOptionToolButton::HasMenu;
-
- if (rule.baseStyleCanDraw() && !(tool->features & QStyleOptionToolButton::Arrow)) {
- baseStyle()->drawComplexControl(cc, &toolOpt, p, w);
- } else {
- QWindowsStyle::drawComplexControl(cc, &toolOpt, p, w);
- }
- if (!customArrow && !customDropDown && !customMenuIndicator)
- return;
+ QStyleOptionToolButton nativeToolOpt(toolOpt);
+ // don't draw natively if we have a custom rule for menu indicators and/or buttons
+ if (customMenuIndicator)
+ nativeToolOpt.features &= ~(QStyleOptionToolButton::Menu | QStyleOptionToolButton::HasMenu);
+ if (customDropDown || customDropDownArrow)
+ nativeToolOpt.features &= ~(QStyleOptionToolButton::Menu | QStyleOptionToolButton::HasMenu | QStyleOptionToolButton::MenuButtonPopup);
+ // Let base or windows style draw the button, which will include the menu-button
+ if (rule.baseStyleCanDraw() && !(tool->features & QStyleOptionToolButton::Arrow))
+ baseStyle()->drawComplexControl(cc, &nativeToolOpt, p, w);
+ else
+ QWindowsStyle::drawComplexControl(cc, &nativeToolOpt, p, w);
+ // if we did draw natively, don't draw custom
+ if (nativeToolOpt.features & (QStyleOptionToolButton::Menu | QStyleOptionToolButton::HasMenu))
+ drawMenuIndicator = false;
+ if (nativeToolOpt.features & QStyleOptionToolButton::MenuButtonPopup && !customDropDownArrow)
+ drawDropDown = false;
} else {
rule.drawRule(p, opt->rect);
toolOpt.rect = rule.contentsRect(opt->rect);
@@ -3301,7 +3349,8 @@ void QStyleSheetStyle::drawComplexControl(ComplexControl cc, const QStyleOptionC
}
const QRect cr = toolOpt.rect;
- if (customDropDown) {
+ // Draw DropDownButton unless drawn before
+ if (drawDropDown) {
if (opt->subControls & QStyle::SC_ToolButtonMenu) {
QRenderRule subRule = renderRule(w, opt, PseudoElement_ToolButtonMenu);
QRect menuButtonRect = subControlRect(CC_ToolButton, opt, QStyle::SC_ToolButtonMenu, w);
@@ -3312,7 +3361,7 @@ void QStyleSheetStyle::drawComplexControl(ComplexControl cc, const QStyleOptionC
baseStyle()->drawPrimitive(PE_IndicatorButtonDropDown, &toolOpt, p, w);
}
- if (customDropDownArrow) {
+ if (customDropDownArrow || drawMenuIndicator) {
QRenderRule arrowRule = renderRule(w, opt, PseudoElement_ToolButtonMenuArrow);
QRect arrowRect = arrowRule.hasGeometry()
? positionRect(w, arrowRule, PseudoElement_ToolButtonMenuArrow, menuButtonRect, toolOpt.direction)
@@ -3325,11 +3374,12 @@ void QStyleSheetStyle::drawComplexControl(ComplexControl cc, const QStyleOptionC
}
}
}
- } else if (customMenuIndicator) {
+ } else if (drawMenuIndicator) {
QRenderRule subRule = renderRule(w, opt, PseudoElement_ToolButtonMenuIndicator);
- QRect r = subRule.hasGeometry()
- ? positionRect(w, subRule, PseudoElement_ToolButtonMenuIndicator, toolOpt.rect, toolOpt.direction)
- : subRule.contentsRect(opt->rect);
+
+ // content padding does not impact the indicator, so use the original rect to
+ // calculate position of the sub element within the toplevel rule
+ QRect r = positionRect(w, rule, subRule, PseudoElement_ToolButtonMenuIndicator, opt->rect, toolOpt.direction);
if (subRule.hasDrawable()) {
subRule.drawRule(p, r);
} else {
@@ -3339,29 +3389,37 @@ void QStyleSheetStyle::drawComplexControl(ComplexControl cc, const QStyleOptionC
}
toolOpt.rect = cr;
+ // If we don't have a custom arrow, then the arrow will have been rendered
+ // already by the base style when drawing the label.
if (customArrow) {
const auto arrowElement = customArrowElement();
QRenderRule subRule = renderRule(w, opt, arrowElement);
- QRect r = subRule.hasGeometry() ? positionRect(w, subRule, arrowElement, toolOpt.rect, toolOpt.direction)
- : subRule.contentsRect(toolOpt.rect);
- if (subRule.hasDrawable()) {
- subRule.drawRule(p, r);
- } else {
- toolOpt.rect = r;
- const auto arrowElement = [&toolOpt] {
- switch (toolOpt.arrowType) {
- case Qt::DownArrow: return QStyle::PE_IndicatorArrowDown;
- case Qt::UpArrow: return QStyle::PE_IndicatorArrowUp;
- case Qt::LeftArrow: return QStyle::PE_IndicatorArrowLeft;
- case Qt::RightArrow: return QStyle::PE_IndicatorArrowRight;
- case Qt::NoArrow: break;
- }
- return QStyle::PE_IndicatorArrowDown; // never happens
- };
- baseStyle()->drawPrimitive(arrowElement(), &toolOpt, p, w);
+ QRect arrowRect = subRule.hasGeometry() ? positionRect(w, subRule, arrowElement, toolOpt.rect, toolOpt.direction)
+ : subRule.contentsRect(toolOpt.rect);
+
+ switch (toolOpt.toolButtonStyle) {
+ case Qt::ToolButtonIconOnly:
+ break;
+ case Qt::ToolButtonTextOnly:
+ case Qt::ToolButtonTextBesideIcon:
+ case Qt::ToolButtonTextUnderIcon: {
+ // The base style needs to lay out the contents and will render the styled
+ // arrow icons, unless the geometry is defined in the style sheet.
+ toolOpt.text = tool->text;
+ if (!subRule.hasGeometry())
+ toolOpt.features |= QStyleOptionToolButton::Arrow;
+ drawControl(CE_ToolButtonLabel, &toolOpt, p, w);
+ if (!subRule.hasGeometry())
+ return;
+ break;
}
+ case Qt::ToolButtonFollowStyle:
+ // QToolButton handles this, so must never happen
+ Q_ASSERT(false);
+ break;
+ }
+ subRule.drawRule(p, arrowRect);
}
-
return;
}
break;
@@ -3443,14 +3501,14 @@ void QStyleSheetStyle::drawComplexControl(ComplexControl cc, const QStyleOptionC
if (hasStyleRule(w, PseudoElement_MdiCloseButton)
|| hasStyleRule(w, PseudoElement_MdiNormalButton)
|| hasStyleRule(w, PseudoElement_MdiMinButton)) {
- QList<QVariant> layout = rule.styleHint(QLatin1String("button-layout")).toList();
+ QList<QVariant> layout = rule.styleHint("button-layout"_L1).toList();
if (layout.isEmpty())
- layout = subControlLayout(QLatin1String("mNX"));
+ layout = subControlLayout("mNX");
QStyleOptionComplex optCopy(*opt);
optCopy.subControls = { };
- for (int i = 0; i < layout.count(); i++) {
- int layoutButton = layout[i].toInt();
+ for (const QVariant &val : std::as_const(layout)) {
+ int layoutButton = val.toInt();
if (layoutButton < PseudoElement_MdiCloseButton
|| layoutButton > PseudoElement_MdiNormalButton)
continue;
@@ -3481,6 +3539,7 @@ void QStyleSheetStyle::drawComplexControl(ComplexControl cc, const QStyleOptionC
break;
subRule.drawRule(p, opt->rect);
QHash<QStyle::SubControl, QRect> layout = titleBarLayout(w, tb);
+ const auto paintDeviceDpr = p->device()->devicePixelRatio();
QRect ir;
ir = layout[SC_TitleBarLabel];
@@ -3491,8 +3550,6 @@ void QStyleSheetStyle::drawComplexControl(ComplexControl cc, const QStyleOptionC
p->drawText(ir.x(), ir.y(), ir.width(), ir.height(), Qt::AlignLeft | Qt::AlignVCenter | Qt::TextSingleLine, tb->text);
}
- QPixmap pm;
-
ir = layout[SC_TitleBarSysMenu];
if (ir.isValid()) {
QRenderRule subSubRule = renderRule(w, opt, PseudoElement_TitleBarSysMenu);
@@ -3502,7 +3559,9 @@ void QStyleSheetStyle::drawComplexControl(ComplexControl cc, const QStyleOptionC
tb->icon.paint(p, ir);
} else {
int iconSize = pixelMetric(PM_SmallIconSize, tb, w);
- pm = standardIcon(SP_TitleBarMenuButton, nullptr, w).pixmap(iconSize, iconSize);
+ const QSize sz(iconSize, iconSize);
+ const auto pm = standardIcon(SP_TitleBarMenuButton, nullptr, w)
+ .pixmap(sz, paintDeviceDpr);
drawItemPixmap(p, ir, Qt::AlignCenter, pm);
}
}
@@ -3512,15 +3571,14 @@ void QStyleSheetStyle::drawComplexControl(ComplexControl cc, const QStyleOptionC
QRenderRule subSubRule = renderRule(w, opt, PseudoElement_TitleBarCloseButton);
subSubRule.drawRule(p, ir);
- QSize sz = subSubRule.contentsRect(ir).size();
- if ((tb->titleBarFlags & Qt::WindowType_Mask) == Qt::Tool)
- pm = standardIcon(SP_DockWidgetCloseButton, nullptr, w).pixmap(sz);
- else
- pm = standardIcon(SP_TitleBarCloseButton, nullptr, w).pixmap(sz);
+ const QSize sz = subSubRule.contentsRect(ir).size();
+ const auto type = ((tb->titleBarFlags & Qt::WindowType_Mask) == Qt::Tool)
+ ? SP_DockWidgetCloseButton : SP_TitleBarCloseButton;
+ const auto pm = standardIcon(type, nullptr, w).pixmap(sz, paintDeviceDpr);
drawItemPixmap(p, ir, Qt::AlignCenter, pm);
}
- int pes[] = {
+ constexpr std::array<int, 6> pes = {
PseudoElement_TitleBarMaxButton,
PseudoElement_TitleBarMinButton,
PseudoElement_TitleBarNormalButton,
@@ -3529,15 +3587,15 @@ void QStyleSheetStyle::drawComplexControl(ComplexControl cc, const QStyleOptionC
PseudoElement_TitleBarContextHelpButton
};
- for (unsigned int i = 0; i < sizeof(pes)/sizeof(int); i++) {
- int pe = pes[i];
+ for (int pe : pes) {
QStyle::SubControl sc = knownPseudoElements[pe].subControl;
ir = layout[sc];
if (!ir.isValid())
continue;
QRenderRule subSubRule = renderRule(w, opt, pe);
subSubRule.drawRule(p, ir);
- pm = standardIcon(subControlIcon(pe), nullptr, w).pixmap(subSubRule.contentsRect(ir).size());
+ const QSize sz = subSubRule.contentsRect(ir).size();
+ const auto pm = standardIcon(subControlIcon(pe), nullptr, w).pixmap(sz, paintDeviceDpr);
drawItemPixmap(p, ir, Qt::AlignCenter, pm);
}
@@ -3553,6 +3611,37 @@ void QStyleSheetStyle::drawComplexControl(ComplexControl cc, const QStyleOptionC
baseStyle()->drawComplexControl(cc, opt, p, w);
}
+void QStyleSheetStyle::renderMenuItemIcon(const QStyleOptionMenuItem *mi, QPainter *p, const QWidget *w,
+ const QRect &rect, QRenderRule &subRule) const
+{
+ const QIcon::Mode mode = mi->state & QStyle::State_Enabled
+ ? (mi->state & QStyle::State_Selected ? QIcon::Active : QIcon::Normal)
+ : QIcon::Disabled;
+ const bool checked = mi->checkType != QStyleOptionMenuItem::NotCheckable && mi->checked;
+ const auto iconSize = pixelMetric(PM_SmallIconSize, mi, w);
+ const QSize sz(iconSize, iconSize);
+ const QPixmap pixmap(mi->icon.pixmap(sz, p->device()->devicePixelRatio(), mode,
+ checked ? QIcon::On : QIcon::Off));
+ const int pixw = pixmap.width() / pixmap.devicePixelRatio();
+ const int pixh = pixmap.height() / pixmap.devicePixelRatio();
+ QRenderRule iconRule = renderRule(w, mi, PseudoElement_MenuIcon);
+ if (!iconRule.hasGeometry()) {
+ iconRule.geo = new QStyleSheetGeometryData(pixw, pixh, pixw, pixh, -1, -1);
+ } else {
+ iconRule.geo->width = pixw;
+ iconRule.geo->height = pixh;
+ }
+ QRect iconRect = positionRect(w, subRule, iconRule, PseudoElement_MenuIcon, rect, mi->direction);
+ if (mi->direction == Qt::LeftToRight)
+ iconRect.moveLeft(iconRect.left());
+ else
+ iconRect.moveRight(iconRect.right());
+ iconRule.drawRule(p, iconRect);
+ QRect pmr(0, 0, pixw, pixh);
+ pmr.moveCenter(iconRect.center());
+ p->drawPixmap(pmr.topLeft(), pixmap);
+}
+
void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter *p,
const QWidget *w) const
{
@@ -3666,7 +3755,8 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q
if (button->state & State_On)
state = QIcon::On;
- QPixmap pixmap = icon.pixmap(button->iconSize, mode, state);
+ const auto paintDeviceDpr = p->device()->devicePixelRatio();
+ QPixmap pixmap = icon.pixmap(button->iconSize, paintDeviceDpr, mode, state);
int pixmapWidth = pixmap.width() / pixmap.devicePixelRatio();
int pixmapHeight = pixmap.height() / pixmap.devicePixelRatio();
int labelWidth = pixmapWidth;
@@ -3833,42 +3923,18 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q
}
mi.palette.setBrush(QPalette::HighlightedText, mi.palette.brush(QPalette::ButtonText));
- bool checkable = mi.checkType != QStyleOptionMenuItem::NotCheckable;
- bool checked = checkable ? mi.checked : false;
-
- bool dis = !(opt->state & QStyle::State_Enabled),
- act = opt->state & QStyle::State_Selected;
-
int textRectOffset = m->maxIconWidth;
if (!mi.icon.isNull()) {
- QIcon::Mode mode = dis ? QIcon::Disabled : QIcon::Normal;
- if (act && !dis)
- mode = QIcon::Active;
- const QPixmap pixmap(mi.icon.pixmap(pixelMetric(PM_SmallIconSize), mode, checked ? QIcon::On : QIcon::Off));
- const int pixw = pixmap.width() / pixmap.devicePixelRatio();
- const int pixh = pixmap.height() / pixmap.devicePixelRatio();
- QRenderRule iconRule = renderRule(w, opt, PseudoElement_MenuIcon);
- if (!iconRule.hasGeometry()) {
- iconRule.geo = new QStyleSheetGeometryData(pixw, pixh, pixw, pixh, -1, -1);
- } else {
- iconRule.geo->width = pixw;
- iconRule.geo->height = pixh;
- }
- QRect iconRect = positionRect(w, subRule, iconRule, PseudoElement_MenuIcon, opt->rect, opt->direction);
- if (opt->direction == Qt::LeftToRight)
- iconRect.moveLeft(iconRect.left());
- else
- iconRect.moveRight(iconRect.right());
- iconRule.drawRule(p, iconRect);
- QRect pmr(0, 0, pixw, pixh);
- pmr.moveCenter(iconRect.center());
- p->drawPixmap(pmr.topLeft(), pixmap);
+ renderMenuItemIcon(&mi, p, w, opt->rect, subRule);
} else if (mi.menuHasCheckableItems) {
- QRenderRule subSubRule = renderRule(w, opt, PseudoElement_MenuCheckMark);
+ const bool checkable = mi.checkType != QStyleOptionMenuItem::NotCheckable;
+ const bool checked = checkable ? mi.checked : false;
+
+ const QRenderRule subSubRule = renderRule(w, opt, PseudoElement_MenuCheckMark);
const QRect cmRect = positionRect(w, subRule, subSubRule, PseudoElement_MenuCheckMark, opt->rect, opt->direction);
if (checkable && (subSubRule.hasDrawable() || checked)) {
QStyleOptionMenuItem newMi = mi;
- if (!dis)
+ if (opt->state & QStyle::State_Enabled)
newMi.state |= State_Enabled;
if (mi.checked)
newMi.state |= State_On;
@@ -3889,7 +3955,7 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q
int text_flags = Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine;
if (!styleHint(SH_UnderlineShortcut, &mi, w))
text_flags |= Qt::TextHideMnemonic;
- int t = s.indexOf(QLatin1Char('\t'));
+ qsizetype t = s.indexOf(u'\t');
if (t >= 0) {
QRect vShortcutRect = visualRect(opt->direction, mi.rect,
QRect(textRect.topRight(), QPoint(mi.rect.right(), textRect.bottom())));
@@ -3905,11 +3971,22 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q
mi.rect = positionRect(w, subRule, subRule2, PseudoElement_MenuRightArrow, opt->rect, mi.direction);
drawPrimitive(arrow, &mi, p, w);
}
+ } else if (!mi.icon.isNull() && hasStyleRule(w, PseudoElement_MenuIcon)) {
+ // we wouldn't be here if the item itself would be styled, so now we only want
+ // the text from the default style, and then draw the icon ourselves.
+ QStyleOptionMenuItem newMi = mi;
+ newMi.icon = {};
+ newMi.checkType = QStyleOptionMenuItem::NotCheckable;
+ if (rule.baseStyleCanDraw() && subRule.baseStyleCanDraw())
+ baseStyle()->drawControl(ce, &newMi, p, w);
+ else
+ ParentStyle::drawControl(ce, &newMi, p, w);
+ renderMenuItemIcon(&mi, p, w, opt->rect, subRule);
} else if (hasStyleRule(w, PseudoElement_MenuCheckMark) || hasStyleRule(w, PseudoElement_MenuRightArrow)) {
QWindowsStyle::drawControl(ce, &mi, p, w);
if (mi.checkType != QStyleOptionMenuItem::NotCheckable && !mi.checked) {
// We have a style defined, but QWindowsStyle won't draw anything if not checked.
- // So we mimick what QWindowsStyle would do.
+ // So we mimic what QWindowsStyle would do.
int checkcol = qMax<int>(mi.maxIconWidth, QWindowsStylePrivate::windowsCheckMarkWidth);
QRect vCheckRect = visualRect(opt->direction, mi.rect, QRect(mi.rect.x(), mi.rect.y(), checkcol, mi.rect.height()));
if (mi.state.testFlag(State_Enabled) && mi.state.testFlag(State_Selected)) {
@@ -3981,7 +4058,8 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q
if (spacing == -1)
spacing = 6;
QIcon::Mode mode = cb->state & State_Enabled ? QIcon::Normal : QIcon::Disabled;
- QPixmap pixmap = cb->currentIcon.pixmap(cb->iconSize, mode);
+ const auto paintDeviceDpr = p->device()->devicePixelRatio();
+ QPixmap pixmap = cb->currentIcon.pixmap(cb->iconSize, paintDeviceDpr, mode);
QRect iconRect(editRect);
iconRect.setWidth(cb->iconSize.width());
iconRect = alignedRect(cb->direction,
@@ -4042,15 +4120,22 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q
case CE_HeaderLabel:
if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(opt)) {
- QStyleOptionHeader hdr(*header);
+ QStyleOptionHeaderV2 hdr;
+ QStyleOptionHeader &v1Copy = hdr;
+ if (auto v2 = qstyleoption_cast<const QStyleOptionHeaderV2 *>(opt))
+ hdr = *v2;
+ else
+ v1Copy = *header;
QRenderRule subRule = renderRule(w, opt, PseudoElement_HeaderViewSection);
if (hasStyleRule(w, PseudoElement_HeaderViewUpArrow)
|| hasStyleRule(w, PseudoElement_HeaderViewDownArrow)) {
- const QRect arrowRect = subElementRect(SE_HeaderArrow, opt, w);
- if (hdr.orientation == Qt::Horizontal)
- hdr.rect.setWidth(hdr.rect.width() - arrowRect.width());
- else
- hdr.rect.setHeight(hdr.rect.height() - arrowRect.height());
+ if (hdr.sortIndicator != QStyleOptionHeader::None) {
+ const QRect arrowRect = subElementRect(SE_HeaderArrow, opt, w);
+ if (hdr.orientation == Qt::Horizontal)
+ hdr.rect.setWidth(hdr.rect.width() - arrowRect.width());
+ else
+ hdr.rect.setHeight(hdr.rect.height() - arrowRect.height());
+ }
}
subRule.configurePalette(&hdr.palette, QPalette::ButtonText, QPalette::Button);
if (subRule.hasFont) {
@@ -4150,6 +4235,7 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q
--chunkCount;
};
} else if (chunkWidth > 0) {
+ const auto ceil = [](qreal x) { return int(x) + (x > 0 && x != int(x)); };
const int chunkCount = ceil(qreal(fillWidth)/chunkWidth);
int x = reverse ? r.left() + r.width() - chunkWidth : r.x();
@@ -4190,12 +4276,11 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q
if (rule.hasDrawable()) {
rule.drawFrame(p, opt->rect);
p->save();
- switch (sgOpt->corner) {
- case Qt::BottomRightCorner: break;
- case Qt::BottomLeftCorner: p->rotate(90); break;
- case Qt::TopLeftCorner: p->rotate(180); break;
- case Qt::TopRightCorner: p->rotate(270); break;
- default: break;
+ static constexpr int rotation[] = { 180, 270, 90, 0 };
+ if (rotation[sgOpt->corner]) {
+ p->translate(opt->rect.center());
+ p->rotate(rotation[sgOpt->corner]);
+ p->translate(-opt->rect.center());
}
rule.drawImage(p, opt->rect);
p->restore();
@@ -4279,15 +4364,47 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q
case CE_ItemViewItem:
if (const QStyleOptionViewItem *vopt = qstyleoption_cast<const QStyleOptionViewItem *>(opt)) {
QRenderRule subRule = renderRule(w, opt, PseudoElement_ViewItem);
- if (subRule.hasDrawable() || hasStyleRule(w, PseudoElement_Indicator)) {
- QStyleOptionViewItem optCopy(*vopt);
+ QStyleOptionViewItem optCopy(*vopt);
+ if (subRule.hasDrawable()) {
subRule.configurePalette(&optCopy.palette, vopt->state & QStyle::State_Selected ? QPalette::HighlightedText : QPalette::Text,
vopt->state & QStyle::State_Selected ? QPalette::Highlight : QPalette::Base);
QWindowsStyle::drawControl(ce, &optCopy, p, w);
} else {
- QStyleOptionViewItem voptCopy(*vopt);
- subRule.configurePalette(&voptCopy.palette, QPalette::Text, QPalette::NoRole);
- baseStyle()->drawControl(ce, &voptCopy, p, w);
+ p->save();
+ if (hasStyleRule(w, PseudoElement_Indicator)) {
+ // there is a rule for the indicator, but no rule for the item itself (otherwise
+ // the previous path would have been taken); only draw the indicator using the
+ // rule (via QWindows/QCommonStyle), then let the base style handle the rest.
+ QStyleOptionViewItem optIndicator(*vopt);
+ subRule.configurePalette(&optIndicator.palette,
+ vopt->state & QStyle::State_Selected
+ ? QPalette::HighlightedText
+ : QPalette::Text,
+ vopt->state & QStyle::State_Selected
+ ? QPalette::Highlight
+ : QPalette::Base);
+ // only draw the indicator; no text, icon or background
+ optIndicator.backgroundBrush = Qt::NoBrush; // no background
+ optIndicator.text.clear();
+ optIndicator.icon = QIcon();
+ QWindowsStyle::drawControl(ce, &optIndicator, p, w);
+
+ // Now draw text, background,icon, and highlight, but not the indicator with
+ // the base style. Since we can't turn off HasCheckIndicator to prevent the base
+ // style from drawing the check indicator again (it would change how the item
+ // gets laid out) we have to clip the indicator that's already been painted.
+ const QRect crStyle = subElementRect(QStyle::SE_ItemViewItemCheckIndicator,
+ &optIndicator, w);
+ const QRect crBase = baseStyle()->subElementRect(QStyle::SE_ItemViewItemCheckIndicator,
+ &optIndicator, w);
+ const QRegion clipRegion = QRegion(p->hasClipping() ? p->clipRegion()
+ : QRegion(optIndicator.rect))
+ - crStyle.united(crBase);
+ p->setClipRegion(clipRegion);
+ }
+ subRule.configurePalette(&optCopy.palette, QPalette::Text, QPalette::NoRole);
+ baseStyle()->drawControl(ce, &optCopy, p, w);
+ p->restore();
}
return;
}
@@ -4305,6 +4422,7 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q
case CE_TabBarTabLabel:
case CE_TabBarTabShape:
if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(opt)) {
+ const auto foregroundRole = w ? w->foregroundRole() : QPalette::WindowText;
QRenderRule subRule = renderRule(w, opt, PseudoElement_TabBarTab);
QRect r = positionRect(w, subRule, PseudoElement_TabBarTab, opt->rect, opt->direction);
if (ce == CE_TabBarTabShape && subRule.hasDrawable() && tab->shape < QTabBar::TriangularNorth) {
@@ -4312,7 +4430,7 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q
return;
}
QStyleOptionTab tabCopy(*tab);
- subRule.configurePalette(&tabCopy.palette, QPalette::WindowText, QPalette::Base);
+ subRule.configurePalette(&tabCopy.palette, foregroundRole, QPalette::Base);
QFont oldFont = p->font();
if (subRule.hasFont)
p->setFont(subRule.font.resolve(p->font()));
@@ -4370,7 +4488,7 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q
QString titleText = p->fontMetrics().elidedText(dwOpt->title, Qt::ElideRight, r.width());
drawItemText(p, r,
- alignment, dwOpt->palette,
+ alignment | Qt::TextHideMnemonic, dwOpt->palette,
dwOpt->state & State_Enabled, titleText,
QPalette::WindowText);
@@ -4532,14 +4650,16 @@ void QStyleSheetStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *op
case PE_PanelLineEdit:
if (const QStyleOptionFrame *frm = qstyleoption_cast<const QStyleOptionFrame *>(opt)) {
-#if QT_CONFIG(spinbox)
- if (w && qobject_cast<const QAbstractSpinBox *>(w->parentWidget())) {
- QRenderRule spinboxRule = renderRule(w->parentWidget(), opt);
- if (!spinboxRule.hasNativeBorder() || !spinboxRule.baseStyleCanDraw())
- return;
- rule = spinboxRule;
+ // Fall back to container widget's render rule
+ if (w) {
+ if (QWidget *container = containerWidget(w); container != w) {
+ QRenderRule containerRule = renderRule(container, opt);
+ if (!containerRule.hasNativeBorder() || !containerRule.baseStyleCanDraw())
+ return;
+ rule = containerRule;
+ }
}
-#endif
+
if (rule.hasNativeBorder()) {
QStyleOptionFrame frmOpt(*frm);
rule.configurePalette(&frmOpt.palette, QPalette::Text, QPalette::Base);
@@ -4648,10 +4768,7 @@ void QStyleSheetStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *op
if (const QStyleOptionViewItem *vopt = qstyleoption_cast<const QStyleOptionViewItem *>(opt)) {
QRenderRule subRule = renderRule(w, opt, PseudoElement_TreeViewBranch);
if (subRule.hasDrawable()) {
- if ((vopt->state & QStyle::State_Selected) && vopt->showDecorationSelected)
- p->fillRect(vopt->rect, vopt->palette.highlight());
- else if (vopt->features & QStyleOptionViewItem::Alternate)
- p->fillRect(vopt->rect, vopt->palette.alternateBase());
+ proxy()->drawPrimitive(PE_PanelItemViewRow, vopt, p, w);
subRule.drawRule(p, opt->rect);
} else {
baseStyle()->drawPrimitive(pe, vopt, p, w);
@@ -4719,6 +4836,17 @@ void QStyleSheetStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *op
pseudoElement = PseudoElement_DockWidgetSeparator;
break;
+ case PE_PanelItemViewRow:
+ // For compatibility reasons, QTreeView draws different parts of
+ // the background of an item row separately, before calling the
+ // delegate to draw the item. The row background of an item is
+ // however not separately styleable through a style sheet, but
+ // only indirectly through the background of the item. To get the
+ // same background for all parts drawn by QTreeView, we have to
+ // use the background rule for the item here.
+ if (renderRule(w, opt, PseudoElement_ViewItem).hasBackground())
+ pseudoElement = PseudoElement_ViewItem;
+ break;
case PE_PanelItemViewItem:
pseudoElement = PseudoElement_ViewItem;
break;
@@ -4745,6 +4873,7 @@ void QStyleSheetStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *op
w = w->parentWidget(); //match on the QTabBar instead of the CloseButton
}
pseudoElement = PseudoElement_TabBarTabCloseButton;
+ break;
#endif
default:
@@ -5003,8 +5132,14 @@ int QStyleSheetStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const
if (!rule.hasNativeBorder() || rule.hasBox())
return 0;
break;
+
+ case PM_ScrollView_ScrollBarOverlap:
+ if (!proxy()->styleHint(SH_ScrollBar_Transient, opt, w))
+ return 0;
+ break;
#endif // QT_CONFIG(scrollbar)
+
case PM_ProgressBarChunkWidth:
subRule = renderRule(w, opt, PseudoElement_ProgressBarChunk);
if (subRule.hasContentsSize()) {
@@ -5077,9 +5212,8 @@ int QStyleSheetStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const
case PM_MessageBoxIconSize:
case PM_ButtonIconSize:
case PM_SmallIconSize:
- if (rule.hasStyleHint(QLatin1String("icon-size"))) {
- return rule.styleHint(QLatin1String("icon-size")).toSize().width();
- }
+ if (rule.hasStyleHint("icon-size"_L1))
+ return rule.styleHint("icon-size"_L1).toSize().width();
break;
case PM_DockWidgetTitleMargin: {
@@ -5272,7 +5406,7 @@ QSize QStyleSheetStyle::sizeFromContents(ContentsType ct, const QStyleOption *op
}
if ((pe == PseudoElement_Item) && (subRule.hasBox() || subRule.hasBorder() || subRule.hasFont)) {
QSize sz(csz);
- if (mi->text.contains(QLatin1Char('\t')))
+ if (mi->text.contains(u'\t'))
sz.rwidth() += 12; //as in QCommonStyle
if (!mi->icon.isNull()) {
const int pmSmall = pixelMetric(PM_SmallIconSize);
@@ -5332,13 +5466,25 @@ QSize QStyleSheetStyle::sizeFromContents(ContentsType ct, const QStyleOption *op
if (subRule.hasBox() || !subRule.hasNativeBorder())
sz = csz + QSize(vertical ? 0 : spaceForIcon, vertical ? spaceForIcon : 0);
if (subRule.hasFont) {
- QFont ruleFont = subRule.font.resolve(w->font());
- QFontMetrics fm(ruleFont);
- const QSize textSize = fm.size(Qt::TextShowMnemonic, text)
- + QSize(pixelMetric(PM_TabBarTabHSpace, opt, w),
- pixelMetric(PM_TabBarTabVSpace, opt, w));
- sz = sz.expandedTo(vertical ? textSize.transposed() : textSize);
+ // first we remove the space needed for the text using the default font
+ const QSize oldTextSize = opt->fontMetrics.size(Qt::TextShowMnemonic, text);
+ (vertical ? sz.rheight() : sz.rwidth()) -= oldTextSize.width();
+
+ // then we add the space needed when using the rule font to the relevant
+ // dimension, and constraint the other dimension to the maximum to make
+ // sure we don't grow, but also don't clip icons or buttons.
+ const QFont ruleFont = subRule.font.resolve(w->font());
+ const QFontMetrics fm(ruleFont);
+ const QSize textSize = fm.size(Qt::TextShowMnemonic, text);
+ if (vertical) {
+ sz.rheight() += textSize.width();
+ sz.rwidth() = qMax(textSize.height(), sz.width());
+ } else {
+ sz.rwidth() += textSize.width();
+ sz.rheight() = qMax(textSize.height(), sz.height());
+ }
}
+
return subRule.boxSize(subRule.adjustSize(sz));
}
sz = subRule.adjustSize(csz);
@@ -5353,13 +5499,13 @@ QSize QStyleSheetStyle::sizeFromContents(ContentsType ct, const QStyleOption *op
&& !hasStyleRule(w, PseudoElement_MdiMinButton))
break;
- QList<QVariant> layout = rule.styleHint(QLatin1String("button-layout")).toList();
+ QList<QVariant> layout = rule.styleHint("button-layout"_L1).toList();
if (layout.isEmpty())
- layout = subControlLayout(QLatin1String("mNX"));
+ layout = subControlLayout("mNX");
int width = 0, height = 0;
- for (int i = 0; i < layout.count(); i++) {
- int layoutButton = layout[i].toInt();
+ for (const QVariant &val : std::as_const(layout)) {
+ int layoutButton = val.toInt();
if (layoutButton < PseudoElement_MdiCloseButton
|| layoutButton > PseudoElement_MdiNormalButton)
continue;
@@ -5397,65 +5543,65 @@ QSize QStyleSheetStyle::sizeFromContents(ContentsType ct, const QStyleOption *op
/*!
\internal
*/
-static QLatin1String propertyNameForStandardPixmap(QStyle::StandardPixmap sp)
+static QLatin1StringView propertyNameForStandardPixmap(QStyle::StandardPixmap sp)
{
switch (sp) {
- case QStyle::SP_TitleBarMenuButton: return QLatin1String("titlebar-menu-icon");
- case QStyle::SP_TitleBarMinButton: return QLatin1String("titlebar-minimize-icon");
- case QStyle::SP_TitleBarMaxButton: return QLatin1String("titlebar-maximize-icon");
- case QStyle::SP_TitleBarCloseButton: return QLatin1String("titlebar-close-icon");
- case QStyle::SP_TitleBarNormalButton: return QLatin1String("titlebar-normal-icon");
- case QStyle::SP_TitleBarShadeButton: return QLatin1String("titlebar-shade-icon");
- case QStyle::SP_TitleBarUnshadeButton: return QLatin1String("titlebar-unshade-icon");
- case QStyle::SP_TitleBarContextHelpButton: return QLatin1String("titlebar-contexthelp-icon");
- case QStyle::SP_DockWidgetCloseButton: return QLatin1String("dockwidget-close-icon");
- case QStyle::SP_MessageBoxInformation: return QLatin1String("messagebox-information-icon");
- case QStyle::SP_MessageBoxWarning: return QLatin1String("messagebox-warning-icon");
- case QStyle::SP_MessageBoxCritical: return QLatin1String("messagebox-critical-icon");
- case QStyle::SP_MessageBoxQuestion: return QLatin1String("messagebox-question-icon");
- case QStyle::SP_DesktopIcon: return QLatin1String("desktop-icon");
- case QStyle::SP_TrashIcon: return QLatin1String("trash-icon");
- case QStyle::SP_ComputerIcon: return QLatin1String("computer-icon");
- case QStyle::SP_DriveFDIcon: return QLatin1String("floppy-icon");
- case QStyle::SP_DriveHDIcon: return QLatin1String("harddisk-icon");
- case QStyle::SP_DriveCDIcon: return QLatin1String("cd-icon");
- case QStyle::SP_DriveDVDIcon: return QLatin1String("dvd-icon");
- case QStyle::SP_DriveNetIcon: return QLatin1String("network-icon");
- case QStyle::SP_DirOpenIcon: return QLatin1String("directory-open-icon");
- case QStyle::SP_DirClosedIcon: return QLatin1String("directory-closed-icon");
- case QStyle::SP_DirLinkIcon: return QLatin1String("directory-link-icon");
- case QStyle::SP_FileIcon: return QLatin1String("file-icon");
- case QStyle::SP_FileLinkIcon: return QLatin1String("file-link-icon");
- case QStyle::SP_FileDialogStart: return QLatin1String("filedialog-start-icon");
- case QStyle::SP_FileDialogEnd: return QLatin1String("filedialog-end-icon");
- case QStyle::SP_FileDialogToParent: return QLatin1String("filedialog-parent-directory-icon");
- case QStyle::SP_FileDialogNewFolder: return QLatin1String("filedialog-new-directory-icon");
- case QStyle::SP_FileDialogDetailedView: return QLatin1String("filedialog-detailedview-icon");
- case QStyle::SP_FileDialogInfoView: return QLatin1String("filedialog-infoview-icon");
- case QStyle::SP_FileDialogContentsView: return QLatin1String("filedialog-contentsview-icon");
- case QStyle::SP_FileDialogListView: return QLatin1String("filedialog-listview-icon");
- case QStyle::SP_FileDialogBack: return QLatin1String("filedialog-backward-icon");
- case QStyle::SP_DirIcon: return QLatin1String("directory-icon");
- case QStyle::SP_DialogOkButton: return QLatin1String("dialog-ok-icon");
- case QStyle::SP_DialogCancelButton: return QLatin1String("dialog-cancel-icon");
- case QStyle::SP_DialogHelpButton: return QLatin1String("dialog-help-icon");
- case QStyle::SP_DialogOpenButton: return QLatin1String("dialog-open-icon");
- case QStyle::SP_DialogSaveButton: return QLatin1String("dialog-save-icon");
- case QStyle::SP_DialogCloseButton: return QLatin1String("dialog-close-icon");
- case QStyle::SP_DialogApplyButton: return QLatin1String("dialog-apply-icon");
- case QStyle::SP_DialogResetButton: return QLatin1String("dialog-reset-icon");
- case QStyle::SP_DialogDiscardButton: return QLatin1String("dialog-discard-icon");
- case QStyle::SP_DialogYesButton: return QLatin1String("dialog-yes-icon");
- case QStyle::SP_DialogNoButton: return QLatin1String("dialog-no-icon");
- case QStyle::SP_ArrowUp: return QLatin1String("uparrow-icon");
- case QStyle::SP_ArrowDown: return QLatin1String("downarrow-icon");
- case QStyle::SP_ArrowLeft: return QLatin1String("leftarrow-icon");
- case QStyle::SP_ArrowRight: return QLatin1String("rightarrow-icon");
- case QStyle::SP_ArrowBack: return QLatin1String("backward-icon");
- case QStyle::SP_ArrowForward: return QLatin1String("forward-icon");
- case QStyle::SP_DirHomeIcon: return QLatin1String("home-icon");
- case QStyle::SP_LineEditClearButton: return QLatin1String("lineedit-clear-button-icon");
- default: return QLatin1String("");
+ case QStyle::SP_TitleBarMenuButton: return "titlebar-menu-icon"_L1;
+ case QStyle::SP_TitleBarMinButton: return "titlebar-minimize-icon"_L1;
+ case QStyle::SP_TitleBarMaxButton: return "titlebar-maximize-icon"_L1;
+ case QStyle::SP_TitleBarCloseButton: return "titlebar-close-icon"_L1;
+ case QStyle::SP_TitleBarNormalButton: return "titlebar-normal-icon"_L1;
+ case QStyle::SP_TitleBarShadeButton: return "titlebar-shade-icon"_L1;
+ case QStyle::SP_TitleBarUnshadeButton: return "titlebar-unshade-icon"_L1;
+ case QStyle::SP_TitleBarContextHelpButton: return "titlebar-contexthelp-icon"_L1;
+ case QStyle::SP_DockWidgetCloseButton: return "dockwidget-close-icon"_L1;
+ case QStyle::SP_MessageBoxInformation: return "messagebox-information-icon"_L1;
+ case QStyle::SP_MessageBoxWarning: return "messagebox-warning-icon"_L1;
+ case QStyle::SP_MessageBoxCritical: return "messagebox-critical-icon"_L1;
+ case QStyle::SP_MessageBoxQuestion: return "messagebox-question-icon"_L1;
+ case QStyle::SP_DesktopIcon: return "desktop-icon"_L1;
+ case QStyle::SP_TrashIcon: return "trash-icon"_L1;
+ case QStyle::SP_ComputerIcon: return "computer-icon"_L1;
+ case QStyle::SP_DriveFDIcon: return "floppy-icon"_L1;
+ case QStyle::SP_DriveHDIcon: return "harddisk-icon"_L1;
+ case QStyle::SP_DriveCDIcon: return "cd-icon"_L1;
+ case QStyle::SP_DriveDVDIcon: return "dvd-icon"_L1;
+ case QStyle::SP_DriveNetIcon: return "network-icon"_L1;
+ case QStyle::SP_DirOpenIcon: return "directory-open-icon"_L1;
+ case QStyle::SP_DirClosedIcon: return "directory-closed-icon"_L1;
+ case QStyle::SP_DirLinkIcon: return "directory-link-icon"_L1;
+ case QStyle::SP_FileIcon: return "file-icon"_L1;
+ case QStyle::SP_FileLinkIcon: return "file-link-icon"_L1;
+ case QStyle::SP_FileDialogStart: return "filedialog-start-icon"_L1;
+ case QStyle::SP_FileDialogEnd: return "filedialog-end-icon"_L1;
+ case QStyle::SP_FileDialogToParent: return "filedialog-parent-directory-icon"_L1;
+ case QStyle::SP_FileDialogNewFolder: return "filedialog-new-directory-icon"_L1;
+ case QStyle::SP_FileDialogDetailedView: return "filedialog-detailedview-icon"_L1;
+ case QStyle::SP_FileDialogInfoView: return "filedialog-infoview-icon"_L1;
+ case QStyle::SP_FileDialogContentsView: return "filedialog-contentsview-icon"_L1;
+ case QStyle::SP_FileDialogListView: return "filedialog-listview-icon"_L1;
+ case QStyle::SP_FileDialogBack: return "filedialog-backward-icon"_L1;
+ case QStyle::SP_DirIcon: return "directory-icon"_L1;
+ case QStyle::SP_DialogOkButton: return "dialog-ok-icon"_L1;
+ case QStyle::SP_DialogCancelButton: return "dialog-cancel-icon"_L1;
+ case QStyle::SP_DialogHelpButton: return "dialog-help-icon"_L1;
+ case QStyle::SP_DialogOpenButton: return "dialog-open-icon"_L1;
+ case QStyle::SP_DialogSaveButton: return "dialog-save-icon"_L1;
+ case QStyle::SP_DialogCloseButton: return "dialog-close-icon"_L1;
+ case QStyle::SP_DialogApplyButton: return "dialog-apply-icon"_L1;
+ case QStyle::SP_DialogResetButton: return "dialog-reset-icon"_L1;
+ case QStyle::SP_DialogDiscardButton: return "dialog-discard-icon"_L1;
+ case QStyle::SP_DialogYesButton: return "dialog-yes-icon"_L1;
+ case QStyle::SP_DialogNoButton: return "dialog-no-icon"_L1;
+ case QStyle::SP_ArrowUp: return "uparrow-icon"_L1;
+ case QStyle::SP_ArrowDown: return "downarrow-icon"_L1;
+ case QStyle::SP_ArrowLeft: return "leftarrow-icon"_L1;
+ case QStyle::SP_ArrowRight: return "rightarrow-icon"_L1;
+ case QStyle::SP_ArrowBack: return "backward-icon"_L1;
+ case QStyle::SP_ArrowForward: return "forward-icon"_L1;
+ case QStyle::SP_DirHomeIcon: return "home-icon"_L1;
+ case QStyle::SP_LineEditClearButton: return "lineedit-clear-button-icon"_L1;
+ default: return ""_L1;
}
}
@@ -5486,7 +5632,8 @@ QPixmap QStyleSheetStyle::standardPixmap(StandardPixmap standardPixmap, const QS
QRenderRule rule = renderRule(w, opt);
if (rule.hasStyleHint(s)) {
QIcon icon = qvariant_cast<QIcon>(rule.styleHint(s));
- return icon.pixmap(16, 16); // ###: unhard-code this if someone complains
+ const auto dpr = w ? w->devicePixelRatio() : qApp->devicePixelRatio();
+ return icon.pixmap(QSize(16, 16), dpr);
}
}
return baseStyle()->standardPixmap(standardPixmap, opt, w);
@@ -5511,25 +5658,25 @@ int QStyleSheetStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWi
QRenderRule rule = renderRule(w, opt);
QString s;
switch (sh) {
- case SH_LineEdit_PasswordCharacter: s = QLatin1String("lineedit-password-character"); break;
- case SH_LineEdit_PasswordMaskDelay: s = QLatin1String("lineedit-password-mask-delay"); break;
- case SH_DitherDisabledText: s = QLatin1String("dither-disabled-text"); break;
- case SH_EtchDisabledText: s = QLatin1String("etch-disabled-text"); break;
- case SH_ItemView_ActivateItemOnSingleClick: s = QLatin1String("activate-on-singleclick"); break;
- case SH_ItemView_ShowDecorationSelected: s = QLatin1String("show-decoration-selected"); break;
- case SH_Table_GridLineColor: s = QLatin1String("gridline-color"); break;
- case SH_DialogButtonLayout: s = QLatin1String("button-layout"); break;
- case SH_ToolTipLabel_Opacity: s = QLatin1String("opacity"); break;
- case SH_ComboBox_Popup: s = QLatin1String("combobox-popup"); break;
- case SH_ComboBox_ListMouseTracking: s = QLatin1String("combobox-list-mousetracking"); break;
- case SH_MenuBar_AltKeyNavigation: s = QLatin1String("menubar-altkey-navigation"); break;
- case SH_Menu_Scrollable: s = QLatin1String("menu-scrollable"); break;
- case SH_DrawMenuBarSeparator: s = QLatin1String("menubar-separator"); break;
- case SH_MenuBar_MouseTracking: s = QLatin1String("mouse-tracking"); break;
- case SH_SpinBox_ClickAutoRepeatRate: s = QLatin1String("spinbox-click-autorepeat-rate"); break;
- case SH_SpinControls_DisableOnBounds: s = QLatin1String("spincontrol-disable-on-bounds"); break;
- case SH_MessageBox_TextInteractionFlags: s = QLatin1String("messagebox-text-interaction-flags"); break;
- case SH_ToolButton_PopupDelay: s = QLatin1String("toolbutton-popup-delay"); break;
+ case SH_LineEdit_PasswordCharacter: s = "lineedit-password-character"_L1; break;
+ case SH_LineEdit_PasswordMaskDelay: s = "lineedit-password-mask-delay"_L1; break;
+ case SH_DitherDisabledText: s = "dither-disabled-text"_L1; break;
+ case SH_EtchDisabledText: s = "etch-disabled-text"_L1; break;
+ case SH_ItemView_ActivateItemOnSingleClick: s = "activate-on-singleclick"_L1; break;
+ case SH_ItemView_ShowDecorationSelected: s = "show-decoration-selected"_L1; break;
+ case SH_Table_GridLineColor: s = "gridline-color"_L1; break;
+ case SH_DialogButtonLayout: s = "button-layout"_L1; break;
+ case SH_ToolTipLabel_Opacity: s = "opacity"_L1; break;
+ case SH_ComboBox_Popup: s = "combobox-popup"_L1; break;
+ case SH_ComboBox_ListMouseTracking: s = "combobox-list-mousetracking"_L1; break;
+ case SH_MenuBar_AltKeyNavigation: s = "menubar-altkey-navigation"_L1; break;
+ case SH_Menu_Scrollable: s = "menu-scrollable"_L1; break;
+ case SH_DrawMenuBarSeparator: s = "menubar-separator"_L1; break;
+ case SH_MenuBar_MouseTracking: s = "mouse-tracking"_L1; break;
+ case SH_SpinBox_ClickAutoRepeatRate: s = "spinbox-click-autorepeat-rate"_L1; break;
+ case SH_SpinControls_DisableOnBounds: s = "spincontrol-disable-on-bounds"_L1; break;
+ case SH_MessageBox_TextInteractionFlags: s = "messagebox-text-interaction-flags"_L1; break;
+ case SH_ToolButton_PopupDelay: s = "toolbutton-popup-delay"_L1; break;
case SH_ToolBox_SelectedPageTitleBold:
if (renderRule(w, opt, PseudoElement_ToolBoxTab).hasFont)
return 0;
@@ -5538,12 +5685,12 @@ int QStyleSheetStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWi
if (rule.hasPalette() && rule.palette()->foreground.style() != Qt::NoBrush)
return rule.palette()->foreground.color().rgba();
break;
- case SH_ScrollView_FrameOnlyAroundContents: s = QLatin1String("scrollview-frame-around-contents"); break;
- case SH_ScrollBar_ContextMenu: s = QLatin1String("scrollbar-contextmenu"); break;
- case SH_ScrollBar_LeftClickAbsolutePosition: s = QLatin1String("scrollbar-leftclick-absolute-position"); break;
- case SH_ScrollBar_MiddleClickAbsolutePosition: s = QLatin1String("scrollbar-middleclick-absolute-position"); break;
- case SH_ScrollBar_RollBetweenButtons: s = QLatin1String("scrollbar-roll-between-buttons"); break;
- case SH_ScrollBar_ScrollWhenPointerLeavesControl: s = QLatin1String("scrollbar-scroll-when-pointer-leaves-control"); break;
+ case SH_ScrollView_FrameOnlyAroundContents: s = "scrollview-frame-around-contents"_L1; break;
+ case SH_ScrollBar_ContextMenu: s = "scrollbar-contextmenu"_L1; break;
+ case SH_ScrollBar_LeftClickAbsolutePosition: s = "scrollbar-leftclick-absolute-position"_L1; break;
+ case SH_ScrollBar_MiddleClickAbsolutePosition: s = "scrollbar-middleclick-absolute-position"_L1; break;
+ case SH_ScrollBar_RollBetweenButtons: s = "scrollbar-roll-between-buttons"_L1; break;
+ case SH_ScrollBar_ScrollWhenPointerLeavesControl: s = "scrollbar-scroll-when-pointer-leaves-control"_L1; break;
case SH_TabBar_Alignment:
#if QT_CONFIG(tabwidget)
if (qobject_cast<const QTabWidget *>(w)) {
@@ -5552,7 +5699,7 @@ int QStyleSheetStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWi
return rule.position()->position;
}
#endif // QT_CONFIG(tabwidget)
- s = QLatin1String("alignment");
+ s = "alignment"_L1;
break;
#if QT_CONFIG(tabbar)
case SH_TabBar_CloseButtonPosition:
@@ -5566,8 +5713,8 @@ int QStyleSheetStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWi
}
break;
#endif
- case SH_TabBar_ElideMode: s = QLatin1String("tabbar-elide-mode"); break;
- case SH_TabBar_PreferNoArrows: s = QLatin1String("tabbar-prefer-no-arrows"); break;
+ case SH_TabBar_ElideMode: s = "tabbar-elide-mode"_L1; break;
+ case SH_TabBar_PreferNoArrows: s = "tabbar-prefer-no-arrows"_L1; break;
case SH_ComboBox_PopupFrameStyle:
#if QT_CONFIG(combobox)
if (qobject_cast<const QComboBox *>(w)) {
@@ -5581,8 +5728,8 @@ int QStyleSheetStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWi
}
#endif // QT_CONFIG(combobox)
break;
- case SH_DialogButtonBox_ButtonsHaveIcons: s = QLatin1String("dialogbuttonbox-buttons-have-icons"); break;
- case SH_Workspace_FillSpaceOnMaximize: s = QLatin1String("mdi-fill-space-on-maximize"); break;
+ case SH_DialogButtonBox_ButtonsHaveIcons: s = "dialogbuttonbox-buttons-have-icons"_L1; break;
+ case SH_Workspace_FillSpaceOnMaximize: s = "mdi-fill-space-on-maximize"_L1; break;
case SH_TitleBar_NoBorder:
if (rule.hasBorder())
return !rule.border()->borders[LeftEdge];
@@ -5593,10 +5740,14 @@ int QStyleSheetStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWi
return 1;
break;
}
- case SH_ItemView_ArrowKeysNavigateIntoChildren: s = QLatin1String("arrow-keys-navigate-into-children"); break;
- case SH_ItemView_PaintAlternatingRowColorsForEmptyArea: s = QLatin1String("paint-alternating-row-colors-for-empty-area"); break;
- case SH_TitleBar_ShowToolTipsOnButtons: s = QLatin1String("titlebar-show-tooltips-on-buttons"); break;
- case SH_Widget_Animation_Duration: s = QLatin1String("widget-animation-duration"); break;
+ case SH_ItemView_ArrowKeysNavigateIntoChildren: s = "arrow-keys-navigate-into-children"_L1; break;
+ case SH_ItemView_PaintAlternatingRowColorsForEmptyArea: s = "paint-alternating-row-colors-for-empty-area"_L1; break;
+ case SH_TitleBar_ShowToolTipsOnButtons: s = "titlebar-show-tooltips-on-buttons"_L1; break;
+ case SH_Widget_Animation_Duration: s = "widget-animation-duration"_L1; break;
+ case SH_ScrollBar_Transient:
+ if (!rule.hasNativeBorder() || rule.hasBox() || rule.hasDrawable())
+ return 0;
+ break;
default: break;
}
if (!s.isEmpty() && rule.hasStyleHint(s)) {
@@ -5915,14 +6066,14 @@ QRect QStyleSheetStyle::subControlRect(ComplexControl cc, const QStyleOptionComp
if (hasStyleRule(w, PseudoElement_MdiCloseButton)
|| hasStyleRule(w, PseudoElement_MdiNormalButton)
|| hasStyleRule(w, PseudoElement_MdiMinButton)) {
- QList<QVariant> layout = rule.styleHint(QLatin1String("button-layout")).toList();
+ QList<QVariant> layout = rule.styleHint("button-layout"_L1).toList();
if (layout.isEmpty())
- layout = subControlLayout(QLatin1String("mNX"));
+ layout = subControlLayout("mNX");
int x = 0, width = 0;
QRenderRule subRule;
- for (int i = 0; i < layout.count(); i++) {
- int layoutButton = layout[i].toInt();
+ for (const QVariant &val : std::as_const(layout)) {
+ int layoutButton = val.toInt();
if (layoutButton < PseudoElement_MdiCloseButton
|| layoutButton > PseudoElement_MdiNormalButton)
continue;
@@ -6078,8 +6229,22 @@ QRect QStyleSheetStyle::subElementRect(SubElement se, const QStyleOption *opt, c
case SE_HeaderLabel: {
QRenderRule subRule = renderRule(w, opt, PseudoElement_HeaderViewSection);
- if (subRule.hasBox() || !subRule.hasNativeBorder())
- return subRule.contentsRect(opt->rect);
+ if (subRule.hasBox() || !subRule.hasNativeBorder()) {
+ auto r = subRule.contentsRect(opt->rect);
+ if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(opt)) {
+ // Subtract width needed for arrow, if there is one
+ if (header->sortIndicator != QStyleOptionHeader::None) {
+ const auto arrowRect = subElementRect(SE_HeaderArrow, opt, w);
+ if (arrowRect.isValid()) {
+ if (opt->state & State_Horizontal)
+ r.setWidth(r.width() - arrowRect.width());
+ else
+ r.setHeight(r.height() - arrowRect.height());
+ }
+ }
+ }
+ return r;
+ }
}
break;
@@ -6207,7 +6372,7 @@ QRect QStyleSheetStyle::subElementRect(SubElement se, const QStyleOption *opt, c
#endif // QT_CONFIG(toolbar)
// On mac we make pixel adjustments to layouts which are not
- // desireable when you have custom style sheets on them
+ // desirable when you have custom style sheets on them
case SE_CheckBoxLayoutItem:
case SE_ComboBoxLayoutItem:
case SE_DateTimeEditLayoutItem:
@@ -6241,7 +6406,7 @@ void QStyleSheetStyle::updateStyleSheetFont(QWidget* w) const
{
// Qt's fontDialog relies on the font of the sample edit for its selection,
// we should never override it.
- if (w->objectName() == QLatin1String("qt_fontDialog_sampleEdit"))
+ if (w->objectName() == "qt_fontDialog_sampleEdit"_L1)
return;
QWidget *container = containerWidget(w);
@@ -6339,7 +6504,7 @@ Qt::Alignment QStyleSheetStyle::resolveAlignment(Qt::LayoutDirection layDir, Qt:
// (and hence has the correct object name).
bool QStyleSheetStyle::isNaturalChild(const QObject *obj)
{
- if (obj->objectName().startsWith(QLatin1String("qt_")))
+ if (obj->objectName().startsWith("qt_"_L1))
return true;
return false;
@@ -6347,6 +6512,9 @@ bool QStyleSheetStyle::isNaturalChild(const QObject *obj)
QPixmap QStyleSheetStyle::loadPixmap(const QString &fileName, const QObject *context)
{
+ if (fileName.isEmpty())
+ return {};
+
qreal ratio = -1.0;
if (const QWidget *widget = qobject_cast<const QWidget *>(context)) {
if (QScreen *screen = QApplication::screenAt(widget->mapToGlobal(QPoint(0, 0))))