diff options
Diffstat (limited to 'src/widgets/styles/qfusionstyle.cpp')
-rw-r--r-- | src/widgets/styles/qfusionstyle.cpp | 987 |
1 files changed, 442 insertions, 545 deletions
diff --git a/src/widgets/styles/qfusionstyle.cpp b/src/widgets/styles/qfusionstyle.cpp index 64954dc833..6b8fd979a9 100644 --- a/src/widgets/styles/qfusionstyle.cpp +++ b/src/widgets/styles/qfusionstyle.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 "qfusionstyle_p.h" #include "qfusionstyle_p_p.h" @@ -52,6 +16,7 @@ #include <qabstractbutton.h> #endif #include <qpainter.h> +#include <qpainterpath.h> #include <qdir.h> #include <qstyleoption.h> #include <qapplication.h> @@ -88,9 +53,11 @@ #include <private/qstylehelper_p.h> #include <private/qdrawhelper_p.h> #include <private/qapplication_p.h> +#include <private/qwidget_p.h> QT_BEGIN_NAMESPACE +using namespace Qt::StringLiterals; using namespace QStyleHelper; enum Direction { @@ -102,85 +69,12 @@ enum Direction { // from windows style static const int windowsItemFrame = 2; // menu item frame width -static const int windowsItemHMargin = 3; // menu item hor text margin static const int windowsItemVMargin = 8; // menu item ver text margin -static const int windowsRightBorder = 15; // right border on windows static const int groupBoxBottomMargin = 0; // space below the groupbox static const int groupBoxTopMargin = 3; #if QT_CONFIG(imageformat_xpm) -/* XPM */ -static const char * const dock_widget_close_xpm[] = { - "11 13 7 1", - " c None", - ". c #D5CFCB", - "+ c #8F8B88", - "@ c #6C6A67", - "# c #ABA6A3", - "$ c #B5B0AC", - "% c #A4A09D", - " ", - " +@@@@@@@+ ", - "+# #+", - "@ $@ @$ @", - "@ @@@ @@@ @", - "@ @@@@@ @", - "@ @@@ @", - "@ @@@@@ @", - "@ @@@ @@@ @", - "@ $@ @$ @", - "+% #+", - " +@@@@@@@+ ", - " "}; - -static const char * const dock_widget_restore_xpm[] = { - "11 13 7 1", - " c None", - ". c #D5CFCB", - "+ c #8F8B88", - "@ c #6C6A67", - "# c #ABA6A3", - "$ c #B5B0AC", - "% c #A4A09D", - " ", - " +@@@@@@@+ ", - "+# #+", - "@ #@@@# @", - "@ @ @ @", - "@ #@@@# @ @", - "@ @ @ @ @", - "@ @ @@@ @", - "@ @ @ @", - "@ #@@@# @", - "+% #+", - " +@@@@@@@+ ", - " "}; - -static const char * const workspace_minimize[] = { - "11 13 7 1", - " c None", - ". c #D5CFCB", - "+ c #8F8B88", - "@ c #6C6A67", - "# c #ABA6A3", - "$ c #B5B0AC", - "% c #A4A09D", - " ", - " +@@@@@@@+ ", - "+# #+", - "@ @", - "@ @", - "@ @", - "@ @@@@@@@ @", - "@ @@@@@@@ @", - "@ @", - "@ @", - "+% #+", - " +@@@@@@@+ ", - " "}; - - static const char * const qt_titlebar_context_help[] = { "10 10 3 1", " c None", @@ -250,20 +144,22 @@ static void qt_fusion_draw_arrow(Qt::ArrowType type, QPainter *painter, const QS if (rect.isEmpty()) return; - const int arrowWidth = QStyleHelper::dpiScaled(14); - const int arrowHeight = QStyleHelper::dpiScaled(8); + const qreal dpi = QStyleHelper::dpi(option); + const qreal dpr = painter->device()->devicePixelRatio(); + const int arrowWidth = int(QStyleHelper::dpiScaled(14, dpi)); + const int arrowHeight = int(QStyleHelper::dpiScaled(8, dpi)); const int arrowMax = qMin(arrowHeight, arrowWidth); const int rectMax = qMin(rect.height(), rect.width()); const int size = qMin(arrowMax, rectMax); QPixmap cachePixmap; - QString cacheKey = QStyleHelper::uniqueName(QLatin1String("fusion-arrow"), option, rect.size()) - % HexString<uint>(type) - % HexString<uint>(color.rgba()); - if (!QPixmapCache::find(cacheKey, cachePixmap)) { - cachePixmap = styleCachePixmap(rect.size()); - cachePixmap.fill(Qt::transparent); + const QString cacheKey = QStyleHelper::uniqueName("fusion-arrow"_L1 + % HexString<uint>(type) + % HexString<uint>(color.rgba()), + option, rect.size(), dpr); + if (!QPixmapCache::find(cacheKey, &cachePixmap)) { + cachePixmap = styleCachePixmap(rect.size(), dpr); QPainter cachePainter(&cachePixmap); QRectF arrowRect; @@ -274,27 +170,26 @@ static void qt_fusion_draw_arrow(Qt::ArrowType type, QPainter *painter, const QS arrowRect.moveTo((rect.width() - arrowRect.width()) / 2.0, (rect.height() - arrowRect.height()) / 2.0); - QPolygonF triangle; - triangle.reserve(3); + std::array<QPointF, 3> triangle; switch (type) { case Qt::DownArrow: - triangle << arrowRect.topLeft() << arrowRect.topRight() << QPointF(arrowRect.center().x(), arrowRect.bottom()); + triangle = {arrowRect.topLeft(), arrowRect.topRight(), QPointF(arrowRect.center().x(), arrowRect.bottom())}; break; case Qt::RightArrow: - triangle << arrowRect.topLeft() << arrowRect.bottomLeft() << QPointF(arrowRect.right(), arrowRect.center().y()); + triangle = {arrowRect.topLeft(), arrowRect.bottomLeft(), QPointF(arrowRect.right(), arrowRect.center().y())}; break; case Qt::LeftArrow: - triangle << arrowRect.topRight() << arrowRect.bottomRight() << QPointF(arrowRect.left(), arrowRect.center().y()); + triangle = {arrowRect.topRight(), arrowRect.bottomRight(), QPointF(arrowRect.left(), arrowRect.center().y())}; break; default: - triangle << arrowRect.bottomLeft() << arrowRect.bottomRight() << QPointF(arrowRect.center().x(), arrowRect.top()); + triangle = {arrowRect.bottomLeft(), arrowRect.bottomRight(), QPointF(arrowRect.center().x(), arrowRect.top())}; break; } cachePainter.setPen(Qt::NoPen); cachePainter.setBrush(color); cachePainter.setRenderHint(QPainter::Antialiasing); - cachePainter.drawPolygon(triangle); + cachePainter.drawPolygon(triangle.data(), int(triangle.size())); QPixmapCache::insert(cacheKey, cachePixmap); } @@ -389,7 +284,7 @@ QFusionStylePrivate::QFusionStylePrivate() */ QFusionStyle::QFusionStyle() : QCommonStyle(*new QFusionStylePrivate) { - setObjectName(QLatin1String("Fusion")); + setObjectName("Fusion"_L1); } /*! @@ -409,37 +304,18 @@ QFusionStyle::~QFusionStyle() } /*! - \fn void QFusionStyle::drawItemText(QPainter *painter, const QRect &rectangle, int alignment, const QPalette &palette, - bool enabled, const QString& text, QPalette::ColorRole textRole) const - - Draws the given \a text in the specified \a rectangle using the - provided \a painter and \a palette. - - Text is drawn using the painter's pen. If an explicit \a textRole - is specified, then the text is drawn using the \a palette's color - for the specified role. The \a enabled value indicates whether or - not the item is enabled; when reimplementing, this value should - influence how the item is drawn. - - The text is aligned and wrapped according to the specified \a - alignment. - - \sa Qt::Alignment + \reimp */ void QFusionStyle::drawItemText(QPainter *painter, const QRect &rect, int alignment, const QPalette &pal, bool enabled, const QString& text, QPalette::ColorRole textRole) const { + Q_UNUSED(enabled); if (text.isEmpty()) return; QPen savedPen = painter->pen(); - if (textRole != QPalette::NoRole) { + if (textRole != QPalette::NoRole) painter->setPen(QPen(pal.brush(textRole), savedPen.widthF())); - } - if (!enabled) { - QPen pen = painter->pen(); - painter->setPen(pen); - } painter->drawText(rect, alignment, text); painter->setPen(savedPen); } @@ -458,22 +334,22 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem, QRect rect = option->rect; int state = option->state; - QColor outline = d->outline(option->palette); - QColor highlightedOutline = d->highlightedOutline(option->palette); + const QColor outline = d->outline(option->palette); + const QColor highlightedOutline = d->highlightedOutline(option->palette); - QColor tabFrameColor = d->tabFrameColor(option->palette); + const QColor tabFrameColor = d->tabFrameColor(option->palette); switch (elem) { +#if QT_CONFIG(groupbox) // No frame drawn case PE_FrameGroupBox: { - QPixmap pixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/fusion_groupbox.png")); - int topMargin = qMax(pixelMetric(PM_ExclusiveIndicatorHeight), option->fontMetrics.height()) + groupBoxTopMargin; - QRect frame = option->rect.adjusted(0, topMargin, 0, 0); - qDrawBorderPixmap(painter, frame, QMargins(6, 6, 6, 6), pixmap); + QPixmap pixmap(":/qt-project.org/styles/commonstyle/images/fusion_groupbox.png"_L1); + qDrawBorderPixmap(painter, option->rect, QMargins(6, 6, 6, 6), pixmap); break; } +#endif // QT_CONFIG(groupbox) case PE_IndicatorBranch: { if (!(option->state & State_Children)) break; @@ -539,7 +415,7 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem, { if (option->rect.width() <= 1 || option->rect.height() <= 1) break; - QColor arrowColor = option->palette.foreground().color(); + QColor arrowColor = option->palette.windowText().color(); arrowColor.setAlpha(160); Qt::ArrowType arrow = Qt::UpArrow; switch (elem) { @@ -558,7 +434,7 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem, qt_fusion_draw_arrow(arrow, painter, option, option->rect, arrowColor); } break; - case PE_IndicatorViewItemCheck: + case PE_IndicatorItemViewItemCheck: { QStyleOptionButton button; button.QStyleOption::operator=(*option); @@ -569,7 +445,7 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem, case PE_IndicatorHeaderArrow: if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) { QRect r = header->rect; - QColor arrowColor = header->palette.foreground().color(); + QColor arrowColor = header->palette.windowText().color(); arrowColor.setAlpha(180); QPoint offset = QPoint(0, -2); @@ -598,24 +474,24 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem, const int margin = 6; if (option->state & State_Horizontal) { const int offset = rect.width()/2; - painter->setPen(QPen(option->palette.background().color().darker(110))); + painter->setPen(QPen(option->palette.window().color().darker(110))); painter->drawLine(rect.bottomLeft().x() + offset, rect.bottomLeft().y() - margin, rect.topLeft().x() + offset, rect.topLeft().y() + margin); - painter->setPen(QPen(option->palette.background().color().lighter(110))); + painter->setPen(QPen(option->palette.window().color().lighter(110))); painter->drawLine(rect.bottomLeft().x() + offset + 1, rect.bottomLeft().y() - margin, rect.topLeft().x() + offset + 1, rect.topLeft().y() + margin); } else { //Draw vertical separator const int offset = rect.height()/2; - painter->setPen(QPen(option->palette.background().color().darker(110))); + painter->setPen(QPen(option->palette.window().color().darker(110))); painter->drawLine(rect.topLeft().x() + margin , rect.topLeft().y() + offset, rect.topRight().x() - margin, rect.topRight().y() + offset); - painter->setPen(QPen(option->palette.background().color().lighter(110))); + painter->setPen(QPen(option->palette.window().color().lighter(110))); painter->drawLine(rect.topLeft().x() + margin , rect.topLeft().y() + offset + 1, rect.topRight().x() - margin, @@ -642,8 +518,8 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem, { painter->setPen(QPen(outline)); painter->drawRect(option->rect.adjusted(0, 0, -1, -1)); - QColor frameLight = option->palette.background().color().lighter(160); - QColor frameShadow = option->palette.background().color().darker(110); + QColor frameLight = option->palette.window().color().lighter(160); + QColor frameShadow = option->palette.window().color().darker(110); //paint beveleffect QRect frame = option->rect.adjusted(1, 1, -1, -1); @@ -661,14 +537,14 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem, painter->save(); { - QColor softshadow = option->palette.background().color().darker(120); + QColor softshadow = option->palette.window().color().darker(120); QRect rect= option->rect; painter->setPen(softshadow); painter->drawRect(option->rect.adjusted(0, 0, -1, -1)); painter->setPen(QPen(option->palette.light(), 1)); painter->drawLine(QPoint(rect.left() + 1, rect.top() + 1), QPoint(rect.left() + 1, rect.bottom() - 1)); - painter->setPen(QPen(option->palette.background().color().darker(120))); + painter->setPen(QPen(option->palette.window().color().darker(120))); painter->drawLine(QPoint(rect.left() + 1, rect.bottom() - 1), QPoint(rect.right() - 2, rect.bottom() - 1)); painter->drawLine(QPoint(rect.right() - 1, rect.top() + 1), QPoint(rect.right() - 1, rect.bottom() - 1)); @@ -704,7 +580,7 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem, painter->setPen(QPen(option->palette.light(), 1)); painter->drawLine(QPoint(rect.left() + 1, rect.top() + 1), QPoint(rect.left() + 1, rect.bottom() - 1)); - painter->setPen(QPen(option->palette.background().color().darker(120))); + painter->setPen(QPen(option->palette.window().color().darker(120))); painter->drawLine(QPoint(rect.left() + 1, rect.bottom() - 1), QPoint(rect.right() - 2, rect.bottom() - 1)); painter->drawLine(QPoint(rect.right() - 1, rect.top() + 1), @@ -748,7 +624,7 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem, painter->translate(0.5, 0.5); rect = rect.adjusted(0, 0, -1, -1); - QColor pressedColor = mergedColors(option->palette.base().color(), option->palette.foreground().color(), 85); + QColor pressedColor = mergedColors(option->palette.base().color(), option->palette.windowText().color(), 85); painter->setBrush(Qt::NoBrush); // Gradient fill @@ -779,12 +655,13 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem, painter->drawRect(rect.adjusted(checkMarkPadding, checkMarkPadding, -checkMarkPadding, -checkMarkPadding)); } else if (checkbox->state & State_On) { - qreal penWidth = QStyleHelper::dpiScaled(1.5); + const qreal dpi = QStyleHelper::dpi(option); + qreal penWidth = QStyleHelper::dpiScaled(1.5, dpi); penWidth = qMax<qreal>(penWidth, 0.13 * rect.height()); penWidth = qMin<qreal>(penWidth, 0.20 * rect.height()); QPen checkPen = QPen(checkMarkColor, penWidth); checkMarkColor.setAlpha(210); - painter->translate(dpiScaled(-0.8), dpiScaled(0.5)); + painter->translate(dpiScaled(-0.8, dpi), dpiScaled(0.5, dpi)); painter->setPen(checkPen); painter->setBrush(Qt::NoBrush); @@ -802,14 +679,14 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem, case PE_IndicatorRadioButton: painter->save(); { - QColor pressedColor = mergedColors(option->palette.base().color(), option->palette.foreground().color(), 85); + QColor pressedColor = mergedColors(option->palette.base().color(), option->palette.windowText().color(), 85); painter->setBrush((state & State_Sunken) ? pressedColor : option->palette.base().color()); painter->setRenderHint(QPainter::Antialiasing, true); QPainterPath circle; const QPointF circleCenter = rect.center() + QPoint(1, 1); const qreal outlineRadius = (rect.width() + (rect.width() + 1) % 2) / 2.0 - 1; circle.addEllipse(circleCenter, outlineRadius, outlineRadius); - painter->setPen(QPen(option->palette.background().color().darker(150))); + painter->setPen(QPen(option->palette.window().color().darker(150))); if (option->state & State_HasFocus && option->state & State_KeyboardFocusChange) painter->setPen(QPen(highlightedOutline)); painter->drawPath(circle); @@ -923,7 +800,7 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem, if (isDefault) buttonColor = mergedColors(buttonColor, highlightedOutline.lighter(130), 90); - BEGIN_STYLE_PIXMAPCACHE(QStringLiteral("pushbutton-") + buttonColor.name(QColor::HexArgb)) + BEGIN_STYLE_PIXMAPCACHE(u"pushbutton-" + buttonColor.name(QColor::HexArgb)) r = rect.adjusted(0, 1, -1, 0); p->setRenderHint(QPainter::Antialiasing, true); @@ -977,21 +854,10 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem, case PE_FrameStatusBarItem: break; - case PE_IndicatorTabClose: - { - Q_D(const QFusionStyle); - if (d->tabBarcloseButtonIcon.isNull()) - d->tabBarcloseButtonIcon = proxy()->standardIcon(SP_DialogCloseButton, option, widget); - if ((option->state & State_Enabled) && (option->state & State_MouseOver)) - proxy()->drawPrimitive(PE_PanelButtonCommand, option, painter, widget); - QPixmap pixmap = d->tabBarcloseButtonIcon.pixmap(QSize(16, 16), QIcon::Normal, QIcon::On); - proxy()->drawItemPixmap(painter, option->rect, Qt::AlignCenter, pixmap); - } - break; case PE_PanelMenu: { painter->save(); const QBrush menuBackground = option->palette.base().color().lighter(108); - QColor borderColor = option->palette.background().color().darker(160); + QColor borderColor = option->palette.window().color().darker(160); qDrawPlainRect(painter, option->rect, borderColor, 1, &menuBackground); painter->restore(); } @@ -1024,7 +890,7 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio if (!cb->currentIcon.isNull()) { QIcon::Mode mode = cb->state & State_Enabled ? QIcon::Normal : QIcon::Disabled; - QPixmap pixmap = cb->currentIcon.pixmap(cb->iconSize, mode); + QPixmap pixmap = cb->currentIcon.pixmap(cb->iconSize, painter->device()->devicePixelRatio(), mode); QRect iconRect(editRect); iconRect.setWidth(cb->iconSize.width() + 4); iconRect = alignedRect(cb->direction, @@ -1041,7 +907,7 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio } if (!cb->currentText.isEmpty() && !cb->editable) { proxy()->drawItemText(painter, editRect.adjusted(1, 0, -1, 0), - visualAlignment(cb->direction, Qt::AlignLeft | Qt::AlignVCenter), + visualAlignment(cb->direction, cb->textAlignment), cb->palette, cb->state & State_Enabled, cb->currentText, cb->editable ? QPalette::Text : QPalette::ButtonText); } @@ -1078,7 +944,7 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio QColor dimHighlight(qMin(highlight.red()/2 + 110, 255), qMin(highlight.green()/2 + 110, 255), qMin(highlight.blue()/2 + 110, 255)); - dimHighlight.setAlpha(widget && widget->isTopLevel() ? 255 : 80); + dimHighlight.setAlpha(widget && widget->isWindow() ? 255 : 80); QLinearGradient gradient(rect.topLeft(), QPoint(rect.bottomLeft().x(), rect.bottomLeft().y())); gradient.setColorAt(0, dimHighlight.lighter(120)); gradient.setColorAt(1, dimHighlight); @@ -1086,10 +952,13 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio painter->translate(0.5, 0.5); painter->setBrush(dimHighlight); painter->drawRoundedRect(option->rect.adjusted(0, 0, -1, -1), 1, 1); - QColor innerLine = Qt::white; - innerLine.setAlpha(40); - painter->setPen(innerLine); - painter->drawRoundedRect(option->rect.adjusted(1, 1, -2, -2), 1, 1); + //when the rectangle we get is large enough, draw the inner rectangle. + if (option->rect.width() > 2 && option->rect.height() > 2) { + QColor innerLine = Qt::white; + innerLine.setAlpha(40); + painter->setPen(innerLine); + painter->drawRoundedRect(option->rect.adjusted(1, 1, -2, -2), 1, 1); + } painter->restore(); } break; @@ -1256,7 +1125,7 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio Qt::ElideRight, titleRect.width()); proxy()->drawItemText(painter, titleRect, - Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic, dwOpt->palette, + Qt::AlignLeft | Qt::AlignVCenter | Qt::TextHideMnemonic, dwOpt->palette, dwOpt->state & State_Enabled, titleText, QPalette::WindowText); } @@ -1267,24 +1136,30 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio painter->save(); // Draws the header in tables. if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) { - QString pixmapName = QStyleHelper::uniqueName(QLatin1String("headersection"), option, option->rect.size()); - pixmapName += QString::number(- int(header->position)); - pixmapName += QString::number(- int(header->orientation)); - + const QStyleOptionHeaderV2 *headerV2 = qstyleoption_cast<const QStyleOptionHeaderV2 *>(option); + const bool isSectionDragTarget = headerV2 ? headerV2->isSectionDragTarget : false; + const qreal dpr = painter->device()->devicePixelRatio(); + const QString pixmapName = QStyleHelper::uniqueName("headersection-"_L1 + % HexString(header->position) + % HexString(header->orientation) + % QLatin1Char(isSectionDragTarget ? '1' : '0'), + option, option->rect.size(), dpr); QPixmap cache; - if (!QPixmapCache::find(pixmapName, cache)) { - cache = styleCachePixmap(rect.size()); - cache.fill(Qt::transparent); + if (!QPixmapCache::find(pixmapName, &cache)) { + cache = styleCachePixmap(rect.size(), dpr); QRect pixmapRect(0, 0, rect.width(), rect.height()); QPainter cachePainter(&cache); QColor buttonColor = d->buttonColor(option->palette); - QColor gradientStopColor; QColor gradientStartColor = buttonColor.lighter(104); - gradientStopColor = buttonColor.darker(102); + QColor gradientStopColor = buttonColor.darker(102); + if (isSectionDragTarget) { + gradientStopColor = gradientStartColor.darker(130); + gradientStartColor = gradientStartColor.darker(130); + } QLinearGradient gradient(pixmapRect.topLeft(), pixmapRect.bottomLeft()); - if (option->palette.background().gradient()) { - gradient.setStops(option->palette.background().gradient()->stops()); + if (option->palette.window().gradient()) { + gradient.setStops(option->palette.window().gradient()->stops()); } else { QColor midColor1 = mergedColors(gradientStartColor, gradientStopColor, 60); QColor midColor2 = mergedColors(gradientStartColor, gradientStopColor, 40); @@ -1344,37 +1219,39 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio case CE_ProgressBarContents: painter->save(); painter->setRenderHint(QPainter::Antialiasing, true); - painter->translate(0.5, 0.5); if (const QStyleOptionProgressBar *bar = qstyleoption_cast<const QStyleOptionProgressBar *>(option)) { - bool vertical = false; - bool inverted = false; - bool indeterminate = (bar->minimum == 0 && bar->maximum == 0); - bool complete = bar->progress == bar->maximum; - - // Get extra style options if version 2 - vertical = (bar->orientation == Qt::Vertical); - inverted = bar->invertedAppearance; + const auto indeterminate = (bar->minimum == 0 && bar->maximum == 0); + const auto complete = bar->progress == bar->maximum; + const auto vertical = !(bar->state & QStyle::State_Horizontal); + const auto inverted = bar->invertedAppearance; + const auto reverse = (bar->direction == Qt::RightToLeft) ^ inverted; // If the orientation is vertical, we use a transform to rotate - // the progress bar 90 degrees clockwise. This way we can use the + // the progress bar 90 degrees (counter)clockwise. This way we can use the // same rendering code for both orientations. if (vertical) { rect = QRect(rect.left(), rect.top(), rect.height(), rect.width()); // flip width and height - QTransform m = QTransform::fromTranslate(rect.height()-1, -1.0); - m.rotate(90.0); + QTransform m; + if (inverted) { + m.rotate(90); + m.translate(0, -rect.height()); + } else { + m.rotate(-90); + m.translate(-rect.width(), 0); + } + painter->setTransform(m, true); + } else if (reverse) { + QTransform m = QTransform::fromScale(-1, 1); + m.translate(-rect.width(), 0); painter->setTransform(m, true); } + painter->translate(0.5, 0.5); - int maxWidth = rect.width(); const auto progress = qMax(bar->progress, bar->minimum); // workaround for bug in QProgressBar const auto totalSteps = qMax(Q_INT64_C(1), qint64(bar->maximum) - bar->minimum); const auto progressSteps = qint64(progress) - bar->minimum; - const auto progressBarWidth = progressSteps * maxWidth / totalSteps; - int width = indeterminate ? maxWidth : progressBarWidth; - - bool reverse = (!vertical && (bar->direction == Qt::RightToLeft)) || vertical; - if (inverted) - reverse = !reverse; + const auto progressBarWidth = progressSteps * rect.width() / totalSteps; + int width = indeterminate ? rect.width() : progressBarWidth; int step = 0; QRect progressBar; @@ -1383,28 +1260,10 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio if (qGray(outline.rgb()) > qGray(highlightedoutline.rgb())) outline = highlightedoutline; - if (!indeterminate) { - QColor innerShadow(Qt::black); - innerShadow.setAlpha(35); - painter->setPen(innerShadow); - if (!reverse) { - progressBar.setRect(rect.left(), rect.top(), width - 1, rect.height() - 1); - if (!complete) { - painter->drawLine(progressBar.topRight() + QPoint(2, 1), progressBar.bottomRight() + QPoint(2, 0)); - painter->setPen(QPen(highlight.darker(140))); - painter->drawLine(progressBar.topRight() + QPoint(1, 1), progressBar.bottomRight() + QPoint(1, 0)); - } - } else { - progressBar.setRect(rect.right() - width - 1, rect.top(), width + 2, rect.height() - 1); - if (!complete) { - painter->drawLine(progressBar.topLeft() + QPoint(-2, 1), progressBar.bottomLeft() + QPoint(-2, 0)); - painter->setPen(QPen(highlight.darker(140))); - painter->drawLine(progressBar.topLeft() + QPoint(-1, 1), progressBar.bottomLeft() + QPoint(-1, 0)); - } - } - } else { + if (!indeterminate) + progressBar.setRect(rect.left(), rect.top(), width - 1, rect.height() - 1); + else progressBar.setRect(rect.left(), rect.top(), rect.width() - 1, rect.height() - 1); - } if (indeterminate || bar->progress > bar->minimum) { @@ -1419,10 +1278,13 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio painter->setBrush(gradient); painter->save(); + // 0.5 - half the width of a cosmetic pen (for vertical line below) if (!complete && !indeterminate) - painter->setClipRect(progressBar.adjusted(-1, -1, -1, 1)); - QRect fillRect = progressBar.adjusted( !indeterminate && !complete && reverse ? -2 : 0, 0, - indeterminate || complete || reverse ? 0 : 2, 0); + painter->setClipRect(QRectF(progressBar).adjusted(-1, -1, 0.5, 1)); + + QRect fillRect = progressBar; + if (!indeterminate && !complete) + fillRect.setWidth(std::min(fillRect.width() + 2, rect.width() - 1)); // avoid round borders at the right end painter->drawRoundedRect(fillRect, 2, 2); painter->restore(); @@ -1449,43 +1311,63 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio x + rect.height() + step, progressBar.top() - 2); } } + if (!indeterminate && !complete) { + QColor innerShadow(Qt::black); + innerShadow.setAlpha(35); + painter->setPen(innerShadow); + painter->drawLine(progressBar.topRight() + QPoint(2, 1), progressBar.bottomRight() + QPoint(2, 0)); + painter->setPen(QPen(highlight.darker(140))); + painter->drawLine(progressBar.topRight() + QPoint(1, 1), progressBar.bottomRight() + QPoint(1, 0)); + } } painter->restore(); break; case CE_ProgressBarLabel: if (const QStyleOptionProgressBar *bar = qstyleoption_cast<const QStyleOptionProgressBar *>(option)) { - QRect leftRect; QRect rect = bar->rect; + QRect leftRect = rect; + QRect rightRect = rect; QColor textColor = option->palette.text().color(); QColor alternateTextColor = d->highlightedText(option->palette); painter->save(); - bool vertical = false, inverted = false; - vertical = (bar->orientation == Qt::Vertical); - inverted = bar->invertedAppearance; - if (vertical) - rect = QRect(rect.left(), rect.top(), rect.height(), rect.width()); // flip width and height + const auto vertical = !(bar->state & QStyle::State_Horizontal); + const auto inverted = bar->invertedAppearance; + const auto reverse = (bar->direction == Qt::RightToLeft) ^ inverted; const auto totalSteps = qMax(Q_INT64_C(1), qint64(bar->maximum) - bar->minimum); const auto progressSteps = qint64(bar->progress) - bar->minimum; - const auto progressIndicatorPos = progressSteps * rect.width() / totalSteps; - if (progressIndicatorPos >= 0 && progressIndicatorPos <= rect.width()) - leftRect = QRect(rect.left(), rect.top(), progressIndicatorPos, rect.height()); - if (vertical) - leftRect.translate(rect.width() - progressIndicatorPos, 0); - - bool flip = (!vertical && (((bar->direction == Qt::RightToLeft) && !inverted) || - ((bar->direction == Qt::LeftToRight) && inverted))); - - QRegion rightRect = rect; - rightRect = rightRect.subtracted(leftRect); - painter->setClipRegion(rightRect); - painter->setPen(flip ? alternateTextColor : textColor); - painter->drawText(rect, bar->text, QTextOption(Qt::AlignAbsolute | Qt::AlignHCenter | Qt::AlignVCenter)); - if (!leftRect.isNull()) { - painter->setPen(flip ? textColor : alternateTextColor); - painter->setClipRect(leftRect); - painter->drawText(rect, bar->text, QTextOption(Qt::AlignAbsolute | Qt::AlignHCenter | Qt::AlignVCenter)); + const auto progressIndicatorPos = progressSteps * (vertical ? rect.height() : rect.width()) / totalSteps; + + if (vertical) { + if (progressIndicatorPos >= 0 && progressIndicatorPos <= rect.height()) { + if (inverted) { + leftRect.setHeight(progressIndicatorPos); + rightRect.setY(progressIndicatorPos); + } else { + leftRect.setHeight(rect.height() - progressIndicatorPos); + rightRect.setY(rect.height() - progressIndicatorPos); + } + } + } else { + if (progressIndicatorPos >= 0 && progressIndicatorPos <= rect.width()) { + if (reverse) { + leftRect.setWidth(rect.width() - progressIndicatorPos); + rightRect.setX(rect.width() - progressIndicatorPos); + } else { + leftRect.setWidth(progressIndicatorPos); + rightRect.setX(progressIndicatorPos); + } + } } + + const auto firstIsAlternateColor = (vertical && !inverted) || (!vertical && reverse); + painter->setClipRect(rightRect); + painter->setPen(firstIsAlternateColor ? alternateTextColor : textColor); + painter->drawText(rect, bar->text, QTextOption(Qt::AlignAbsolute | Qt::AlignHCenter | Qt::AlignVCenter)); + painter->setPen(firstIsAlternateColor ? textColor : alternateTextColor); + painter->setClipRect(leftRect); + painter->drawText(rect, bar->text, QTextOption(Qt::AlignAbsolute | Qt::AlignHCenter | Qt::AlignVCenter)); + painter->restore(); } break; @@ -1514,12 +1396,12 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio //draw text QPalette::ColorRole textRole = dis ? QPalette::Text : QPalette::HighlightedText; uint alignment = Qt::AlignCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine; - if (!styleHint(SH_UnderlineShortcut, mbi, widget)) + if (!proxy()->styleHint(SH_UnderlineShortcut, mbi, widget)) alignment |= Qt::TextHideMnemonic; proxy()->drawItemText(painter, item.rect, alignment, mbi->palette, mbi->state & State_Enabled, mbi->text, textRole); } else { - QColor shadow = mergedColors(option->palette.background().color().darker(120), + QColor shadow = mergedColors(option->palette.window().color().darker(120), outline.lighter(140), 60); painter->setPen(QPen(shadow)); painter->drawLine(option->rect.bottomLeft(), option->rect.bottomRight()); @@ -1535,37 +1417,40 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio QColor highlight = option->palette.highlight().color(); if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) { int w = 0; - const int margin = QStyleHelper::dpiScaled(5); + const int margin = int(QStyleHelper::dpiScaled(5, option)); if (!menuItem->text.isEmpty()) { painter->setFont(menuItem->font); - proxy()->drawItemText(painter, menuItem->rect.adjusted(margin, 0, -margin, 0), Qt::AlignLeft | Qt::AlignVCenter, + proxy()->drawItemText(painter, menuItem->rect.adjusted(margin, 0, -margin, 0), + Qt::AlignLeft | Qt::AlignVCenter, menuItem->palette, menuItem->state & State_Enabled, menuItem->text, QPalette::Text); w = menuItem->fontMetrics.horizontalAdvance(menuItem->text) + margin; } painter->setPen(shadow.lighter(106)); - bool reverse = menuItem->direction == Qt::RightToLeft; - painter->drawLine(menuItem->rect.left() + margin + (reverse ? 0 : w), menuItem->rect.center().y(), - menuItem->rect.right() - margin - (reverse ? w : 0), menuItem->rect.center().y()); + const bool reverse = menuItem->direction == Qt::RightToLeft; + qreal y = menuItem->rect.center().y() + 0.5f; + painter->drawLine(QPointF(menuItem->rect.left() + margin + (reverse ? 0 : w), y), + QPointF(menuItem->rect.right() - margin - (reverse ? w : 0), y)); painter->restore(); break; } - bool selected = menuItem->state & State_Selected && menuItem->state & State_Enabled; + const bool selected = menuItem->state & State_Selected && menuItem->state & State_Enabled; if (selected) { QRect r = option->rect; painter->fillRect(r, highlight); painter->setPen(QPen(highlightOutline)); painter->drawRect(QRectF(r).adjusted(0.5, 0.5, -0.5, -0.5)); } - bool checkable = menuItem->checkType != QStyleOptionMenuItem::NotCheckable; - bool checked = menuItem->checked; - bool sunken = menuItem->state & State_Sunken; - bool enabled = menuItem->state & State_Enabled; + const bool checkable = menuItem->checkType != QStyleOptionMenuItem::NotCheckable; + const bool checked = menuItem->checked; + const bool sunken = menuItem->state & State_Sunken; + const bool enabled = menuItem->state & State_Enabled; - bool ignoreCheckMark = false; - const int checkColHOffset = windowsItemHMargin + windowsItemFrame - 1; + const int checkColHOffset = QFusionStylePrivate::menuItemHMargin + windowsItemFrame - 1; + // icon checkbox's highlight column width int checkcol = qMax<int>(menuItem->rect.height() * 0.79, - qMax<int>(menuItem->maxIconWidth, dpiScaled(21))); // icon checkbox's highlight column width + qMax<int>(menuItem->maxIconWidth, dpiScaled(21, option))); + bool ignoreCheckMark = false; if ( #if QT_CONFIG(combobox) qobject_cast<const QComboBox*>(widget) || @@ -1573,23 +1458,26 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio (option->styleObject && option->styleObject->property("_q_isComboBoxPopupItem").toBool())) ignoreCheckMark = true; //ignore the checkmarks provided by the QComboMenuDelegate - if (!ignoreCheckMark) { + if (!ignoreCheckMark || menuItem->state & (State_On | State_Off)) { // Check, using qreal and QRectF to avoid error accumulation - const qreal boxMargin = dpiScaled(3.5); + const qreal boxMargin = dpiScaled(3.5, option); const qreal boxWidth = checkcol - 2 * boxMargin; - QRectF checkRectF(option->rect.left() + boxMargin + checkColHOffset, option->rect.center().y() - boxWidth/2 + 1, boxWidth, boxWidth); - QRect checkRect = checkRectF.toRect(); + QRect checkRect = QRectF(option->rect.left() + boxMargin + checkColHOffset, + option->rect.center().y() - boxWidth/2 + 1, boxWidth, + boxWidth).toRect(); checkRect.setWidth(checkRect.height()); // avoid .toRect() round error results in non-perfect square checkRect = visualRect(menuItem->direction, menuItem->rect, checkRect); if (checkable) { if (menuItem->checkType & QStyleOptionMenuItem::Exclusive) { // Radio button - if (checked || sunken) { + if (menuItem->state & State_On || checked || sunken) { painter->setRenderHint(QPainter::Antialiasing); painter->setPen(Qt::NoPen); - QPalette::ColorRole textRole = !enabled ? QPalette::Text: - selected ? QPalette::HighlightedText : QPalette::ButtonText; + QPalette::ColorRole textRole = !enabled + ? QPalette::Text : + selected ? QPalette::HighlightedText + : QPalette::ButtonText; painter->setBrush(option->palette.brush( option->palette.currentColorGroup(), textRole)); const int adjustment = checkRect.height() * 0.3; painter->drawEllipse(checkRect.adjusted(adjustment, adjustment, -adjustment, -adjustment)); @@ -1600,8 +1488,10 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio QStyleOptionButton box; box.QStyleOption::operator=(*option); box.rect = checkRect; - if (checked) + if (checked || menuItem->state & State_On) box.state |= State_On; + else + box.state |= State_Off; proxy()->drawPrimitive(PE_IndicatorCheckBox, &box, painter, widget); } } @@ -1614,8 +1504,8 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio } // Text and icon, ripped from windows style - bool dis = !(menuItem->state & State_Enabled); - bool act = menuItem->state & State_Selected; + const bool dis = !(menuItem->state & State_Enabled); + const bool act = menuItem->state & State_Selected; const QStyleOption *opt = option; const QStyleOptionMenuItem *menuitem = menuItem; @@ -1636,20 +1526,17 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio iconSize = combo->iconSize(); #endif if (checked) - pixmap = menuItem->icon.pixmap(iconSize, mode, QIcon::On); + pixmap = menuItem->icon.pixmap(iconSize, painter->device()->devicePixelRatio(), mode, QIcon::On); else - pixmap = menuItem->icon.pixmap(iconSize, mode); - - const int pixw = pixmap.width() / pixmap.devicePixelRatio(); - const int pixh = pixmap.height() / pixmap.devicePixelRatio(); + pixmap = menuItem->icon.pixmap(iconSize, painter->device()->devicePixelRatio(), mode); - QRect pmr(0, 0, pixw, pixh); + QRect pmr(QPoint(0, 0), pixmap.deviceIndependentSize().toSize()); pmr.moveCenter(vCheckRect.center()); painter->setPen(menuItem->palette.text().color()); if (!ignoreCheckMark && checkable && checked) { QStyleOption opt = *option; if (act) { - QColor activeColor = mergedColors(option->palette.background().color(), + QColor activeColor = mergedColors(option->palette.window().color(), option->palette.highlight().color()); opt.palette.setBrush(QPalette::Button, activeColor); } @@ -1666,36 +1553,38 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio } int x, y, w, h; menuitem->rect.getRect(&x, &y, &w, &h); - int tab = menuitem->tabWidth; QColor discol; if (dis) { discol = menuitem->palette.text().color(); p->setPen(discol); } - int xm = checkColHOffset + checkcol + windowsItemHMargin; - int xpos = menuitem->rect.x() + xm; + const int xm = checkColHOffset + checkcol + QFusionStylePrivate::menuItemHMargin; + const int xpos = menuitem->rect.x() + xm; - QRect textRect(xpos, y + windowsItemVMargin, w - xm - windowsRightBorder - tab + 1, h - 2 * windowsItemVMargin); - QRect vTextRect = visualRect(opt->direction, menuitem->rect, textRect); - QStringRef s(&menuitem->text); + const QRect textRect(xpos, y + windowsItemVMargin, + w - xm - QFusionStylePrivate::menuRightBorder - menuitem->reservedShortcutWidth + 2, + h - 2 * windowsItemVMargin); + const QRect vTextRect = visualRect(opt->direction, menuitem->rect, textRect); + QStringView s(menuitem->text); if (!s.isEmpty()) { // draw text p->save(); - int t = s.indexOf(QLatin1Char('\t')); + const qsizetype tabIndex = s.indexOf(u'\t'); int text_flags = Qt::AlignVCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine; - if (!styleHint(SH_UnderlineShortcut, menuitem, widget)) + if (!proxy()->styleHint(SH_UnderlineShortcut, menuitem, widget)) text_flags |= Qt::TextHideMnemonic; text_flags |= Qt::AlignLeft; - if (t >= 0) { + if (tabIndex >= 0) { QRect vShortcutRect = visualRect(opt->direction, menuitem->rect, - QRect(textRect.topRight(), QPoint(menuitem->rect.right(), textRect.bottom()))); - const QString textToDraw = s.mid(t + 1).toString(); + QRect(textRect.topRight(), + QPoint(menuitem->rect.right(), textRect.bottom()))); + const QString textToDraw = s.mid(tabIndex + 1).toString(); if (dis && !act && proxy()->styleHint(SH_EtchDisabledText, option, widget)) { p->setPen(menuitem->palette.light().color()); p->drawText(vShortcutRect.adjusted(1, 1, 1, 1), text_flags, textToDraw); p->setPen(discol); } p->drawText(vShortcutRect, text_flags, textToDraw); - s = s.left(t); + s = s.left(tabIndex); } QFont font = menuitem->font; // font may not have any "hard" flags set. We override @@ -1709,7 +1598,10 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio font.setBold(true); p->setFont(font); - const QString textToDraw = s.left(t).toString(); + const QFontMetrics fontMetrics(font); + const QString textToDraw = fontMetrics.elidedText(s.left(tabIndex).toString(), + Qt::ElideMiddle, vTextRect.width(), + text_flags); if (dis && !act && proxy()->styleHint(SH_EtchDisabledText, option, widget)) { p->setPen(menuitem->palette.light().color()); p->drawText(vTextRect.adjusted(1, 1, 1, 1), text_flags, textToDraw); @@ -1721,17 +1613,17 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio // Arrow if (menuItem->menuItemType == QStyleOptionMenuItem::SubMenu) {// draw sub menu arrow - int dim = (menuItem->rect.height() - 4) / 2; + const int dim = (menuItem->rect.height() - 4) / 2; PrimitiveElement arrow; arrow = option->direction == Qt::RightToLeft ? PE_IndicatorArrowLeft : PE_IndicatorArrowRight; - int xpos = menuItem->rect.left() + menuItem->rect.width() - 3 - dim; + const int xpos = menuItem->rect.left() + menuItem->rect.width() - 3 - dim; QRect vSubMenuRect = visualRect(option->direction, menuItem->rect, QRect(xpos, menuItem->rect.top() + menuItem->rect.height() / 2 - dim / 2, dim, dim)); QStyleOptionMenuItem newMI = *menuItem; newMI.rect = vSubMenuRect; newMI.state = !enabled ? State_None : State_Enabled; if (selected) - newMI.palette.setColor(QPalette::Foreground, + newMI.palette.setColor(QPalette::WindowText, newMI.palette.highlightedText().color()); proxy()->drawPrimitive(arrow, &newMI, painter, widget); } @@ -1751,68 +1643,11 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio proxy()->drawControl(CE_PushButtonLabel, &subopt, painter, widget); } break; - case CE_PushButtonLabel: - if (const QStyleOptionButton *button = qstyleoption_cast<const QStyleOptionButton *>(option)) { - QRect ir = button->rect; - uint tf = Qt::AlignVCenter; - if (styleHint(SH_UnderlineShortcut, button, widget)) - tf |= Qt::TextShowMnemonic; - else - tf |= Qt::TextHideMnemonic; - - if (!button->icon.isNull()) { - //Center both icon and text - QPoint point; - - QIcon::Mode mode = button->state & State_Enabled ? QIcon::Normal - : QIcon::Disabled; - if (mode == QIcon::Normal && button->state & State_HasFocus) - mode = QIcon::Active; - QIcon::State state = QIcon::Off; - if (button->state & State_On) - state = QIcon::On; - - QPixmap pixmap = button->icon.pixmap(button->iconSize, mode, state); - int w = pixmap.width() / pixmap.devicePixelRatio(); - int h = pixmap.height() / pixmap.devicePixelRatio(); - - if (!button->text.isEmpty()) - w += button->fontMetrics.boundingRect(option->rect, tf, button->text).width() + 2; - - point = QPoint(ir.x() + ir.width() / 2 - w / 2, - ir.y() + ir.height() / 2 - h / 2); - - w = pixmap.width() / pixmap.devicePixelRatio(); - - if (button->direction == Qt::RightToLeft) - point.rx() += w; - - painter->drawPixmap(visualPos(button->direction, button->rect, point), pixmap); - - if (button->direction == Qt::RightToLeft) - ir.translate(-point.x() - 2, 0); - else - ir.translate(point.x() + w, 0); - - // left-align text if there is - if (!button->text.isEmpty()) - tf |= Qt::AlignLeft; - - } else { - tf |= Qt::AlignHCenter; - } - - if (button->features & QStyleOptionButton::HasMenu) - ir = ir.adjusted(0, 0, -proxy()->pixelMetric(PM_MenuButtonIndicator, button, widget), 0); - proxy()->drawItemText(painter, ir, tf, button->palette, (button->state & State_Enabled), - button->text, QPalette::ButtonText); - } - break; case CE_MenuBarEmptyArea: painter->save(); { painter->fillRect(rect, option->palette.window()); - QColor shadow = mergedColors(option->palette.background().color().darker(120), + QColor shadow = mergedColors(option->palette.window().color().darker(120), outline.lighter(140), 60); painter->setPen(QPen(shadow)); painter->drawLine(option->rect.bottomLeft(), option->rect.bottomRight()); @@ -1975,7 +1810,7 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption // ### backgroundrole/foregroundrole should be part of the style option alphaCornerColor = mergedColors(option->palette.color(widget->backgroundRole()), outline); } else { - alphaCornerColor = mergedColors(option->palette.background().color(), outline); + alphaCornerColor = mergedColors(option->palette.window().color(), outline); } switch (control) { @@ -1993,7 +1828,23 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption frame.lineWidth = groupBox->lineWidth; frame.midLineWidth = groupBox->midLineWidth; frame.rect = proxy()->subControlRect(CC_GroupBox, option, SC_GroupBoxFrame, widget); + painter->save(); + QRegion region(groupBox->rect); + if (!groupBox->text.isEmpty()) { + bool ltr = groupBox->direction == Qt::LeftToRight; + QRect finalRect; + if (groupBox->subControls & QStyle::SC_GroupBoxCheckBox) { + finalRect = checkBoxRect.united(textRect); + finalRect.adjust(ltr ? -4 : -2, 0, ltr ? 2 : 4, 0); + } else { + finalRect = textRect; + finalRect.adjust(-2, 0, 2, 0); + } + region -= finalRect.adjusted(0, 0, 0, 3 - textRect.height() / 2); + } + painter->setClipRegion(region); proxy()->drawPrimitive(PE_FrameGroupBox, &frame, painter, widget); + painter->restore(); } // Draw title @@ -2028,18 +1879,18 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption #if QT_CONFIG(spinbox) case CC_SpinBox: if (const QStyleOptionSpinBox *spinBox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) { + const qreal dpr = painter->device()->devicePixelRatio(); QPixmap cache; - QString pixmapName = QStyleHelper::uniqueName(QLatin1String("spinbox"), spinBox, spinBox->rect.size()); - if (!QPixmapCache::find(pixmapName, cache)) { + QString pixmapName = QStyleHelper::uniqueName("spinbox"_L1, spinBox, spinBox->rect.size(), dpr); + if (!QPixmapCache::find(pixmapName, &cache)) { - cache = styleCachePixmap(spinBox->rect.size()); - cache.fill(Qt::transparent); + cache = styleCachePixmap(spinBox->rect.size(), dpr); QRect pixmapRect(0, 0, spinBox->rect.width(), spinBox->rect.height()); QRect rect = pixmapRect; QRect r = rect.adjusted(0, 1, 0, -1); QPainter cachePainter(&cache); - QColor arrowColor = spinBox->palette.foreground().color(); + QColor arrowColor = spinBox->palette.windowText().color(); arrowColor.setAlpha(160); bool isEnabled = (spinBox->state & State_Enabled); @@ -2068,22 +1919,24 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption cachePainter.setPen(d->topShadow()); cachePainter.drawLine(QPoint(r.left() + 2, r.top() + 1), QPoint(r.right() - 2, r.top() + 1)); - // Draw button gradient - QColor buttonColor = d->buttonColor(option->palette); - QRect updownRect = upRect.adjusted(0, -2, 0, downRect.height() + 2); - QLinearGradient gradient = qt_fusion_gradient(updownRect, (isEnabled && option->state & State_MouseOver ) ? buttonColor : buttonColor.darker(104)); + if (!upRect.isNull()) { + // Draw button gradient + const QColor buttonColor = d->buttonColor(option->palette); + const QRect updownRect = upRect.adjusted(0, -2, 0, downRect.height() + 2); + const QLinearGradient gradient = qt_fusion_gradient(updownRect, (isEnabled && option->state & State_MouseOver ) + ? buttonColor : buttonColor.darker(104)); - // Draw button gradient - cachePainter.setPen(Qt::NoPen); - cachePainter.setBrush(gradient); + cachePainter.setPen(Qt::NoPen); + cachePainter.setBrush(gradient); - cachePainter.save(); - cachePainter.setClipRect(updownRect); - cachePainter.drawRoundedRect(r.adjusted(0, 0, -1, -1), 2, 2); - cachePainter.setPen(QPen(d->innerContrastLine())); - cachePainter.setBrush(Qt::NoBrush); - cachePainter.drawRoundedRect(r.adjusted(1, 1, -2, -2), 2, 2); - cachePainter.restore(); + cachePainter.save(); + cachePainter.setClipRect(updownRect); + cachePainter.drawRoundedRect(r.adjusted(0, 0, -1, -1), 2, 2); + cachePainter.setPen(QPen(d->innerContrastLine())); + cachePainter.setBrush(Qt::NoBrush); + cachePainter.drawRoundedRect(r.adjusted(1, 1, -2, -2), 2, 2); + cachePainter.restore(); + } if ((spinBox->stepEnabled & QAbstractSpinBox::StepUpEnabled) && upIsActive) { if (sunken) @@ -2111,12 +1964,14 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption cachePainter.restore(); } - // outline the up/down buttons - cachePainter.setPen(outline); - if (spinBox->direction == Qt::RightToLeft) { - cachePainter.drawLine(upRect.right(), upRect.top() - 1, upRect.right(), downRect.bottom() + 1); - } else { - cachePainter.drawLine(upRect.left(), upRect.top() - 1, upRect.left(), downRect.bottom() + 1); + if (spinBox->buttonSymbols != QAbstractSpinBox::NoButtons) { + // buttonSymbols == NoButtons results in 'null' rects + // and a tiny rect painted in the corner. + cachePainter.setPen(outline); + if (spinBox->direction == Qt::RightToLeft) + cachePainter.drawLine(QLineF(upRect.right(), upRect.top() - 0.5, upRect.right(), downRect.bottom() + 1.5)); + else + cachePainter.drawLine(QLineF(upRect.left(), upRect.top() - 0.5, upRect.left(), downRect.bottom() + 1.5)); } if (upIsActive && sunken) { @@ -2174,13 +2029,13 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption QColor highlight = option->palette.highlight().color(); QColor titleBarFrameBorder(active ? highlight.darker(180): outline.darker(110)); - QColor titleBarHighlight(active ? highlight.lighter(120): palette.background().color().lighter(120)); + QColor titleBarHighlight(active ? highlight.lighter(120): palette.window().color().lighter(120)); QColor textColor(active ? 0xffffff : 0xff000000); QColor textAlphaColor(active ? 0xffffff : 0xff000000 ); { // Fill title bar gradient - QColor titlebarColor = QColor(active ? highlight: palette.background().color()); + QColor titlebarColor = QColor(active ? highlight: palette.window().color()); QLinearGradient gradient(option->rect.center().x(), option->rect.top(), option->rect.center().x(), option->rect.bottom()); @@ -2443,10 +2298,10 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption int oldMin = styleObject->property("_q_stylemin").toInt(); int oldMax = styleObject->property("_q_stylemax").toInt(); QRect oldRect = styleObject->property("_q_stylerect").toRect(); - QStyle::State oldState = static_cast<QStyle::State>(styleObject->property("_q_stylestate").value<QStyle::State::Int>()); + QStyle::State oldState = static_cast<QStyle::State>(qvariant_cast<QStyle::State::Int>(styleObject->property("_q_stylestate"))); uint oldActiveControls = styleObject->property("_q_stylecontrols").toUInt(); - // a scrollbar is transient when the the scrollbar itself and + // a scrollbar is transient when the scrollbar itself and // its sibling are both inactive (ie. not pressed/hovered/moved) bool transient = !option->activeSubControls && !(option->state & State_On); @@ -2531,7 +2386,7 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption QColor alphaOutline = outline; alphaOutline.setAlpha(180); - QColor arrowColor = option->palette.foreground().color(); + QColor arrowColor = option->palette.windowText().color(); arrowColor.setAlpha(160); const QColor bgColor = QStyleHelper::backgroundColor(option->palette, widget); @@ -2591,7 +2446,6 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption subtleEdge.setAlpha(40); painter->setPen(subtleEdge); painter->setBrush(Qt::NoBrush); - painter->setClipRect(scrollBarGroove.adjusted(1, 0, -1, -3)); painter->drawRect(scrollBarGroove.adjusted(1, 0, -1, -1)); painter->restore(); } @@ -2631,10 +2485,12 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption painter->setBrush(midColor2); else if (option->state & State_MouseOver && scrollBar->activeSubControls & SC_ScrollBarSlider) painter->setBrush(highlightedGradient); - else + else if (!isDarkBg) painter->setBrush(gradient); + else + painter->setBrush(midColor2); - painter->drawRect(pixmapRect.adjusted(horizontal ? -1 : 0, horizontal ? 0 : -1, horizontal ? 0 : 1, horizontal ? 1 : 0)); + painter->drawRect(pixmapRect.adjusted(horizontal ? -1 : 0, horizontal ? 0 : -1, horizontal ? 0 : -1, horizontal ? -1 : 0)); painter->setPen(d->innerContrastLine()); painter->drawRect(scrollBarSlider.adjusted(horizontal ? 0 : 1, horizontal ? 1 : 0, -1, -1)); @@ -2664,16 +2520,9 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption painter->drawRect(scrollBarSubLine.adjusted(horizontal ? 0 : 1, horizontal ? 1 : 0, 0, 0)); painter->setPen(QPen(alphaOutline)); if (option->state & State_Horizontal) { - if (option->direction == Qt::RightToLeft) { - pixmapRect.setLeft(scrollBarSubLine.left()); - painter->drawLine(pixmapRect.topLeft(), pixmapRect.bottomLeft()); - } else { - pixmapRect.setRight(scrollBarSubLine.right()); - painter->drawLine(pixmapRect.topRight(), pixmapRect.bottomRight()); - } + painter->drawRect(scrollBarSubLine.adjusted(horizontal ? 0 : 1, 0, horizontal ? 1 : 0, horizontal ? -1 : 0)); } else { - pixmapRect.setBottom(scrollBarSubLine.bottom()); - painter->drawLine(pixmapRect.bottomLeft(), pixmapRect.bottomRight()); + painter->drawRect(scrollBarSubLine.adjusted(0, 0, horizontal ? 0 : -1, 0)); } QRect upRect = scrollBarSubLine.adjusted(horizontal ? 0 : 1, horizontal ? 1 : 0, horizontal ? -2 : -1, horizontal ? -1 : -2); @@ -2701,16 +2550,9 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption painter->drawRect(scrollBarAddLine.adjusted(horizontal ? 0 : 1, horizontal ? 1 : 0, 0, 0)); painter->setPen(QPen(alphaOutline, 1)); if (option->state & State_Horizontal) { - if (option->direction == Qt::LeftToRight) { - pixmapRect.setLeft(scrollBarAddLine.left()); - painter->drawLine(pixmapRect.topLeft(), pixmapRect.bottomLeft()); - } else { - pixmapRect.setRight(scrollBarAddLine.right()); - painter->drawLine(pixmapRect.topRight(), pixmapRect.bottomRight()); - } + painter->drawRect(scrollBarAddLine.adjusted(horizontal ? -1 : 0, 0, horizontal ? -1 : 0, horizontal ? -1 : 0)); } else { - pixmapRect.setTop(scrollBarAddLine.top()); - painter->drawLine(pixmapRect.topLeft(), pixmapRect.topRight()); + painter->drawRect(scrollBarAddLine.adjusted(0, horizontal ? 0 : -1, horizontal ? 0 : -1, horizontal ? 0 : -1)); } QRect downRect = scrollBarAddLine.adjusted(1, 1, -1, -1); @@ -2726,7 +2568,7 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption } painter->restore(); - break;; + break; #endif // QT_CONFIG(slider) case CC_ComboBox: painter->save(); @@ -2734,20 +2576,16 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption bool hasFocus = option->state & State_HasFocus && option->state & State_KeyboardFocusChange; bool sunken = comboBox->state & State_On; // play dead, if combobox has no items bool isEnabled = (comboBox->state & State_Enabled); + const qreal dpr = painter->device()->devicePixelRatio(); QPixmap cache; - QString pixmapName = QStyleHelper::uniqueName(QLatin1String("combobox"), option, comboBox->rect.size()); - if (sunken) - pixmapName += QLatin1String("-sunken"); - if (comboBox->editable) - pixmapName += QLatin1String("-editable"); - if (isEnabled) - pixmapName += QLatin1String("-enabled"); - if (!comboBox->frame) - pixmapName += QLatin1String("-frameless"); - - if (!QPixmapCache::find(pixmapName, cache)) { - cache = styleCachePixmap(comboBox->rect.size()); - cache.fill(Qt::transparent); + const QString pixmapName = QStyleHelper::uniqueName("combobox"_L1 + % QLatin1StringView(sunken ? "-sunken" : "") + % QLatin1StringView(comboBox->editable ? "-editable" : "") + % QLatin1StringView(isEnabled ? "-enabled" : "") + % QLatin1StringView(!comboBox->frame ? "-frameless" : ""), + option, comboBox->rect.size(), dpr); + if (!QPixmapCache::find(pixmapName, &cache)) { + cache = styleCachePixmap(comboBox->rect.size(), dpr); QPainter cachePainter(&cache); QRect pixmapRect(0, 0, comboBox->rect.width(), comboBox->rect.height()); QStyleOptionComboBox comboBoxCopy = *comboBox; @@ -2835,6 +2673,7 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption #if QT_CONFIG(slider) case CC_Slider: if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(option)) { + const qreal dpr = painter->device()->devicePixelRatio(); QRect groove = proxy()->subControlRect(CC_Slider, option, SC_SliderGroove, widget); QRect handle = proxy()->subControlRect(CC_Slider, option, SC_SliderHandle, widget); @@ -2856,13 +2695,13 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption grooveColor.setHsv(buttonColor.hue(), qMin(255, (int)(buttonColor.saturation())), qMin(255, (int)(buttonColor.value()*0.9))); - QString groovePixmapName = QStyleHelper::uniqueName(QLatin1String("slider_groove"), option, groove.size()); + QString groovePixmapName = QStyleHelper::uniqueName("slider_groove"_L1, option, + groove.size(), dpr); QRect pixmapRect(0, 0, groove.width(), groove.height()); // draw background groove - if (!QPixmapCache::find(groovePixmapName, cache)) { - cache = styleCachePixmap(pixmapRect.size()); - cache.fill(Qt::transparent); + if (!QPixmapCache::find(groovePixmapName, &cache)) { + cache = styleCachePixmap(pixmapRect.size(), dpr); QPainter groovePainter(&cache); groovePainter.setRenderHint(QPainter::Antialiasing, true); groovePainter.translate(0.5, 0.5); @@ -2887,10 +2726,10 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption // draw blue groove highlight QRect clipRect; - groovePixmapName += QLatin1String("_blue"); - if (!QPixmapCache::find(groovePixmapName, cache)) { - cache = styleCachePixmap(pixmapRect.size()); - cache.fill(Qt::transparent); + if (!groovePixmapName.isEmpty()) + groovePixmapName += "_blue"_L1; + if (!QPixmapCache::find(groovePixmapName, &cache)) { + cache = styleCachePixmap(pixmapRect.size(), dpr); QPainter groovePainter(&cache); QLinearGradient gradient; if (horizontal) { @@ -2903,13 +2742,13 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption } QColor highlight = d->highlight(option->palette); QColor highlightedoutline = highlight.darker(140); - if (qGray(outline.rgb()) > qGray(highlightedoutline.rgb())) - outline = highlightedoutline; - + QColor grooveOutline = outline; + if (qGray(grooveOutline.rgb()) > qGray(highlightedoutline.rgb())) + grooveOutline = highlightedoutline; groovePainter.setRenderHint(QPainter::Antialiasing, true); groovePainter.translate(0.5, 0.5); - groovePainter.setPen(QPen(outline)); + groovePainter.setPen(QPen(grooveOutline)); gradient.setColorAt(0, activeHighlight); gradient.setColorAt(1, activeHighlight.lighter(130)); groovePainter.setBrush(gradient); @@ -2924,10 +2763,11 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption if (slider->upsideDown) clipRect = QRect(handle.right(), groove.top(), groove.right() - handle.right(), groove.height()); else - clipRect = QRect(groove.left(), groove.top(), handle.left(), groove.height()); + clipRect = QRect(groove.left(), groove.top(), + handle.left() - slider->rect.left(), groove.height()); } else { if (slider->upsideDown) - clipRect = QRect(groove.left(), handle.bottom(), groove.width(), groove.height() - handle.bottom()); + clipRect = QRect(groove.left(), handle.bottom(), groove.width(), groove.height() - (handle.bottom() - slider->rect.top())); else clipRect = QRect(groove.left(), groove.top(), groove.width(), handle.top() - groove.top()); } @@ -2938,6 +2778,8 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption } if (option->subControls & SC_SliderTickmarks) { + painter->save(); + painter->translate(slider->rect.x(), slider->rect.y()); painter->setPen(outline); int tickSize = proxy()->pixelMetric(PM_SliderTickmarkOffset, option, widget); int available = proxy()->pixelMetric(PM_SliderSpaceAvailable, slider, widget); @@ -2955,6 +2797,7 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption int v = slider->minimum; int len = proxy()->pixelMetric(PM_SliderLength, slider, widget); + QVector<QLine> lines; while (v <= slider->maximum + 1) { if (v == slider->maximum + 1 && interval == 1) break; @@ -2968,21 +2811,21 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption if (horizontal) { if (ticksAbove) { - painter->drawLine(pos, slider->rect.top() + extra, - pos, slider->rect.top() + tickSize); + lines += QLine(pos, slider->rect.top() + extra, + pos, slider->rect.top() + tickSize); } if (ticksBelow) { - painter->drawLine(pos, slider->rect.bottom() - extra, - pos, slider->rect.bottom() - tickSize); + lines += QLine(pos, slider->rect.bottom() - extra, + pos, slider->rect.bottom() - tickSize); } } else { if (ticksAbove) { - painter->drawLine(slider->rect.left() + extra, pos, - slider->rect.left() + tickSize, pos); + lines += QLine(slider->rect.left() + extra, pos, + slider->rect.left() + tickSize, pos); } if (ticksBelow) { - painter->drawLine(slider->rect.right() - extra, pos, - slider->rect.right() - tickSize, pos); + lines += QLine(slider->rect.right() - extra, pos, + slider->rect.right() - tickSize, pos); } } // in the case where maximum is max int @@ -2991,13 +2834,15 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption break; v = nextInterval; } + painter->drawLines(lines); + painter->restore(); } // draw handle if ((option->subControls & SC_SliderHandle) ) { - QString handlePixmapName = QStyleHelper::uniqueName(QLatin1String("slider_handle"), option, handle.size()); - if (!QPixmapCache::find(handlePixmapName, cache)) { - cache = styleCachePixmap(handle.size()); - cache.fill(Qt::transparent); + QString handlePixmapName = QStyleHelper::uniqueName("slider_handle"_L1, option, + handle.size(), dpr); + if (!QPixmapCache::find(handlePixmapName, &cache)) { + cache = styleCachePixmap(handle.size(), dpr); QRect pixmapRect(0, 0, handle.width(), handle.height()); QPainter handlePainter(&cache); QRect gradRect = pixmapRect.adjusted(2, 2, -2, -2); @@ -3011,7 +2856,7 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption handlePainter.setPen(Qt::NoPen); handlePainter.setBrush(QColor(0, 0, 0, 40)); - handlePainter.drawRect(r.adjusted(-1, 2, 1, -2)); + handlePainter.drawRect(horizontal ? r.adjusted(-1, 2, 1, -2) : r.adjusted(2, -1, -2, 1)); handlePainter.setPen(QPen(d->outline(option->palette))); if (option->state & State_HasFocus && option->state & State_KeyboardFocusChange) @@ -3081,7 +2926,6 @@ int QFusionStyle::pixelMetric(PixelMetric metric, const QStyleOption *option, co case PM_ListViewIconSize: val = 24; break; - case PM_DialogButtonsSeparator: case PM_ScrollBarSliderMin: val = 26; break; @@ -3175,7 +3019,7 @@ int QFusionStyle::pixelMetric(PixelMetric metric, const QStyleOption *option, co default: return QCommonStyle::pixelMetric(metric, option, widget); } - return QStyleHelper::dpiScaled(val); + return QStyleHelper::dpiScaled(val, option); } /*! @@ -3196,7 +3040,7 @@ QSize QFusionStyle::sizeFromContents(ContentsType type, const QStyleOption *opti break; case CT_GroupBox: if (option) { - int topMargin = qMax(pixelMetric(PM_ExclusiveIndicatorHeight), option->fontMetrics.height()) + groupBoxTopMargin; + int topMargin = qMax(pixelMetric(PM_IndicatorHeight, option, widget), option->fontMetrics.height()) + groupBoxTopMargin; newSize += QSize(10, topMargin); // Add some space below the groupbox } break; @@ -3221,23 +3065,24 @@ QSize QFusionStyle::sizeFromContents(ContentsType type, const QStyleOption *opti break; case CT_MenuItem: if (const QStyleOptionMenuItem *menuItem = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) { - int w = newSize.width(); - int maxpmw = menuItem->maxIconWidth; - int tabSpacing = 20; - if (menuItem->text.contains(QLatin1Char('\t'))) - w += tabSpacing; + int w = size.width(); // Don't rely of QCommonStyle's width calculation here + if (menuItem->text.contains(u'\t')) + w += menuItem->reservedShortcutWidth; else if (menuItem->menuItemType == QStyleOptionMenuItem::SubMenu) - w += 2 * QStyleHelper::dpiScaled(QFusionStylePrivate::menuArrowHMargin); + w += 2 * QStyleHelper::dpiScaled(QFusionStylePrivate::menuArrowHMargin, option); else if (menuItem->menuItemType == QStyleOptionMenuItem::DefaultItem) { - QFontMetrics fm(menuItem->font); + const QFontMetrics fm(menuItem->font); QFont fontBold = menuItem->font; fontBold.setBold(true); - QFontMetrics fmBold(fontBold); - w += fmBold.width(menuItem->text) - fm.horizontalAdvance(menuItem->text); - } - const int checkcol = qMax<int>(maxpmw, QStyleHelper::dpiScaled(QFusionStylePrivate::menuCheckMarkWidth)); // Windows always shows a check column - w += checkcol; - w += QStyleHelper::dpiScaled(int(QFusionStylePrivate::menuRightBorder) + 10); + const QFontMetrics fmBold(fontBold); + w += fmBold.horizontalAdvance(menuItem->text) - fm.horizontalAdvance(menuItem->text); + } + const qreal dpi = QStyleHelper::dpi(option); + // Windows always shows a check column + const int checkcol = qMax<int>(menuItem->maxIconWidth, + QStyleHelper::dpiScaled(QFusionStylePrivate::menuCheckMarkWidth, dpi)); + w += checkcol + windowsItemFrame; + w += QStyleHelper::dpiScaled(int(QFusionStylePrivate::menuRightBorder) + 10, dpi); newSize.setWidth(w); if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) { if (!menuItem->text.isEmpty()) { @@ -3251,8 +3096,8 @@ QSize QFusionStyle::sizeFromContents(ContentsType type, const QStyleOption *opti } #endif } - newSize.setWidth(newSize.width() + QStyleHelper::dpiScaled(12)); - newSize.setWidth(qMax<int>(newSize.width(), QStyleHelper::dpiScaled(120))); + newSize.setWidth(newSize.width() + int(QStyleHelper::dpiScaled(12, dpi))); + newSize.setWidth(qMax<int>(newSize.width(), int(QStyleHelper::dpiScaled(120, dpi)))); } break; case CT_SizeGrip: @@ -3377,42 +3222,52 @@ QRect QFusionStyle::subControlRect(ComplexControl control, const QStyleOptionCom int tickSize = proxy()->pixelMetric(PM_SliderTickmarkOffset, option, widget); switch (subControl) { case SC_SliderHandle: { + const bool bothTicks = (slider->tickPosition & QSlider::TicksBothSides) == QSlider::TicksBothSides; if (slider->orientation == Qt::Horizontal) { - rect.setHeight(proxy()->pixelMetric(PM_SliderThickness)); - rect.setWidth(proxy()->pixelMetric(PM_SliderLength)); + rect.setHeight(proxy()->pixelMetric(PM_SliderThickness, option, widget)); + rect.setWidth(proxy()->pixelMetric(PM_SliderLength, option, widget)); int centerY = slider->rect.center().y() - rect.height() / 2; - if (slider->tickPosition & QSlider::TicksAbove) - centerY += tickSize; - if (slider->tickPosition & QSlider::TicksBelow) - centerY -= tickSize; + if (!bothTicks) { + if (slider->tickPosition & QSlider::TicksAbove) + centerY += tickSize; + if (slider->tickPosition & QSlider::TicksBelow) + centerY -= tickSize - 1; + } rect.moveTop(centerY); } else { - rect.setWidth(proxy()->pixelMetric(PM_SliderThickness)); - rect.setHeight(proxy()->pixelMetric(PM_SliderLength)); + rect.setWidth(proxy()->pixelMetric(PM_SliderThickness, option, widget)); + rect.setHeight(proxy()->pixelMetric(PM_SliderLength, option, widget)); int centerX = slider->rect.center().x() - rect.width() / 2; - if (slider->tickPosition & QSlider::TicksAbove) - centerX += tickSize; - if (slider->tickPosition & QSlider::TicksBelow) - centerX -= tickSize; + if (!bothTicks) { + if (slider->tickPosition & QSlider::TicksAbove) + centerX += tickSize; + if (slider->tickPosition & QSlider::TicksBelow) + centerX -= tickSize - 1; + } rect.moveLeft(centerX); } } break; case SC_SliderGroove: { QPoint grooveCenter = slider->rect.center(); - const int grooveThickness = QStyleHelper::dpiScaled(7); + const int grooveThickness = QStyleHelper::dpiScaled(7, option); + const bool bothTicks = (slider->tickPosition & QSlider::TicksBothSides) == QSlider::TicksBothSides; if (slider->orientation == Qt::Horizontal) { rect.setHeight(grooveThickness); - if (slider->tickPosition & QSlider::TicksAbove) - grooveCenter.ry() += tickSize; - if (slider->tickPosition & QSlider::TicksBelow) - grooveCenter.ry() -= tickSize; + if (!bothTicks) { + if (slider->tickPosition & QSlider::TicksAbove) + grooveCenter.ry() += tickSize; + if (slider->tickPosition & QSlider::TicksBelow) + grooveCenter.ry() -= tickSize - 1; + } } else { rect.setWidth(grooveThickness); - if (slider->tickPosition & QSlider::TicksAbove) - grooveCenter.rx() += tickSize; - if (slider->tickPosition & QSlider::TicksBelow) - grooveCenter.rx() -= tickSize; + if (!bothTicks) { + if (slider->tickPosition & QSlider::TicksAbove) + grooveCenter.rx() += tickSize; + if (slider->tickPosition & QSlider::TicksBelow) + grooveCenter.rx() -= tickSize - 1; + } } rect.moveCenter(grooveCenter); break; @@ -3429,7 +3284,7 @@ QRect QFusionStyle::subControlRect(ComplexControl control, const QStyleOptionCom int center = spinbox->rect.height() / 2; int fw = spinbox->frame ? 3 : 0; // Is drawn with 3 pixels width in drawComplexControl, independently from PM_SpinBoxFrameWidth int y = fw; - const int buttonWidth = QStyleHelper::dpiScaled(14); + const int buttonWidth = QStyleHelper::dpiScaled(14, option); int x, lx, rx; x = spinbox->rect.width() - y - buttonWidth + 2; lx = fw; @@ -3455,6 +3310,7 @@ QRect QFusionStyle::subControlRect(ComplexControl control, const QStyleOptionCom break; case SC_SpinBoxFrame: rect = spinbox->rect; + break; default: break; } @@ -3464,14 +3320,20 @@ QRect QFusionStyle::subControlRect(ComplexControl control, const QStyleOptionCom #endif // QT_CONFIG(spinbox) case CC_GroupBox: if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast<const QStyleOptionGroupBox *>(option)) { - rect = option->rect; + const int groupBoxTextAlignment = groupBox->textAlignment; + const bool hasVerticalAlignment = (groupBoxTextAlignment & Qt::AlignVertical_Mask) == Qt::AlignVCenter; + const int fontMetricsHeight = groupBox->text.isEmpty() ? 0 : groupBox->fontMetrics.height(); + if (subControl == SC_GroupBoxFrame) - return rect.adjusted(0, 0, 0, 0); + return rect; else if (subControl == SC_GroupBoxContents) { QRect frameRect = option->rect.adjusted(0, 0, 0, -groupBoxBottomMargin); int margin = 3; int leftMarginExtension = 0; - int topMargin = qMax(pixelMetric(PM_ExclusiveIndicatorHeight), option->fontMetrics.height()) + groupBoxTopMargin; + const int indicatorHeight = option->subControls.testFlag(SC_GroupBoxCheckBox) ? + pixelMetric(PM_IndicatorHeight, option, widget) : 0; + const int topMargin = qMax(indicatorHeight, fontMetricsHeight) + + groupBoxTopMargin; return frameRect.adjusted(leftMarginExtension + margin, margin + topMargin, -margin, -margin - groupBoxBottomMargin); } @@ -3485,12 +3347,17 @@ QRect QFusionStyle::subControlRect(ComplexControl control, const QStyleOptionCom rect = QRect(); if (option->rect.width() > width) { - switch (groupBox->textAlignment & Qt::AlignHorizontal_Mask) { + switch (groupBoxTextAlignment & Qt::AlignHorizontal_Mask) { case Qt::AlignHCenter: rect.moveLeft((option->rect.width() - width) / 2); break; case Qt::AlignRight: - rect.moveLeft(option->rect.width() - width); + rect.moveLeft(option->rect.width() - width + - (hasVerticalAlignment ? proxy()->pixelMetric(PM_LayoutRightMargin, groupBox, widget) : 0)); + break; + case Qt::AlignLeft: + if (hasVerticalAlignment) + rect.moveLeft(proxy()->pixelMetric(PM_LayoutLeftMargin, option, widget)); break; } } @@ -3513,17 +3380,19 @@ QRect QFusionStyle::subControlRect(ComplexControl control, const QStyleOptionCom case CC_ComboBox: switch (subControl) { - case SC_ComboBoxArrow: + case SC_ComboBoxArrow: { + const qreal dpi = QStyleHelper::dpi(option); rect = visualRect(option->direction, option->rect, rect); - rect.setRect(rect.right() - QStyleHelper::dpiScaled(18), rect.top() - 2, - QStyleHelper::dpiScaled(19), rect.height() + 4); + rect.setRect(rect.right() - int(QStyleHelper::dpiScaled(18, dpi)), rect.top() - 2, + int(QStyleHelper::dpiScaled(19, dpi)), rect.height() + 4); rect = visualRect(option->direction, option->rect, rect); + } break; case SC_ComboBoxEditField: { int frameWidth = 2; rect = visualRect(option->direction, option->rect, rect); rect.setRect(option->rect.left() + frameWidth, option->rect.top() + frameWidth, - option->rect.width() - int(QStyleHelper::dpiScaled(19)) - 2 * frameWidth, + option->rect.width() - int(QStyleHelper::dpiScaled(19, option)) - 2 * frameWidth, option->rect.height() - 2 * frameWidth); if (const QStyleOptionComboBox *box = qstyleoption_cast<const QStyleOptionComboBox *>(option)) { if (!box->editable) { @@ -3681,7 +3550,7 @@ int QFusionStyle::styleHint(StyleHint hint, const QStyleOption *option, const QW case SH_FontDialog_SelectAssociatedText: case SH_MenuBar_AltKeyNavigation: case SH_ComboBox_ListMouseTracking: - case SH_ScrollBar_StopMouseOverSlider: + case SH_Slider_StopMouseOverSlider: case SH_ScrollBar_MiddleClickAbsolutePosition: case SH_EtchDisabledText: case SH_TitleBar_AutoRaise: @@ -3713,7 +3582,7 @@ int QFusionStyle::styleHint(StyleHint hint, const QStyleOption *option, const QW return 0; case SH_Table_GridLineColor: - return option ? option->palette.background().color().darker(120).rgb() : 0; + return option ? option->palette.window().color().darker(120).rgba() : 0; case SH_MessageBox_TextInteractionFlags: return Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse; @@ -3740,6 +3609,17 @@ int QFusionStyle::styleHint(StyleHint hint, const QStyleOption *option, const QW mask->region -= QRect(option->rect.right() , option->rect.top() + 3, 1, 2); return 1; } + break; + case SH_GroupBox_TextLabelVerticalAlignment: { + if (const auto *groupBox = qstyleoption_cast<const QStyleOptionGroupBox *>(option)) { + if (groupBox) { + const auto vAlign = groupBox->textAlignment & Qt::AlignVertical_Mask; + // default fusion style is AlignTop + return vAlign == 0 ? Qt::AlignTop : vAlign; + } + } + break; + } default: break; } @@ -3780,24 +3660,49 @@ QRect QFusionStyle::subElementRect(SubElement sr, const QStyleOption *opt, const } /*! - \reimp + \internal */ -QIcon QFusionStyle::standardIcon(StandardPixmap standardIcon, const QStyleOption *option, - const QWidget *widget) const +QIcon QFusionStyle::iconFromTheme(StandardPixmap standardIcon) const { -#if QT_CONFIG(imageformat_xpm) + QIcon icon; +#if QT_CONFIG(imageformat_png) + auto addIconFiles = [](QStringView prefix, QIcon &icon) + { + const auto fullPrefix = QStringLiteral(":/qt-project.org/styles/fusionstyle/images/") + prefix; + static constexpr auto dockTitleIconSizes = {10, 16, 20, 32, 48, 64}; + for (int size : dockTitleIconSizes) + icon.addFile(fullPrefix + QString::number(size) + QStringLiteral(".png"), + QSize(size, size)); + }; switch (standardIcon) { case SP_TitleBarNormalButton: - return QIcon(QPixmap(dock_widget_restore_xpm)); + addIconFiles(u"fusion_normalizedockup-", icon); + break; case SP_TitleBarMinButton: - return QIcon(QPixmap(workspace_minimize)); + addIconFiles(u"fusion_titlebar-min-", icon); + break; case SP_TitleBarCloseButton: case SP_DockWidgetCloseButton: - return QIcon(QPixmap(dock_widget_close_xpm)); + addIconFiles(u"fusion_closedock-", icon); + break; default: break; } -#endif // imageformat_xpm +#else // imageformat_png + Q_UNUSED(standardIcon); +#endif // imageformat_png + return icon; +} + +/*! + \reimp +*/ +QIcon QFusionStyle::standardIcon(StandardPixmap standardIcon, const QStyleOption *option, + const QWidget *widget) const +{ + const auto icon = iconFromTheme(standardIcon); + if (!icon.availableSizes().isEmpty()) + return icon; return QCommonStyle::standardIcon(standardIcon, option, widget); } @@ -3807,21 +3712,13 @@ QIcon QFusionStyle::standardIcon(StandardPixmap standardIcon, const QStyleOption QPixmap QFusionStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt, const QWidget *widget) const { -#ifndef QT_NO_IMAGEFORMAT_XPM - switch (standardPixmap) { - case SP_TitleBarNormalButton: - return QPixmap(dock_widget_restore_xpm); - case SP_TitleBarMinButton: - return QPixmap(workspace_minimize); - case SP_TitleBarCloseButton: - case SP_DockWidgetCloseButton: - return QPixmap(dock_widget_close_xpm); - - default: - break; - } -#endif //QT_NO_IMAGEFORMAT_XPM - + auto getDevicePixelRatio = [](const QWidget *widget) + { + return widget ? widget->devicePixelRatio() : qApp->devicePixelRatio(); + }; + const auto icon = iconFromTheme(standardPixmap); + if (!icon.availableSizes().isEmpty()) + return icon.pixmap(QSize(16, 16), getDevicePixelRatio(widget)); return QCommonStyle::standardPixmap(standardPixmap, opt, widget); } |