diff options
Diffstat (limited to 'src/widgets/styles/qstylesheetstyle.cpp')
-rw-r--r-- | src/widgets/styles/qstylesheetstyle.cpp | 307 |
1 files changed, 186 insertions, 121 deletions
diff --git a/src/widgets/styles/qstylesheetstyle.cpp b/src/widgets/styles/qstylesheetstyle.cpp index 6abef62835..655b224617 100644 --- a/src/widgets/styles/qstylesheetstyle.cpp +++ b/src/widgets/styles/qstylesheetstyle.cpp @@ -59,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) @@ -138,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, @@ -436,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 @@ -616,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", @@ -709,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.length(); i++) { - int button = layout[i].toLatin1(); + for (int button : layout) { switch (button) { case 'm': buttons.append(PseudoElement_MdiMinButton); @@ -777,10 +783,9 @@ QHash<QStyle::SubControl, QRect> QStyleSheetStyle::titleBarLayout(const QWidget 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 == ')') { @@ -839,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: { @@ -956,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; @@ -980,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; @@ -1014,8 +1025,8 @@ QRenderRule::QRenderRule(const QList<Declaration> &declarations, const QObject * // intentionally left blank... } else if (decl.d->propertyId == UnknownProperty) { bool knownStyleHint = false; - for (int i = 0; i < numKnownStyleHints; i++) { - QLatin1StringView styleHint(knownStyleHints[i]); + for (const auto sh : knownStyleHints) { + QLatin1StringView styleHint(sh); if (decl.d->property.compare(styleHint) == 0) { QString hintName = QString(styleHint); QVariant hintValue; @@ -1055,9 +1066,9 @@ QRenderRule::QRenderRule(const QList<Declaration> &declarations, const QObject * } } else if (hintName.endsWith("icon"_L1)) { hintValue = decl.iconValue(); - } else if (hintName == "button-layout"_L1 - && decl.d->values.count() != 0 && decl.d->values.at(0).type == Value::String) { - hintValue = subControlLayout(decl.d->values.at(0).variant.toString()); + } 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); @@ -1449,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) { @@ -1470,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); @@ -1482,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 @@ -1596,8 +1625,8 @@ public: 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; @@ -1647,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(); } @@ -1694,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; @@ -1712,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 @@ -1842,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); @@ -2163,8 +2193,8 @@ bool QStyleSheetStyle::hasStyleRule(const QObject *obj, int part) const return result; } - QString pseudoElement = QLatin1StringView(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; @@ -2564,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; } @@ -2635,7 +2666,7 @@ void QStyleSheetStyle::setProperties(QWidget *w) { // scan decls for final occurrence of each "qproperty" QDuplicateTracker<QString> propertySet(decls.size()); - for (int i = decls.count() - 1; i >= 0; --i) { + for (int i = decls.size() - 1; i >= 0; --i) { const QString property = decls.at(i).d->property; if (!property.startsWith("qproperty-"_L1, Qt::CaseInsensitive)) continue; @@ -2644,7 +2675,7 @@ void QStyleSheetStyle::setProperties(QWidget *w) } } - 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-" @@ -2801,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); } @@ -2869,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; } @@ -2896,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); @@ -2913,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 @@ -2986,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); @@ -3019,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); @@ -3041,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 { @@ -3480,12 +3503,12 @@ void QStyleSheetStyle::drawComplexControl(ComplexControl cc, const QStyleOptionC || hasStyleRule(w, PseudoElement_MdiMinButton)) { QList<QVariant> layout = rule.styleHint("button-layout"_L1).toList(); if (layout.isEmpty()) - layout = subControlLayout("mNX"_L1); + 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; @@ -3516,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]; @@ -3526,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); @@ -3537,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); } } @@ -3547,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, @@ -3564,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); } @@ -3595,7 +3618,9 @@ void QStyleSheetStyle::renderMenuItemIcon(const QStyleOptionMenuItem *mi, QPaint ? (mi->state & QStyle::State_Selected ? QIcon::Active : QIcon::Normal) : QIcon::Disabled; const bool checked = mi->checkType != QStyleOptionMenuItem::NotCheckable && mi->checked; - const QPixmap pixmap(mi->icon.pixmap(pixelMetric(PM_SmallIconSize), mode, + 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(); @@ -3730,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; @@ -4032,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, @@ -4093,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) { @@ -4201,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(); @@ -4241,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(); @@ -4349,19 +4383,23 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q vopt->state & QStyle::State_Selected ? QPalette::Highlight : QPalette::Base); - // only draw the indicator; no text or background + // 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, and highlight, but not the indicator with the - // base style. Since we can't turn off HasCheckIndicator to prevent the base + + // 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 checkRect = subElementRect(QStyle::SE_ItemViewItemCheckIndicator, - &optIndicator, w); + 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)) - - checkRect; + - crStyle.united(crBase); p->setClipRegion(clipRegion); } subRule.configurePalette(&optCopy.palette, QPalette::Text, QPalette::NoRole); @@ -4450,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); @@ -4730,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); @@ -4801,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; @@ -4827,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: @@ -5087,7 +5134,7 @@ int QStyleSheetStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const break; case PM_ScrollView_ScrollBarOverlap: - if (!rule.hasNativeBorder() || rule.hasBox()) + if (!proxy()->styleHint(SH_ScrollBar_Transient, opt, w)) return 0; break; #endif // QT_CONFIG(scrollbar) @@ -5454,11 +5501,11 @@ QSize QStyleSheetStyle::sizeFromContents(ContentsType ct, const QStyleOption *op QList<QVariant> layout = rule.styleHint("button-layout"_L1).toList(); if (layout.isEmpty()) - layout = subControlLayout("mNX"_L1); + 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; @@ -5585,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); @@ -5697,7 +5745,7 @@ int QStyleSheetStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWi 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()) + if (!rule.hasNativeBorder() || rule.hasBox() || rule.hasDrawable()) return 0; break; default: break; @@ -6020,12 +6068,12 @@ QRect QStyleSheetStyle::subControlRect(ComplexControl cc, const QStyleOptionComp || hasStyleRule(w, PseudoElement_MdiMinButton)) { QList<QVariant> layout = rule.styleHint("button-layout"_L1).toList(); if (layout.isEmpty()) - layout = subControlLayout("mNX"_L1); + 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; @@ -6181,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; @@ -6450,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)))) |