1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qfusionstyle_p.h"
5#include "qfusionstyle_p_p.h"
6
7#if QT_CONFIG(style_fusion) || defined(QT_PLUGIN)
8#include "qcommonstyle_p.h"
9#if QT_CONFIG(combobox)
10#include <qcombobox.h>
11#endif
12#if QT_CONFIG(pushbutton)
13#include <qpushbutton.h>
14#endif
15#if QT_CONFIG(abstractbutton)
16#include <qabstractbutton.h>
17#endif
18#include <qpainter.h>
19#include <qpainterpath.h>
20#include <qdir.h>
21#include <qstyleoption.h>
22#include <qapplication.h>
23#if QT_CONFIG(mainwindow)
24#include <qmainwindow.h>
25#endif
26#include <qfont.h>
27#if QT_CONFIG(groupbox)
28#include <qgroupbox.h>
29#endif
30#include <qpixmapcache.h>
31#if QT_CONFIG(scrollbar)
32#include <qscrollbar.h>
33#endif
34#if QT_CONFIG(spinbox)
35#include <qspinbox.h>
36#endif
37#if QT_CONFIG(abstractslider)
38#include <qabstractslider.h>
39#endif
40#if QT_CONFIG(slider)
41#include <qslider.h>
42#endif
43#if QT_CONFIG(splitter)
44#include <qsplitter.h>
45#endif
46#if QT_CONFIG(progressbar)
47#include <qprogressbar.h>
48#endif
49#if QT_CONFIG(wizard)
50#include <qwizard.h>
51#endif
52#include <qdrawutil.h>
53#include <private/qstylehelper_p.h>
54#include <private/qdrawhelper_p.h>
55#include <private/qapplication_p.h>
56#include <private/qwidget_p.h>
57
58QT_BEGIN_NAMESPACE
59
60using namespace Qt::StringLiterals;
61using namespace QStyleHelper;
62
63enum Direction {
64 TopDown,
65 FromLeft,
66 BottomUp,
67 FromRight
68};
69
70// from windows style
71static const int windowsItemFrame = 2; // menu item frame width
72static const int windowsItemVMargin = 8; // menu item ver text margin
73
74static const int groupBoxBottomMargin = 0; // space below the groupbox
75static const int groupBoxTopMargin = 3;
76
77#if QT_CONFIG(imageformat_xpm)
78static const char * const qt_titlebar_context_help[] = {
79 "10 10 3 1",
80 " c None",
81 "# c #000000",
82 "+ c #444444",
83 " +####+ ",
84 " ### ### ",
85 " ## ## ",
86 " +##+ ",
87 " +## ",
88 " ## ",
89 " ## ",
90 " ",
91 " ## ",
92 " ## "};
93#endif // QT_CONFIG(imageformat_xpm)
94
95static QColor mergedColors(const QColor &colorA, const QColor &colorB, int factor = 50)
96{
97 const int maxFactor = 100;
98 QColor tmp = colorA;
99 tmp.setRed((tmp.red() * factor) / maxFactor + (colorB.red() * (maxFactor - factor)) / maxFactor);
100 tmp.setGreen((tmp.green() * factor) / maxFactor + (colorB.green() * (maxFactor - factor)) / maxFactor);
101 tmp.setBlue((tmp.blue() * factor) / maxFactor + (colorB.blue() * (maxFactor - factor)) / maxFactor);
102 return tmp;
103}
104
105// The default button and handle gradient
106static QLinearGradient qt_fusion_gradient(const QRect &rect, const QBrush &baseColor, Direction direction = TopDown)
107{
108 int x = rect.center().x();
109 int y = rect.center().y();
110 QLinearGradient gradient;
111 switch (direction) {
112 case FromLeft:
113 gradient = QLinearGradient(rect.left(), y, rect.right(), y);
114 break;
115 case FromRight:
116 gradient = QLinearGradient(rect.right(), y, rect.left(), y);
117 break;
118 case BottomUp:
119 gradient = QLinearGradient(x, rect.bottom(), x, rect.top());
120 break;
121 case TopDown:
122 default:
123 gradient = QLinearGradient(x, rect.top(), x, rect.bottom());
124 break;
125 }
126 if (baseColor.gradient())
127 gradient.setStops(baseColor.gradient()->stops());
128 else {
129 QColor gradientStartColor = baseColor.color().lighter(f: 124);
130 QColor gradientStopColor = baseColor.color().lighter(f: 102);
131 gradient.setColorAt(pos: 0, color: gradientStartColor);
132 gradient.setColorAt(pos: 1, color: gradientStopColor);
133 // Uncomment for adding shiny shading
134 // QColor midColor1 = mergedColors(gradientStartColor, gradientStopColor, 55);
135 // QColor midColor2 = mergedColors(gradientStartColor, gradientStopColor, 45);
136 // gradient.setColorAt(0.5, midColor1);
137 // gradient.setColorAt(0.501, midColor2);
138 }
139 return gradient;
140}
141
142static void qt_fusion_draw_arrow(Qt::ArrowType type, QPainter *painter, const QStyleOption *option, const QRect &rect, const QColor &color)
143{
144 if (rect.isEmpty())
145 return;
146
147 const qreal dpi = QStyleHelper::dpi(option);
148 const qreal dpr = painter->device()->devicePixelRatio();
149 const int arrowWidth = int(QStyleHelper::dpiScaled(value: 14, dpi));
150 const int arrowHeight = int(QStyleHelper::dpiScaled(value: 8, dpi));
151
152 const int arrowMax = qMin(a: arrowHeight, b: arrowWidth);
153 const int rectMax = qMin(a: rect.height(), b: rect.width());
154 const int size = qMin(a: arrowMax, b: rectMax);
155
156 QPixmap cachePixmap;
157 const QString cacheKey = QStyleHelper::uniqueName(key: "fusion-arrow"_L1
158 % HexString<uint>(type)
159 % HexString<uint>(color.rgba()),
160 option, size: rect.size(), dpr);
161 if (!QPixmapCache::find(key: cacheKey, pixmap: &cachePixmap)) {
162 cachePixmap = styleCachePixmap(size: rect.size(), pixelRatio: dpr);
163 QPainter cachePainter(&cachePixmap);
164
165 QRectF arrowRect;
166 arrowRect.setWidth(size);
167 arrowRect.setHeight(arrowHeight * size / arrowWidth);
168 if (type == Qt::LeftArrow || type == Qt::RightArrow)
169 arrowRect = arrowRect.transposed();
170 arrowRect.moveTo(ax: (rect.width() - arrowRect.width()) / 2.0,
171 ay: (rect.height() - arrowRect.height()) / 2.0);
172
173 std::array<QPointF, 3> triangle;
174 switch (type) {
175 case Qt::DownArrow:
176 triangle = {arrowRect.topLeft(), arrowRect.topRight(), QPointF(arrowRect.center().x(), arrowRect.bottom())};
177 break;
178 case Qt::RightArrow:
179 triangle = {arrowRect.topLeft(), arrowRect.bottomLeft(), QPointF(arrowRect.right(), arrowRect.center().y())};
180 break;
181 case Qt::LeftArrow:
182 triangle = {arrowRect.topRight(), arrowRect.bottomRight(), QPointF(arrowRect.left(), arrowRect.center().y())};
183 break;
184 default:
185 triangle = {arrowRect.bottomLeft(), arrowRect.bottomRight(), QPointF(arrowRect.center().x(), arrowRect.top())};
186 break;
187 }
188
189 cachePainter.setPen(Qt::NoPen);
190 cachePainter.setBrush(color);
191 cachePainter.setRenderHint(hint: QPainter::Antialiasing);
192 cachePainter.drawPolygon(points: triangle.data(), pointCount: int(triangle.size()));
193
194 QPixmapCache::insert(key: cacheKey, pixmap: cachePixmap);
195 }
196
197 painter->drawPixmap(r: rect, pm: cachePixmap);
198}
199
200static void qt_fusion_draw_mdibutton(QPainter *painter, const QStyleOptionTitleBar *option, const QRect &tmp, bool hover, bool sunken)
201{
202 QColor dark;
203 dark.setHsv(h: option->palette.button().color().hue(),
204 s: qMin(a: 255, b: (int)(option->palette.button().color().saturation())),
205 v: qMin(a: 255, b: (int)(option->palette.button().color().value()*0.7)));
206
207 QColor highlight = option->palette.highlight().color();
208
209 bool active = (option->titleBarState & QStyle::State_Active);
210 QColor titleBarHighlight(255, 255, 255, 60);
211
212 if (sunken)
213 painter->fillRect(tmp.adjusted(xp1: 1, yp1: 1, xp2: -1, yp2: -1), color: option->palette.highlight().color().darker(f: 120));
214 else if (hover)
215 painter->fillRect(tmp.adjusted(xp1: 1, yp1: 1, xp2: -1, yp2: -1), color: QColor(255, 255, 255, 20));
216
217 QColor mdiButtonGradientStartColor;
218 QColor mdiButtonGradientStopColor;
219
220 mdiButtonGradientStartColor = QColor(0, 0, 0, 40);
221 mdiButtonGradientStopColor = QColor(255, 255, 255, 60);
222
223 if (sunken)
224 titleBarHighlight = highlight.darker(f: 130);
225
226 QLinearGradient gradient(tmp.center().x(), tmp.top(), tmp.center().x(), tmp.bottom());
227 gradient.setColorAt(pos: 0, color: mdiButtonGradientStartColor);
228 gradient.setColorAt(pos: 1, color: mdiButtonGradientStopColor);
229 QColor mdiButtonBorderColor(active ? option->palette.highlight().color().darker(f: 180): dark.darker(f: 110));
230
231 painter->setPen(QPen(mdiButtonBorderColor));
232 const QLine lines[4] = {
233 QLine(tmp.left() + 2, tmp.top(), tmp.right() - 2, tmp.top()),
234 QLine(tmp.left() + 2, tmp.bottom(), tmp.right() - 2, tmp.bottom()),
235 QLine(tmp.left(), tmp.top() + 2, tmp.left(), tmp.bottom() - 2),
236 QLine(tmp.right(), tmp.top() + 2, tmp.right(), tmp.bottom() - 2)
237 };
238 painter->drawLines(lines, lineCount: 4);
239 const QPoint points[4] = {
240 QPoint(tmp.left() + 1, tmp.top() + 1),
241 QPoint(tmp.right() - 1, tmp.top() + 1),
242 QPoint(tmp.left() + 1, tmp.bottom() - 1),
243 QPoint(tmp.right() - 1, tmp.bottom() - 1)
244 };
245 painter->drawPoints(points, pointCount: 4);
246
247 painter->setPen(titleBarHighlight);
248 painter->drawLine(x1: tmp.left() + 2, y1: tmp.top() + 1, x2: tmp.right() - 2, y2: tmp.top() + 1);
249 painter->drawLine(x1: tmp.left() + 1, y1: tmp.top() + 2, x2: tmp.left() + 1, y2: tmp.bottom() - 2);
250
251 painter->setPen(QPen(gradient, 1));
252 painter->drawLine(x1: tmp.right() + 1, y1: tmp.top() + 2, x2: tmp.right() + 1, y2: tmp.bottom() - 2);
253 painter->drawPoint(x: tmp.right() , y: tmp.top() + 1);
254
255 painter->drawLine(x1: tmp.left() + 2, y1: tmp.bottom() + 1, x2: tmp.right() - 2, y2: tmp.bottom() + 1);
256 painter->drawPoint(x: tmp.left() + 1, y: tmp.bottom());
257 painter->drawPoint(x: tmp.right() - 1, y: tmp.bottom());
258 painter->drawPoint(x: tmp.right() , y: tmp.bottom() - 1);
259}
260
261/*
262 \internal
263*/
264QFusionStylePrivate::QFusionStylePrivate()
265{
266 animationFps = 60;
267}
268
269/*!
270 \class QFusionStyle
271 \brief The QFusionStyle class provides a custom widget style
272
273 \inmodule QtWidgets
274 \internal
275
276 The Fusion style provides a custom look and feel that is not
277 tied to a particular platform.
278 //{Fusion Style Widget Gallery}
279 \sa QWindowsStyle, QWindowsVistaStyle, QMacStyle, QCommonStyle
280*/
281
282/*!
283 Constructs a QFusionStyle object.
284*/
285QFusionStyle::QFusionStyle() : QCommonStyle(*new QFusionStylePrivate)
286{
287 setObjectName("Fusion"_L1);
288}
289
290/*!
291 \internal
292
293 Constructs a QFusionStyle object.
294*/
295QFusionStyle::QFusionStyle(QFusionStylePrivate &dd) : QCommonStyle(dd)
296{
297}
298
299/*!
300 Destroys the QFusionStyle object.
301*/
302QFusionStyle::~QFusionStyle()
303{
304}
305
306/*!
307 \reimp
308*/
309void QFusionStyle::drawItemText(QPainter *painter, const QRect &rect, int alignment, const QPalette &pal,
310 bool enabled, const QString& text, QPalette::ColorRole textRole) const
311{
312 Q_UNUSED(enabled);
313 if (text.isEmpty())
314 return;
315
316 QPen savedPen = painter->pen();
317 if (textRole != QPalette::NoRole)
318 painter->setPen(QPen(pal.brush(cr: textRole), savedPen.widthF()));
319 painter->drawText(r: rect, flags: alignment, text);
320 painter->setPen(savedPen);
321}
322
323
324/*!
325 \reimp
326*/
327void QFusionStyle::drawPrimitive(PrimitiveElement elem,
328 const QStyleOption *option,
329 QPainter *painter, const QWidget *widget) const
330{
331 Q_ASSERT(option);
332 Q_D (const QFusionStyle);
333
334 QRect rect = option->rect;
335 int state = option->state;
336
337 const QColor outline = d->outline(pal: option->palette);
338 const QColor highlightedOutline = d->highlightedOutline(pal: option->palette);
339
340 const QColor tabFrameColor = d->tabFrameColor(pal: option->palette);
341
342 switch (elem) {
343
344#if QT_CONFIG(groupbox)
345 // No frame drawn
346 case PE_FrameGroupBox:
347 {
348 const auto strFrameGroupBox = QStringLiteral(u"fusion_groupbox");
349 QPixmap pixmap;
350 if (!QPixmapCache::find(key: strFrameGroupBox, pixmap: &pixmap)) {
351 pixmap.load(fileName: ":/qt-project.org/styles/commonstyle/images/fusion_groupbox.png"_L1);
352 QPixmapCache::insert(key: strFrameGroupBox, pixmap);
353 }
354 qDrawBorderPixmap(painter, target: option->rect, margins: QMargins(6, 6, 6, 6), pixmap);
355 break;
356 }
357#endif // QT_CONFIG(groupbox)
358 case PE_IndicatorBranch: {
359 if (!(option->state & State_Children))
360 break;
361 if (option->state & State_Open)
362 drawPrimitive(elem: PE_IndicatorArrowDown, option, painter, widget);
363 else {
364 const bool reverse = (option->direction == Qt::RightToLeft);
365 drawPrimitive(elem: reverse ? PE_IndicatorArrowLeft : PE_IndicatorArrowRight, option, painter, widget);
366 }
367 break;
368 }
369#if QT_CONFIG(tabbar)
370 case PE_FrameTabBarBase:
371 if (const QStyleOptionTabBarBase *tbb
372 = qstyleoption_cast<const QStyleOptionTabBarBase *>(opt: option)) {
373 painter->save();
374 painter->setPen(QPen(outline.lighter(f: 110)));
375 switch (tbb->shape) {
376 case QTabBar::RoundedNorth: {
377 QRegion region(tbb->rect);
378 region -= tbb->selectedTabRect;
379 painter->drawLine(p1: tbb->rect.topLeft(), p2: tbb->rect.topRight());
380 painter->setClipRegion(region);
381 painter->setPen(option->palette.light().color());
382 painter->drawLine(p1: tbb->rect.topLeft() + QPoint(0, 1), p2: tbb->rect.topRight() + QPoint(0, 1));
383 }
384 break;
385 case QTabBar::RoundedWest:
386 painter->drawLine(x1: tbb->rect.left(), y1: tbb->rect.top(), x2: tbb->rect.left(), y2: tbb->rect.bottom());
387 break;
388 case QTabBar::RoundedSouth:
389 painter->drawLine(x1: tbb->rect.left(), y1: tbb->rect.bottom(),
390 x2: tbb->rect.right(), y2: tbb->rect.bottom());
391 break;
392 case QTabBar::RoundedEast:
393 painter->drawLine(p1: tbb->rect.topRight(), p2: tbb->rect.bottomRight());
394 break;
395 case QTabBar::TriangularNorth:
396 case QTabBar::TriangularEast:
397 case QTabBar::TriangularWest:
398 case QTabBar::TriangularSouth:
399 painter->restore();
400 QCommonStyle::drawPrimitive(pe: elem, opt: option, p: painter, w: widget);
401 return;
402 }
403 painter->restore();
404 }
405 return;
406#endif // QT_CONFIG(tabbar)
407 case PE_PanelScrollAreaCorner: {
408 painter->save();
409 QColor alphaOutline = outline;
410 alphaOutline.setAlpha(180);
411 painter->setPen(alphaOutline);
412 painter->setBrush(option->palette.brush(cr: QPalette::Window));
413 painter->drawRect(r: option->rect);
414 painter->restore();
415 } break;
416 case PE_IndicatorArrowUp:
417 case PE_IndicatorArrowDown:
418 case PE_IndicatorArrowRight:
419 case PE_IndicatorArrowLeft:
420 {
421 if (option->rect.width() <= 1 || option->rect.height() <= 1)
422 break;
423 QColor arrowColor = option->palette.windowText().color();
424 arrowColor.setAlpha(160);
425 Qt::ArrowType arrow = Qt::UpArrow;
426 switch (elem) {
427 case PE_IndicatorArrowDown:
428 arrow = Qt::DownArrow;
429 break;
430 case PE_IndicatorArrowRight:
431 arrow = Qt::RightArrow;
432 break;
433 case PE_IndicatorArrowLeft:
434 arrow = Qt::LeftArrow;
435 break;
436 default:
437 break;
438 }
439 qt_fusion_draw_arrow(type: arrow, painter, option, rect: option->rect, color: arrowColor);
440 }
441 break;
442 case PE_IndicatorItemViewItemCheck:
443 {
444 QStyleOptionButton button;
445 button.QStyleOption::operator=(other: *option);
446 button.state &= ~State_MouseOver;
447 proxy()->drawPrimitive(pe: PE_IndicatorCheckBox, opt: &button, p: painter, w: widget);
448 }
449 return;
450 case PE_IndicatorHeaderArrow:
451 if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(opt: option)) {
452 QRect r = header->rect;
453 QColor arrowColor = header->palette.windowText().color();
454 arrowColor.setAlpha(180);
455 QPoint offset = QPoint(0, -2);
456
457#if defined(Q_OS_LINUX)
458 if (header->sortIndicator & QStyleOptionHeader::SortUp) {
459 qt_fusion_draw_arrow(type: Qt::UpArrow, painter, option, rect: r.translated(p: offset), color: arrowColor);
460 } else if (header->sortIndicator & QStyleOptionHeader::SortDown) {
461 qt_fusion_draw_arrow(type: Qt::DownArrow, painter, option, rect: r.translated(p: offset), color: arrowColor);
462 }
463#else
464 if (header->sortIndicator & QStyleOptionHeader::SortUp) {
465 qt_fusion_draw_arrow(Qt::DownArrow, painter, option, r.translated(offset), arrowColor);
466 } else if (header->sortIndicator & QStyleOptionHeader::SortDown) {
467 qt_fusion_draw_arrow(Qt::UpArrow, painter, option, r.translated(offset), arrowColor);
468 }
469#endif
470 }
471 break;
472 case PE_IndicatorButtonDropDown:
473 proxy()->drawPrimitive(pe: PE_PanelButtonCommand, opt: option, p: painter, w: widget);
474 break;
475
476 case PE_IndicatorToolBarSeparator:
477 {
478 QRect rect = option->rect;
479 const int margin = 6;
480 if (option->state & State_Horizontal) {
481 const int offset = rect.width()/2;
482 painter->setPen(QPen(option->palette.window().color().darker(f: 110)));
483 painter->drawLine(x1: rect.bottomLeft().x() + offset,
484 y1: rect.bottomLeft().y() - margin,
485 x2: rect.topLeft().x() + offset,
486 y2: rect.topLeft().y() + margin);
487 painter->setPen(QPen(option->palette.window().color().lighter(f: 110)));
488 painter->drawLine(x1: rect.bottomLeft().x() + offset + 1,
489 y1: rect.bottomLeft().y() - margin,
490 x2: rect.topLeft().x() + offset + 1,
491 y2: rect.topLeft().y() + margin);
492 } else { //Draw vertical separator
493 const int offset = rect.height()/2;
494 painter->setPen(QPen(option->palette.window().color().darker(f: 110)));
495 painter->drawLine(x1: rect.topLeft().x() + margin ,
496 y1: rect.topLeft().y() + offset,
497 x2: rect.topRight().x() - margin,
498 y2: rect.topRight().y() + offset);
499 painter->setPen(QPen(option->palette.window().color().lighter(f: 110)));
500 painter->drawLine(x1: rect.topLeft().x() + margin ,
501 y1: rect.topLeft().y() + offset + 1,
502 x2: rect.topRight().x() - margin,
503 y2: rect.topRight().y() + offset + 1);
504 }
505 }
506 break;
507 case PE_Frame: {
508 if (widget && widget->inherits(classname: "QComboBoxPrivateContainer")){
509 QStyleOption copy = *option;
510 copy.state |= State_Raised;
511 proxy()->drawPrimitive(pe: PE_PanelMenu, opt: &copy, p: painter, w: widget);
512 break;
513 }
514 painter->save();
515 QPen thePen(outline.lighter(f: 108));
516 thePen.setCosmetic(false);
517 painter->setPen(thePen);
518 painter->drawRect(r: option->rect.adjusted(xp1: 0, yp1: 0, xp2: -1, yp2: -1));
519 painter->restore(); }
520 break;
521 case PE_FrameMenu:
522 painter->save();
523 {
524 painter->setPen(QPen(outline));
525 painter->drawRect(r: option->rect.adjusted(xp1: 0, yp1: 0, xp2: -1, yp2: -1));
526 QColor frameLight = option->palette.window().color().lighter(f: 160);
527 QColor frameShadow = option->palette.window().color().darker(f: 110);
528
529 //paint beveleffect
530 QRect frame = option->rect.adjusted(xp1: 1, yp1: 1, xp2: -1, yp2: -1);
531 painter->setPen(frameLight);
532 painter->drawLine(p1: frame.topLeft(), p2: frame.bottomLeft());
533 painter->drawLine(p1: frame.topLeft(), p2: frame.topRight());
534
535 painter->setPen(frameShadow);
536 painter->drawLine(p1: frame.topRight(), p2: frame.bottomRight());
537 painter->drawLine(p1: frame.bottomLeft(), p2: frame.bottomRight());
538 }
539 painter->restore();
540 break;
541 case PE_FrameDockWidget:
542
543 painter->save();
544 {
545 QColor softshadow = option->palette.window().color().darker(f: 120);
546
547 QRect rect= option->rect;
548 painter->setPen(softshadow);
549 painter->drawRect(r: option->rect.adjusted(xp1: 0, yp1: 0, xp2: -1, yp2: -1));
550 painter->setPen(QPen(option->palette.light(), 1));
551 painter->drawLine(p1: QPoint(rect.left() + 1, rect.top() + 1), p2: QPoint(rect.left() + 1, rect.bottom() - 1));
552 painter->setPen(QPen(option->palette.window().color().darker(f: 120)));
553 painter->drawLine(p1: QPoint(rect.left() + 1, rect.bottom() - 1), p2: QPoint(rect.right() - 2, rect.bottom() - 1));
554 painter->drawLine(p1: QPoint(rect.right() - 1, rect.top() + 1), p2: QPoint(rect.right() - 1, rect.bottom() - 1));
555
556 }
557 painter->restore();
558 break;
559 case PE_PanelButtonTool:
560 painter->save();
561 if ((option->state & State_Enabled || option->state & State_On) || !(option->state & State_AutoRaise)) {
562 if (widget && widget->inherits(classname: "QDockWidgetTitleButton")) {
563 if (option->state & State_MouseOver)
564 proxy()->drawPrimitive(pe: PE_PanelButtonCommand, opt: option, p: painter, w: widget);
565 } else {
566 proxy()->drawPrimitive(pe: PE_PanelButtonCommand, opt: option, p: painter, w: widget);
567 }
568 }
569 painter->restore();
570 break;
571 case PE_IndicatorDockWidgetResizeHandle:
572 {
573 QStyleOption dockWidgetHandle = *option;
574 bool horizontal = option->state & State_Horizontal;
575 dockWidgetHandle.state.setFlag(flag: State_Horizontal, on: !horizontal);
576 proxy()->drawControl(element: CE_Splitter, opt: &dockWidgetHandle, p: painter, w: widget);
577 }
578 break;
579 case PE_FrameWindow:
580 painter->save();
581 {
582 QRect rect= option->rect;
583 painter->setPen(QPen(outline.darker(f: 150)));
584 painter->drawRect(r: option->rect.adjusted(xp1: 0, yp1: 0, xp2: -1, yp2: -1));
585 painter->setPen(QPen(option->palette.light(), 1));
586 painter->drawLine(p1: QPoint(rect.left() + 1, rect.top() + 1),
587 p2: QPoint(rect.left() + 1, rect.bottom() - 1));
588 painter->setPen(QPen(option->palette.window().color().darker(f: 120)));
589 painter->drawLine(p1: QPoint(rect.left() + 1, rect.bottom() - 1),
590 p2: QPoint(rect.right() - 2, rect.bottom() - 1));
591 painter->drawLine(p1: QPoint(rect.right() - 1, rect.top() + 1),
592 p2: QPoint(rect.right() - 1, rect.bottom() - 1));
593 }
594 painter->restore();
595 break;
596 case PE_FrameLineEdit:
597 {
598 QRect r = rect;
599 bool hasFocus = option->state & State_HasFocus;
600
601 painter->save();
602
603 painter->setRenderHint(hint: QPainter::Antialiasing, on: true);
604 // ### highdpi painter bug.
605 painter->translate(dx: 0.5, dy: 0.5);
606
607 // Draw Outline
608 painter->setPen( QPen(hasFocus ? highlightedOutline : outline));
609 painter->drawRoundedRect(rect: r.adjusted(xp1: 0, yp1: 0, xp2: -1, yp2: -1), xRadius: 2, yRadius: 2);
610
611 if (hasFocus) {
612 QColor softHighlight = highlightedOutline;
613 softHighlight.setAlpha(40);
614 painter->setPen(softHighlight);
615 painter->drawRoundedRect(rect: r.adjusted(xp1: 1, yp1: 1, xp2: -2, yp2: -2), xRadius: 1.7, yRadius: 1.7);
616 }
617 // Draw inner shadow
618 painter->setPen(d->topShadow());
619 painter->drawLine(p1: QPoint(r.left() + 2, r.top() + 1), p2: QPoint(r.right() - 2, r.top() + 1));
620
621 painter->restore();
622
623 }
624 break;
625 case PE_IndicatorCheckBox:
626 painter->save();
627 if (const QStyleOptionButton *checkbox = qstyleoption_cast<const QStyleOptionButton*>(opt: option)) {
628 painter->setRenderHint(hint: QPainter::Antialiasing, on: true);
629 painter->translate(dx: 0.5, dy: 0.5);
630 rect = rect.adjusted(xp1: 0, yp1: 0, xp2: -1, yp2: -1);
631
632 QColor pressedColor = mergedColors(colorA: option->palette.base().color(), colorB: option->palette.windowText().color(), factor: 85);
633 painter->setBrush(Qt::NoBrush);
634
635 // Gradient fill
636 QLinearGradient gradient(rect.topLeft(), rect.bottomLeft());
637 gradient.setColorAt(pos: 0, color: (state & State_Sunken) ? pressedColor : option->palette.base().color().darker(f: 115));
638 gradient.setColorAt(pos: 0.15, color: (state & State_Sunken) ? pressedColor : option->palette.base().color());
639 gradient.setColorAt(pos: 1, color: (state & State_Sunken) ? pressedColor : option->palette.base().color());
640
641 painter->setBrush((state & State_Sunken) ? QBrush(pressedColor) : gradient);
642 painter->setPen(QPen(outline.lighter(f: 110)));
643
644 if (option->state & State_HasFocus && option->state & State_KeyboardFocusChange)
645 painter->setPen(QPen(highlightedOutline));
646 painter->drawRect(r: rect);
647
648 QColor checkMarkColor = option->palette.text().color().darker(f: 120);
649 const qreal checkMarkPadding = 1 + rect.width() * 0.13; // at least one pixel padding
650
651 if (checkbox->state & State_NoChange) {
652 gradient = QLinearGradient(rect.topLeft(), rect.bottomLeft());
653 checkMarkColor.setAlpha(80);
654 gradient.setColorAt(pos: 0, color: checkMarkColor);
655 checkMarkColor.setAlpha(140);
656 gradient.setColorAt(pos: 1, color: checkMarkColor);
657 checkMarkColor.setAlpha(180);
658 painter->setPen(QPen(checkMarkColor, 1));
659 painter->setBrush(gradient);
660 painter->drawRect(r: rect.adjusted(xp1: checkMarkPadding, yp1: checkMarkPadding, xp2: -checkMarkPadding, yp2: -checkMarkPadding));
661
662 } else if (checkbox->state & State_On) {
663 const qreal dpi = QStyleHelper::dpi(option);
664 qreal penWidth = QStyleHelper::dpiScaled(value: 1.5, dpi);
665 penWidth = qMax<qreal>(a: penWidth, b: 0.13 * rect.height());
666 penWidth = qMin<qreal>(a: penWidth, b: 0.20 * rect.height());
667 QPen checkPen = QPen(checkMarkColor, penWidth);
668 checkMarkColor.setAlpha(210);
669 painter->translate(dx: dpiScaled(value: -0.8, dpi), dy: dpiScaled(value: 0.5, dpi));
670 painter->setPen(checkPen);
671 painter->setBrush(Qt::NoBrush);
672
673 // Draw checkmark
674 QPainterPath path;
675 const qreal rectHeight = rect.height(); // assuming height equals width
676 path.moveTo(x: checkMarkPadding + rectHeight * 0.11, y: rectHeight * 0.47);
677 path.lineTo(x: rectHeight * 0.5, y: rectHeight - checkMarkPadding);
678 path.lineTo(x: rectHeight - checkMarkPadding, y: checkMarkPadding);
679 painter->drawPath(path: path.translated(offset: rect.topLeft()));
680 }
681 }
682 painter->restore();
683 break;
684 case PE_IndicatorRadioButton:
685 painter->save();
686 {
687 QColor pressedColor = mergedColors(colorA: option->palette.base().color(), colorB: option->palette.windowText().color(), factor: 85);
688 painter->setBrush((state & State_Sunken) ? pressedColor : option->palette.base().color());
689 painter->setRenderHint(hint: QPainter::Antialiasing, on: true);
690 QPainterPath circle;
691 const QPointF circleCenter = rect.center() + QPoint(1, 1);
692 const qreal outlineRadius = (rect.width() + (rect.width() + 1) % 2) / 2.0 - 1;
693 circle.addEllipse(center: circleCenter, rx: outlineRadius, ry: outlineRadius);
694 painter->setPen(QPen(option->palette.window().color().darker(f: 150)));
695 if (option->state & State_HasFocus && option->state & State_KeyboardFocusChange)
696 painter->setPen(QPen(highlightedOutline));
697 painter->drawPath(path: circle);
698
699 if (state & (State_On )) {
700 circle = QPainterPath();
701 const qreal checkmarkRadius = outlineRadius / 2.32;
702 circle.addEllipse(center: circleCenter, rx: checkmarkRadius, ry: checkmarkRadius);
703 QColor checkMarkColor = option->palette.text().color().darker(f: 120);
704 checkMarkColor.setAlpha(200);
705 painter->setPen(checkMarkColor);
706 checkMarkColor.setAlpha(180);
707 painter->setBrush(checkMarkColor);
708 painter->drawPath(path: circle);
709 }
710 }
711 painter->restore();
712 break;
713 case PE_IndicatorToolBarHandle:
714 {
715 //draw grips
716 if (option->state & State_Horizontal) {
717 for (int i = -3 ; i < 2 ; i += 3) {
718 for (int j = -8 ; j < 10 ; j += 3) {
719 painter->fillRect(x: rect.center().x() + i, y: rect.center().y() + j, w: 2, h: 2, b: d->lightShade());
720 painter->fillRect(x: rect.center().x() + i, y: rect.center().y() + j, w: 1, h: 1, b: d->darkShade());
721 }
722 }
723 } else { //vertical toolbar
724 for (int i = -6 ; i < 12 ; i += 3) {
725 for (int j = -3 ; j < 2 ; j += 3) {
726 painter->fillRect(x: rect.center().x() + i, y: rect.center().y() + j, w: 2, h: 2, b: d->lightShade());
727 painter->fillRect(x: rect.center().x() + i, y: rect.center().y() + j, w: 1, h: 1, b: d->darkShade());
728 }
729 }
730 }
731 break;
732 }
733 case PE_FrameDefaultButton:
734 break;
735 case PE_FrameFocusRect:
736 if (const QStyleOptionFocusRect *fropt = qstyleoption_cast<const QStyleOptionFocusRect *>(opt: option)) {
737 //### check for d->alt_down
738 if (!(fropt->state & State_KeyboardFocusChange))
739 return;
740 QRect rect = option->rect;
741
742 painter->save();
743 painter->setRenderHint(hint: QPainter::Antialiasing, on: true);
744 painter->translate(dx: 0.5, dy: 0.5);
745 QColor fillcolor = highlightedOutline;
746 fillcolor.setAlpha(80);
747 painter->setPen(fillcolor.darker(f: 120));
748 fillcolor.setAlpha(30);
749 QLinearGradient gradient(rect.topLeft(), rect.bottomLeft());
750 gradient.setColorAt(pos: 0, color: fillcolor.lighter(f: 160));
751 gradient.setColorAt(pos: 1, color: fillcolor);
752 painter->setBrush(gradient);
753 painter->drawRoundedRect(rect: option->rect.adjusted(xp1: 0, yp1: 0, xp2: -1, yp2: -1), xRadius: 1, yRadius: 1);
754 painter->restore();
755 }
756 break;
757 case PE_PanelButtonCommand:
758 {
759 bool isDefault = false;
760 bool isFlat = false;
761 bool isDown = (option->state & State_Sunken) || (option->state & State_On);
762 QRect r;
763
764 if (const QStyleOptionButton *button = qstyleoption_cast<const QStyleOptionButton*>(opt: option)) {
765 isDefault = (button->features & QStyleOptionButton::DefaultButton) && (button->state & State_Enabled);
766 isFlat = (button->features & QStyleOptionButton::Flat);
767 }
768
769 if (isFlat && !isDown) {
770 if (isDefault) {
771 r = option->rect.adjusted(xp1: 0, yp1: 1, xp2: 0, yp2: -1);
772 painter->setPen(QPen(Qt::black));
773 const QLine lines[4] = {
774 QLine(QPoint(r.left() + 2, r.top()),
775 QPoint(r.right() - 2, r.top())),
776 QLine(QPoint(r.left(), r.top() + 2),
777 QPoint(r.left(), r.bottom() - 2)),
778 QLine(QPoint(r.right(), r.top() + 2),
779 QPoint(r.right(), r.bottom() - 2)),
780 QLine(QPoint(r.left() + 2, r.bottom()),
781 QPoint(r.right() - 2, r.bottom()))
782 };
783 painter->drawLines(lines, lineCount: 4);
784 const QPoint points[4] = {
785 QPoint(r.right() - 1, r.bottom() - 1),
786 QPoint(r.right() - 1, r.top() + 1),
787 QPoint(r.left() + 1, r.bottom() - 1),
788 QPoint(r.left() + 1, r.top() + 1)
789 };
790 painter->drawPoints(points, pointCount: 4);
791 }
792 return;
793 }
794
795
796 bool isEnabled = option->state & State_Enabled;
797 bool hasFocus = (option->state & State_HasFocus && option->state & State_KeyboardFocusChange);
798 QColor buttonColor = d->buttonColor(pal: option->palette);
799
800 QColor darkOutline = outline;
801 if (hasFocus | isDefault) {
802 darkOutline = highlightedOutline;
803 }
804
805 if (isDefault)
806 buttonColor = mergedColors(colorA: buttonColor, colorB: highlightedOutline.lighter(f: 130), factor: 90);
807
808 BEGIN_STYLE_PIXMAPCACHE(u"pushbutton-" + buttonColor.name(QColor::HexArgb))
809 r = rect.adjusted(xp1: 0, yp1: 1, xp2: -1, yp2: 0);
810
811 p->setRenderHint(hint: QPainter::Antialiasing, on: true);
812 p->translate(dx: 0.5, dy: -0.5);
813
814 QLinearGradient gradient = qt_fusion_gradient(rect, baseColor: (isEnabled && option->state & State_MouseOver ) ? buttonColor : buttonColor.darker(f: 104));
815 p->setPen(Qt::transparent);
816 p->setBrush(isDown ? QBrush(buttonColor.darker(f: 110)) : gradient);
817 p->drawRoundedRect(rect: r, xRadius: 2.0, yRadius: 2.0);
818 p->setBrush(Qt::NoBrush);
819
820 // Outline
821 p->setPen(!isEnabled ? QPen(darkOutline.lighter(f: 115)) : QPen(darkOutline));
822 p->drawRoundedRect(rect: r, xRadius: 2.0, yRadius: 2.0);
823
824 p->setPen(d->innerContrastLine());
825 p->drawRoundedRect(rect: r.adjusted(xp1: 1, yp1: 1, xp2: -1, yp2: -1), xRadius: 2.0, yRadius: 2.0);
826
827 END_STYLE_PIXMAPCACHE
828 }
829 break;
830 case PE_FrameTabWidget:
831 painter->save();
832 painter->fillRect(option->rect.adjusted(xp1: 0, yp1: 0, xp2: -1, yp2: -1), color: tabFrameColor);
833#if QT_CONFIG(tabwidget)
834 if (const QStyleOptionTabWidgetFrame *twf = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(opt: option)) {
835 QColor borderColor = outline.lighter(f: 110);
836 QRect rect = option->rect.adjusted(xp1: 0, yp1: 0, xp2: -1, yp2: -1);
837
838 // Shadow outline
839 if (twf->shape != QTabBar::RoundedSouth) {
840 rect.adjust(dx1: 0, dy1: 0, dx2: 0, dy2: -1);
841 QColor alphaShadow(Qt::black);
842 alphaShadow.setAlpha(15);
843 painter->setPen(alphaShadow);
844 painter->drawLine(p1: option->rect.bottomLeft(), p2: option->rect.bottomRight()); painter->setPen(borderColor);
845 }
846
847 // outline
848 painter->setPen(outline);
849 painter->drawRect(r: rect);
850
851 // Inner frame highlight
852 painter->setPen(d->innerContrastLine());
853 painter->drawRect(r: rect.adjusted(xp1: 1, yp1: 1, xp2: -1, yp2: -1));
854
855 }
856#endif // QT_CONFIG(tabwidget)
857 painter->restore();
858 break ;
859
860 case PE_FrameStatusBarItem:
861 break;
862 case PE_PanelMenu: {
863 painter->save();
864 const QBrush menuBackground = option->palette.base().color().lighter(f: 108);
865 QColor borderColor = option->palette.window().color().darker(f: 160);
866 qDrawPlainRect(p: painter, r: option->rect, borderColor, lineWidth: 1, fill: &menuBackground);
867 painter->restore();
868 }
869 break;
870
871 default:
872 QCommonStyle::drawPrimitive(pe: elem, opt: option, p: painter, w: widget);
873 break;
874 }
875}
876
877/*!
878 \reimp
879*/
880void QFusionStyle::drawControl(ControlElement element, const QStyleOption *option, QPainter *painter,
881 const QWidget *widget) const
882{
883 Q_D (const QFusionStyle);
884 QRect rect = option->rect;
885 QColor outline = d->outline(pal: option->palette);
886 QColor highlightedOutline = d->highlightedOutline(pal: option->palette);
887 QColor shadow = d->darkShade();
888
889 switch (element) {
890 case CE_ComboBoxLabel:
891 if (const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(opt: option)) {
892 QRect editRect = proxy()->subControlRect(cc: CC_ComboBox, opt: cb, sc: SC_ComboBoxEditField, widget);
893 painter->save();
894 painter->setClipRect(editRect);
895 if (!cb->currentIcon.isNull()) {
896 QIcon::Mode mode = cb->state & State_Enabled ? QIcon::Normal
897 : QIcon::Disabled;
898 QPixmap pixmap = cb->currentIcon.pixmap(size: cb->iconSize, devicePixelRatio: painter->device()->devicePixelRatio(), mode);
899 QRect iconRect(editRect);
900 iconRect.setWidth(cb->iconSize.width() + 4);
901 iconRect = alignedRect(direction: cb->direction,
902 alignment: Qt::AlignLeft | Qt::AlignVCenter,
903 size: iconRect.size(), rectangle: editRect);
904 if (cb->editable)
905 painter->fillRect(iconRect, cb->palette.brush(cr: QPalette::Base));
906 proxy()->drawItemPixmap(painter, rect: iconRect, alignment: Qt::AlignCenter, pixmap);
907
908 if (cb->direction == Qt::RightToLeft)
909 editRect.translate(dx: -4 - cb->iconSize.width(), dy: 0);
910 else
911 editRect.translate(dx: cb->iconSize.width() + 4, dy: 0);
912 }
913 if (!cb->currentText.isEmpty() && !cb->editable) {
914 proxy()->drawItemText(painter, rect: editRect.adjusted(xp1: 1, yp1: 0, xp2: -1, yp2: 0),
915 flags: visualAlignment(direction: cb->direction, alignment: cb->textAlignment),
916 pal: cb->palette, enabled: cb->state & State_Enabled, text: cb->currentText,
917 textRole: cb->editable ? QPalette::Text : QPalette::ButtonText);
918 }
919 painter->restore();
920 }
921 break;
922 case CE_Splitter:
923 {
924 // Don't draw handle for single pixel splitters
925 if (option->rect.width() > 1 && option->rect.height() > 1) {
926 //draw grips
927 if (option->state & State_Horizontal) {
928 for (int j = -6 ; j< 12 ; j += 3) {
929 painter->fillRect(x: rect.center().x() + 1, y: rect.center().y() + j, w: 2, h: 2, b: d->lightShade());
930 painter->fillRect(x: rect.center().x() + 1, y: rect.center().y() + j, w: 1, h: 1, b: d->darkShade());
931 }
932 } else {
933 for (int i = -6; i< 12 ; i += 3) {
934 painter->fillRect(x: rect.center().x() + i, y: rect.center().y(), w: 2, h: 2, b: d->lightShade());
935 painter->fillRect(x: rect.center().x() + i, y: rect.center().y(), w: 1, h: 1, b: d->darkShade());
936 }
937 }
938 }
939 break;
940 }
941#if QT_CONFIG(rubberband)
942 case CE_RubberBand:
943 if (qstyleoption_cast<const QStyleOptionRubberBand *>(opt: option)) {
944 QColor highlight = option->palette.color(cg: QPalette::Active, cr: QPalette::Highlight);
945 painter->save();
946 QColor penColor = highlight.darker(f: 120);
947 penColor.setAlpha(180);
948 painter->setPen(penColor);
949 QColor dimHighlight(qMin(a: highlight.red()/2 + 110, b: 255),
950 qMin(a: highlight.green()/2 + 110, b: 255),
951 qMin(a: highlight.blue()/2 + 110, b: 255));
952 dimHighlight.setAlpha(widget && widget->isWindow() ? 255 : 80);
953 QLinearGradient gradient(rect.topLeft(), QPoint(rect.bottomLeft().x(), rect.bottomLeft().y()));
954 gradient.setColorAt(pos: 0, color: dimHighlight.lighter(f: 120));
955 gradient.setColorAt(pos: 1, color: dimHighlight);
956 painter->setRenderHint(hint: QPainter::Antialiasing, on: true);
957 painter->translate(dx: 0.5, dy: 0.5);
958 painter->setBrush(dimHighlight);
959 painter->drawRoundedRect(rect: option->rect.adjusted(xp1: 0, yp1: 0, xp2: -1, yp2: -1), xRadius: 1, yRadius: 1);
960 //when the rectangle we get is large enough, draw the inner rectangle.
961 if (option->rect.width() > 2 && option->rect.height() > 2) {
962 QColor innerLine = Qt::white;
963 innerLine.setAlpha(40);
964 painter->setPen(innerLine);
965 painter->drawRoundedRect(rect: option->rect.adjusted(xp1: 1, yp1: 1, xp2: -2, yp2: -2), xRadius: 1, yRadius: 1);
966 }
967 painter->restore();
968 }
969 break;
970#endif //QT_CONFIG(rubberband)
971 case CE_SizeGrip:
972 painter->save();
973 {
974 //draw grips
975 for (int i = -6; i< 12 ; i += 3) {
976 for (int j = -6 ; j< 12 ; j += 3) {
977 if ((option->direction == Qt::LeftToRight && i > -j) || (option->direction == Qt::RightToLeft && j > i) ) {
978 painter->fillRect(x: rect.center().x() + i, y: rect.center().y() + j, w: 2, h: 2, b: d->lightShade());
979 painter->fillRect(x: rect.center().x() + i, y: rect.center().y() + j, w: 1, h: 1, b: d->darkShade());
980 }
981 }
982 }
983 }
984 painter->restore();
985 break;
986#if QT_CONFIG(toolbar)
987 case CE_ToolBar:
988 if (const QStyleOptionToolBar *toolBar = qstyleoption_cast<const QStyleOptionToolBar *>(opt: option)) {
989 // Reserve the beveled appearance only for mainwindow toolbars
990 if (widget && !(qobject_cast<const QMainWindow*> (object: widget->parentWidget())))
991 break;
992
993 // Draws the light line above and the dark line below menu bars and
994 // tool bars.
995 QLinearGradient gradient(option->rect.topLeft(), option->rect.bottomLeft());
996 if (!(option->state & State_Horizontal))
997 gradient = QLinearGradient(rect.left(), rect.center().y(),
998 rect.right(), rect.center().y());
999 gradient.setColorAt(pos: 0, color: option->palette.window().color().lighter(f: 104));
1000 gradient.setColorAt(pos: 1, color: option->palette.window().color());
1001 painter->fillRect(option->rect, gradient);
1002
1003 QColor light = d->lightShade();
1004 QColor shadow = d->darkShade();
1005
1006 QPen oldPen = painter->pen();
1007 if (toolBar->toolBarArea == Qt::TopToolBarArea) {
1008 if (toolBar->positionOfLine == QStyleOptionToolBar::End
1009 || toolBar->positionOfLine == QStyleOptionToolBar::OnlyOne) {
1010 // The end and onlyone top toolbar lines draw a double
1011 // line at the bottom to blend with the central
1012 // widget.
1013 painter->setPen(light);
1014 painter->drawLine(p1: option->rect.bottomLeft(), p2: option->rect.bottomRight());
1015 painter->setPen(shadow);
1016 painter->drawLine(x1: option->rect.left(), y1: option->rect.bottom() - 1,
1017 x2: option->rect.right(), y2: option->rect.bottom() - 1);
1018 } else {
1019 // All others draw a single dark line at the bottom.
1020 painter->setPen(shadow);
1021 painter->drawLine(p1: option->rect.bottomLeft(), p2: option->rect.bottomRight());
1022 }
1023 // All top toolbar lines draw a light line at the top.
1024 painter->setPen(light);
1025 painter->drawLine(p1: option->rect.topLeft(), p2: option->rect.topRight());
1026 } else if (toolBar->toolBarArea == Qt::BottomToolBarArea) {
1027 if (toolBar->positionOfLine == QStyleOptionToolBar::End
1028 || toolBar->positionOfLine == QStyleOptionToolBar::Middle) {
1029 // The end and middle bottom tool bar lines draw a dark
1030 // line at the bottom.
1031 painter->setPen(shadow);
1032 painter->drawLine(p1: option->rect.bottomLeft(), p2: option->rect.bottomRight());
1033 }
1034 if (toolBar->positionOfLine == QStyleOptionToolBar::Beginning
1035 || toolBar->positionOfLine == QStyleOptionToolBar::OnlyOne) {
1036 // The beginning and only one tool bar lines draw a
1037 // double line at the bottom to blend with the
1038 // status bar.
1039 // ### The styleoption could contain whether the
1040 // main window has a menu bar and a status bar, and
1041 // possibly dock widgets.
1042 painter->setPen(shadow);
1043 painter->drawLine(x1: option->rect.left(), y1: option->rect.bottom() - 1,
1044 x2: option->rect.right(), y2: option->rect.bottom() - 1);
1045 painter->setPen(light);
1046 painter->drawLine(p1: option->rect.bottomLeft(), p2: option->rect.bottomRight());
1047 }
1048 if (toolBar->positionOfLine == QStyleOptionToolBar::End) {
1049 painter->setPen(shadow);
1050 painter->drawLine(p1: option->rect.topLeft(), p2: option->rect.topRight());
1051 painter->setPen(light);
1052 painter->drawLine(x1: option->rect.left(), y1: option->rect.top() + 1,
1053 x2: option->rect.right(), y2: option->rect.top() + 1);
1054
1055 } else {
1056 // All other bottom toolbars draw a light line at the top.
1057 painter->setPen(light);
1058 painter->drawLine(p1: option->rect.topLeft(), p2: option->rect.topRight());
1059 }
1060 }
1061 if (toolBar->toolBarArea == Qt::LeftToolBarArea) {
1062 if (toolBar->positionOfLine == QStyleOptionToolBar::Middle
1063 || toolBar->positionOfLine == QStyleOptionToolBar::End) {
1064 // The middle and left end toolbar lines draw a light
1065 // line to the left.
1066 painter->setPen(light);
1067 painter->drawLine(p1: option->rect.topLeft(), p2: option->rect.bottomLeft());
1068 }
1069 if (toolBar->positionOfLine == QStyleOptionToolBar::End) {
1070 // All other left toolbar lines draw a dark line to the right
1071 painter->setPen(shadow);
1072 painter->drawLine(x1: option->rect.right() - 1, y1: option->rect.top(),
1073 x2: option->rect.right() - 1, y2: option->rect.bottom());
1074 painter->setPen(light);
1075 painter->drawLine(p1: option->rect.topRight(), p2: option->rect.bottomRight());
1076 } else {
1077 // All other left toolbar lines draw a dark line to the right
1078 painter->setPen(shadow);
1079 painter->drawLine(p1: option->rect.topRight(), p2: option->rect.bottomRight());
1080 }
1081 } else if (toolBar->toolBarArea == Qt::RightToolBarArea) {
1082 if (toolBar->positionOfLine == QStyleOptionToolBar::Middle
1083 || toolBar->positionOfLine == QStyleOptionToolBar::End) {
1084 // Right middle and end toolbar lines draw the dark right line
1085 painter->setPen(shadow);
1086 painter->drawLine(p1: option->rect.topRight(), p2: option->rect.bottomRight());
1087 }
1088 if (toolBar->positionOfLine == QStyleOptionToolBar::End
1089 || toolBar->positionOfLine == QStyleOptionToolBar::OnlyOne) {
1090 // The right end and single toolbar draws the dark
1091 // line on its left edge
1092 painter->setPen(shadow);
1093 painter->drawLine(p1: option->rect.topLeft(), p2: option->rect.bottomLeft());
1094 // And a light line next to it
1095 painter->setPen(light);
1096 painter->drawLine(x1: option->rect.left() + 1, y1: option->rect.top(),
1097 x2: option->rect.left() + 1, y2: option->rect.bottom());
1098 } else {
1099 // Other right toolbars draw a light line on its left edge
1100 painter->setPen(light);
1101 painter->drawLine(p1: option->rect.topLeft(), p2: option->rect.bottomLeft());
1102 }
1103 }
1104 painter->setPen(oldPen);
1105 }
1106 break;
1107#endif // QT_CONFIG(toolbar)
1108 case CE_DockWidgetTitle:
1109 painter->save();
1110 if (const QStyleOptionDockWidget *dwOpt = qstyleoption_cast<const QStyleOptionDockWidget *>(opt: option)) {
1111 bool verticalTitleBar = dwOpt->verticalTitleBar;
1112
1113 QRect titleRect = subElementRect(r: SE_DockWidgetTitleBarText, opt: option, widget);
1114 if (verticalTitleBar) {
1115 QRect rect = dwOpt->rect;
1116 QRect r = rect.transposed();
1117 titleRect = QRect(r.left() + rect.bottom()
1118 - titleRect.bottom(),
1119 r.top() + titleRect.left() - rect.left(),
1120 titleRect.height(), titleRect.width());
1121
1122 painter->translate(dx: r.left(), dy: r.top() + r.width());
1123 painter->rotate(a: -90);
1124 painter->translate(dx: -r.left(), dy: -r.top());
1125 }
1126
1127 if (!dwOpt->title.isEmpty()) {
1128 QString titleText
1129 = painter->fontMetrics().elidedText(text: dwOpt->title,
1130 mode: Qt::ElideRight, width: titleRect.width());
1131 proxy()->drawItemText(painter,
1132 rect: titleRect,
1133 flags: Qt::AlignLeft | Qt::AlignVCenter | Qt::TextHideMnemonic, pal: dwOpt->palette,
1134 enabled: dwOpt->state & State_Enabled, text: titleText,
1135 textRole: QPalette::WindowText);
1136 }
1137 }
1138 painter->restore();
1139 break;
1140 case CE_HeaderSection:
1141 painter->save();
1142 // Draws the header in tables.
1143 if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(opt: option)) {
1144 const QStyleOptionHeaderV2 *headerV2 = qstyleoption_cast<const QStyleOptionHeaderV2 *>(opt: option);
1145 const bool isSectionDragTarget = headerV2 ? headerV2->isSectionDragTarget : false;
1146 const qreal dpr = painter->device()->devicePixelRatio();
1147 const QString pixmapName = QStyleHelper::uniqueName(key: "headersection-"_L1
1148 % HexString(header->position)
1149 % HexString(header->orientation)
1150 % QLatin1Char(isSectionDragTarget ? '1' : '0'),
1151 option, size: option->rect.size(), dpr);
1152 QPixmap cache;
1153 if (!QPixmapCache::find(key: pixmapName, pixmap: &cache)) {
1154 cache = styleCachePixmap(size: rect.size(), pixelRatio: dpr);
1155 QRect pixmapRect(0, 0, rect.width(), rect.height());
1156 QPainter cachePainter(&cache);
1157 QColor buttonColor = d->buttonColor(pal: option->palette);
1158 QColor gradientStartColor = buttonColor.lighter(f: 104);
1159 QColor gradientStopColor = buttonColor.darker(f: 102);
1160 if (isSectionDragTarget) {
1161 gradientStopColor = gradientStartColor.darker(f: 130);
1162 gradientStartColor = gradientStartColor.darker(f: 130);
1163 }
1164 QLinearGradient gradient(pixmapRect.topLeft(), pixmapRect.bottomLeft());
1165
1166 if (option->palette.window().gradient()) {
1167 gradient.setStops(option->palette.window().gradient()->stops());
1168 } else {
1169 QColor midColor1 = mergedColors(colorA: gradientStartColor, colorB: gradientStopColor, factor: 60);
1170 QColor midColor2 = mergedColors(colorA: gradientStartColor, colorB: gradientStopColor, factor: 40);
1171 gradient.setColorAt(pos: 0, color: gradientStartColor);
1172 gradient.setColorAt(pos: 0.5, color: midColor1);
1173 gradient.setColorAt(pos: 0.501, color: midColor2);
1174 gradient.setColorAt(pos: 0.92, color: gradientStopColor);
1175 gradient.setColorAt(pos: 1, color: gradientStopColor.darker(f: 104));
1176 }
1177 cachePainter.fillRect(pixmapRect, gradient);
1178 cachePainter.setPen(d->innerContrastLine());
1179 cachePainter.setBrush(Qt::NoBrush);
1180 cachePainter.drawLine(p1: pixmapRect.topLeft(), p2: pixmapRect.topRight());
1181 cachePainter.setPen(d->outline(pal: option->palette));
1182 cachePainter.drawLine(p1: pixmapRect.bottomLeft(), p2: pixmapRect.bottomRight());
1183
1184 if (header->orientation == Qt::Horizontal &&
1185 header->position != QStyleOptionHeader::End &&
1186 header->position != QStyleOptionHeader::OnlyOneSection) {
1187 cachePainter.setPen(QColor(0, 0, 0, 40));
1188 cachePainter.drawLine(p1: pixmapRect.topRight(), p2: pixmapRect.bottomRight() + QPoint(0, -1));
1189 cachePainter.setPen(d->innerContrastLine());
1190 cachePainter.drawLine(p1: pixmapRect.topRight() + QPoint(-1, 0), p2: pixmapRect.bottomRight() + QPoint(-1, -1));
1191 } else if (header->orientation == Qt::Vertical) {
1192 cachePainter.setPen(d->outline(pal: option->palette));
1193 cachePainter.drawLine(p1: pixmapRect.topRight(), p2: pixmapRect.bottomRight());
1194 }
1195 cachePainter.end();
1196 QPixmapCache::insert(key: pixmapName, pixmap: cache);
1197 }
1198 painter->drawPixmap(p: rect.topLeft(), pm: cache);
1199 }
1200 painter->restore();
1201 break;
1202 case CE_ProgressBarGroove:
1203 painter->save();
1204 {
1205 painter->setRenderHint(hint: QPainter::Antialiasing, on: true);
1206 painter->translate(dx: 0.5, dy: 0.5);
1207
1208 QColor shadowAlpha = Qt::black;
1209 shadowAlpha.setAlpha(16);
1210 painter->setPen(shadowAlpha);
1211 painter->drawLine(p1: rect.topLeft() - QPoint(0, 1), p2: rect.topRight() - QPoint(0, 1));
1212
1213 painter->setBrush(option->palette.base());
1214 painter->setPen(QPen(outline));
1215 painter->drawRoundedRect(rect: rect.adjusted(xp1: 0, yp1: 0, xp2: -1, yp2: -1), xRadius: 2, yRadius: 2);
1216
1217 // Inner shadow
1218 painter->setPen(d->topShadow());
1219 painter->drawLine(p1: QPoint(rect.left() + 1, rect.top() + 1),
1220 p2: QPoint(rect.right() - 1, rect.top() + 1));
1221 }
1222 painter->restore();
1223 break;
1224 case CE_ProgressBarContents:
1225 painter->save();
1226 painter->setRenderHint(hint: QPainter::Antialiasing, on: true);
1227 if (const QStyleOptionProgressBar *bar = qstyleoption_cast<const QStyleOptionProgressBar *>(opt: option)) {
1228 painter->translate(offset: rect.topLeft());
1229 rect.translate(p: -rect.topLeft());
1230 const auto indeterminate = (bar->minimum == 0 && bar->maximum == 0);
1231 const auto complete = bar->progress == bar->maximum;
1232 const auto vertical = !(bar->state & QStyle::State_Horizontal);
1233 const auto inverted = bar->invertedAppearance;
1234 const auto reverse = (bar->direction == Qt::RightToLeft) ^ inverted;
1235
1236 // If the orientation is vertical, we use a transform to rotate
1237 // the progress bar 90 degrees (counter)clockwise. This way we can use the
1238 // same rendering code for both orientations.
1239 if (vertical) {
1240 rect = QRect(rect.left(), rect.top(), rect.height(), rect.width()); // flip width and height
1241 QTransform m;
1242 if (inverted) {
1243 m.rotate(a: 90);
1244 m.translate(dx: 0, dy: -rect.height());
1245 } else {
1246 m.rotate(a: -90);
1247 m.translate(dx: -rect.width(), dy: 0);
1248 }
1249 painter->setTransform(transform: m, combine: true);
1250 } else if (reverse) {
1251 QTransform m = QTransform::fromScale(dx: -1, dy: 1);
1252 m.translate(dx: -rect.width(), dy: 0);
1253 painter->setTransform(transform: m, combine: true);
1254 }
1255 painter->translate(dx: 0.5, dy: 0.5);
1256
1257 const auto progress = qMax(a: bar->progress, b: bar->minimum); // workaround for bug in QProgressBar
1258 const auto totalSteps = qMax(Q_INT64_C(1), b: qint64(bar->maximum) - bar->minimum);
1259 const auto progressSteps = qint64(progress) - bar->minimum;
1260 const auto progressBarWidth = progressSteps * rect.width() / totalSteps;
1261 int width = indeterminate ? rect.width() : progressBarWidth;
1262
1263 int step = 0;
1264 QRect progressBar;
1265 QColor highlight = d->highlight(pal: option->palette);
1266 QColor highlightedoutline = highlight.darker(f: 140);
1267 if (qGray(rgb: outline.rgb()) > qGray(rgb: highlightedoutline.rgb()))
1268 outline = highlightedoutline;
1269
1270 if (!indeterminate)
1271 progressBar.setRect(ax: rect.left(), ay: rect.top(), aw: width - 1, ah: rect.height() - 1);
1272 else
1273 progressBar.setRect(ax: rect.left(), ay: rect.top(), aw: rect.width() - 1, ah: rect.height() - 1);
1274
1275 if (indeterminate || bar->progress > bar->minimum) {
1276
1277 painter->setPen(QPen(outline));
1278
1279 QColor highlightedGradientStartColor = highlight.lighter(f: 120);
1280 QColor highlightedGradientStopColor = highlight;
1281 QLinearGradient gradient(rect.topLeft(), QPoint(rect.bottomLeft().x(), rect.bottomLeft().y()));
1282 gradient.setColorAt(pos: 0, color: highlightedGradientStartColor);
1283 gradient.setColorAt(pos: 1, color: highlightedGradientStopColor);
1284
1285 painter->setBrush(gradient);
1286
1287 painter->save();
1288 // 0.5 - half the width of a cosmetic pen (for vertical line below)
1289 if (!complete && !indeterminate)
1290 painter->setClipRect(QRectF(progressBar).adjusted(xp1: -1, yp1: -1, xp2: 0.5, yp2: 1));
1291
1292 QRect fillRect = progressBar;
1293 if (!indeterminate && !complete)
1294 fillRect.setWidth(std::min(a: fillRect.width() + 2, b: rect.width() - 1)); // avoid round borders at the right end
1295 painter->drawRoundedRect(rect: fillRect, xRadius: 2, yRadius: 2);
1296 painter->restore();
1297
1298 painter->setBrush(Qt::NoBrush);
1299 painter->setPen(QColor(255, 255, 255, 50));
1300 painter->drawRoundedRect(rect: progressBar.adjusted(xp1: 1, yp1: 1, xp2: -1, yp2: -1), xRadius: 1, yRadius: 1);
1301
1302 if (!indeterminate) {
1303#if QT_CONFIG(animation)
1304 (const_cast<QFusionStylePrivate*>(d))->stopAnimation(target: option->styleObject);
1305#endif
1306 } else {
1307 highlightedGradientStartColor.setAlpha(120);
1308 painter->setPen(QPen(highlightedGradientStartColor, 9.0));
1309 painter->setClipRect(progressBar.adjusted(xp1: 1, yp1: 1, xp2: -1, yp2: -1));
1310#if QT_CONFIG(animation)
1311 if (QProgressStyleAnimation *animation = qobject_cast<QProgressStyleAnimation*>(object: d->animation(target: option->styleObject)))
1312 step = animation->animationStep() % 22;
1313 else
1314 (const_cast<QFusionStylePrivate*>(d))->startAnimation(animation: new QProgressStyleAnimation(d->animationFps, option->styleObject));
1315#endif
1316 for (int x = progressBar.left() - rect.height(); x < rect.right() ; x += 22)
1317 painter->drawLine(x1: x + step, y1: progressBar.bottom() + 1,
1318 x2: x + rect.height() + step, y2: progressBar.top() - 2);
1319 }
1320 }
1321 if (!indeterminate && !complete) {
1322 QColor innerShadow(Qt::black);
1323 innerShadow.setAlpha(35);
1324 painter->setPen(innerShadow);
1325 painter->drawLine(p1: progressBar.topRight() + QPoint(2, 1), p2: progressBar.bottomRight() + QPoint(2, 0));
1326 painter->setPen(QPen(highlight.darker(f: 140)));
1327 painter->drawLine(p1: progressBar.topRight() + QPoint(1, 1), p2: progressBar.bottomRight() + QPoint(1, 0));
1328 }
1329 }
1330 painter->restore();
1331 break;
1332 case CE_ProgressBarLabel:
1333 if (const QStyleOptionProgressBar *bar = qstyleoption_cast<const QStyleOptionProgressBar *>(opt: option)) {
1334 QRect rect = bar->rect;
1335 QRect leftRect = rect;
1336 QRect rightRect = rect;
1337 QColor textColor = option->palette.text().color();
1338 QColor alternateTextColor = d->highlightedText(pal: option->palette);
1339
1340 painter->save();
1341 const auto vertical = !(bar->state & QStyle::State_Horizontal);
1342 const auto inverted = bar->invertedAppearance;
1343 const auto reverse = (bar->direction == Qt::RightToLeft) ^ inverted;
1344 const auto totalSteps = qMax(Q_INT64_C(1), b: qint64(bar->maximum) - bar->minimum);
1345 const auto progressSteps = qint64(bar->progress) - bar->minimum;
1346 const auto progressIndicatorPos = progressSteps * (vertical ? rect.height() : rect.width()) / totalSteps;
1347
1348 if (vertical) {
1349 if (progressIndicatorPos >= 0 && progressIndicatorPos <= rect.height()) {
1350 if (inverted) {
1351 leftRect.setHeight(progressIndicatorPos);
1352 rightRect.setY(progressIndicatorPos);
1353 } else {
1354 leftRect.setHeight(rect.height() - progressIndicatorPos);
1355 rightRect.setY(rect.height() - progressIndicatorPos);
1356 }
1357 }
1358 } else {
1359 if (progressIndicatorPos >= 0 && progressIndicatorPos <= rect.width()) {
1360 if (reverse) {
1361 leftRect.setWidth(rect.width() - progressIndicatorPos);
1362 rightRect.setX(rect.width() - progressIndicatorPos);
1363 } else {
1364 leftRect.setWidth(progressIndicatorPos);
1365 rightRect.setX(progressIndicatorPos);
1366 }
1367 }
1368 }
1369
1370 const auto firstIsAlternateColor = (vertical && !inverted) || (!vertical && reverse);
1371 painter->setClipRect(rightRect);
1372 painter->setPen(firstIsAlternateColor ? alternateTextColor : textColor);
1373 painter->drawText(r: rect, text: bar->text, o: QTextOption(Qt::AlignAbsolute | Qt::AlignHCenter | Qt::AlignVCenter));
1374 painter->setPen(firstIsAlternateColor ? textColor : alternateTextColor);
1375 painter->setClipRect(leftRect);
1376 painter->drawText(r: rect, text: bar->text, o: QTextOption(Qt::AlignAbsolute | Qt::AlignHCenter | Qt::AlignVCenter));
1377
1378 painter->restore();
1379 }
1380 break;
1381 case CE_MenuBarItem:
1382 painter->save();
1383 if (const QStyleOptionMenuItem *mbi = qstyleoption_cast<const QStyleOptionMenuItem *>(opt: option))
1384 {
1385 QStyleOptionMenuItem item = *mbi;
1386 item.rect = mbi->rect.adjusted(xp1: 0, yp1: 1, xp2: 0, yp2: -3);
1387 QColor highlightOutline = option->palette.highlight().color().darker(f: 125);
1388 painter->fillRect(rect, option->palette.window());
1389
1390 QCommonStyle::drawControl(element, opt: &item, p: painter, w: widget);
1391
1392 bool act = mbi->state & State_Selected && mbi->state & State_Sunken;
1393 bool dis = !(mbi->state & State_Enabled);
1394
1395 QRect r = option->rect;
1396 if (act) {
1397 painter->setBrush(option->palette.highlight().color());
1398 painter->setPen(QPen(highlightOutline));
1399 painter->drawRect(r: r.adjusted(xp1: 0, yp1: 0, xp2: -1, yp2: -1));
1400
1401 // painter->drawRoundedRect(r.adjusted(1, 1, -1, -1), 2, 2);
1402
1403 //draw text
1404 QPalette::ColorRole textRole = dis ? QPalette::Text : QPalette::HighlightedText;
1405 uint alignment = Qt::AlignCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine;
1406 if (!proxy()->styleHint(stylehint: SH_UnderlineShortcut, opt: mbi, widget))
1407 alignment |= Qt::TextHideMnemonic;
1408 proxy()->drawItemText(painter, rect: item.rect, flags: alignment, pal: mbi->palette, enabled: mbi->state & State_Enabled, text: mbi->text, textRole);
1409 } else {
1410
1411 QColor shadow = mergedColors(colorA: option->palette.window().color().darker(f: 120),
1412 colorB: outline.lighter(f: 140), factor: 60);
1413 painter->setPen(QPen(shadow));
1414 painter->drawLine(p1: option->rect.bottomLeft(), p2: option->rect.bottomRight());
1415 }
1416 }
1417 painter->restore();
1418 break;
1419 case CE_MenuItem:
1420 painter->save();
1421 // Draws one item in a popup menu.
1422 if (const QStyleOptionMenuItem *menuItem = qstyleoption_cast<const QStyleOptionMenuItem *>(opt: option)) {
1423 QColor highlightOutline = highlightedOutline;
1424 QColor highlight = option->palette.highlight().color();
1425 if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) {
1426 int w = 0;
1427 const int margin = int(QStyleHelper::dpiScaled(value: 5, option));
1428 if (!menuItem->text.isEmpty()) {
1429 painter->setFont(menuItem->font);
1430 proxy()->drawItemText(painter, rect: menuItem->rect.adjusted(xp1: margin, yp1: 0, xp2: -margin, yp2: 0),
1431 flags: Qt::AlignLeft | Qt::AlignVCenter,
1432 pal: menuItem->palette, enabled: menuItem->state & State_Enabled, text: menuItem->text,
1433 textRole: QPalette::Text);
1434 w = menuItem->fontMetrics.horizontalAdvance(menuItem->text) + margin;
1435 }
1436 painter->setPen(shadow.lighter(f: 106));
1437 const bool reverse = menuItem->direction == Qt::RightToLeft;
1438 qreal y = menuItem->rect.center().y() + 0.5f;
1439 painter->drawLine(p1: QPointF(menuItem->rect.left() + margin + (reverse ? 0 : w), y),
1440 p2: QPointF(menuItem->rect.right() - margin - (reverse ? w : 0), y));
1441 painter->restore();
1442 break;
1443 }
1444 const bool selected = menuItem->state & State_Selected && menuItem->state & State_Enabled;
1445 if (selected) {
1446 QRect r = option->rect;
1447 painter->fillRect(r, color: highlight);
1448 painter->setPen(QPen(highlightOutline));
1449 painter->drawRect(rect: QRectF(r).adjusted(xp1: 0.5, yp1: 0.5, xp2: -0.5, yp2: -0.5));
1450 }
1451 const bool checkable = menuItem->checkType != QStyleOptionMenuItem::NotCheckable;
1452 const bool checked = menuItem->checked;
1453 const bool sunken = menuItem->state & State_Sunken;
1454 const bool enabled = menuItem->state & State_Enabled;
1455
1456 const int checkColHOffset = QFusionStylePrivate::menuItemHMargin + windowsItemFrame - 1;
1457 // icon checkbox's highlight column width
1458 int checkcol = qMax<int>(a: menuItem->rect.height() * 0.79,
1459 b: qMax<int>(a: menuItem->maxIconWidth, b: dpiScaled(value: 21, option)));
1460 bool ignoreCheckMark = false;
1461#if QT_CONFIG(combobox)
1462 if (qobject_cast<const QComboBox*>(object: widget))
1463 ignoreCheckMark = true; //ignore the checkmarks provided by the QComboMenuDelegate
1464#endif
1465 if (!ignoreCheckMark || menuItem->state & (State_On | State_Off)) {
1466 // Check, using qreal and QRectF to avoid error accumulation
1467 const qreal boxMargin = dpiScaled(value: 3.5, option);
1468 const qreal boxWidth = checkcol - 2 * boxMargin;
1469 QRect checkRect = QRectF(option->rect.left() + boxMargin + checkColHOffset,
1470 option->rect.center().y() - boxWidth/2 + 1, boxWidth,
1471 boxWidth).toRect();
1472 checkRect.setWidth(checkRect.height()); // avoid .toRect() round error results in non-perfect square
1473 checkRect = visualRect(direction: menuItem->direction, boundingRect: menuItem->rect, logicalRect: checkRect);
1474 if (checkable) {
1475 if (menuItem->checkType & QStyleOptionMenuItem::Exclusive) {
1476 // Radio button
1477 if (menuItem->state & State_On || checked || sunken) {
1478 painter->setRenderHint(hint: QPainter::Antialiasing);
1479 painter->setPen(Qt::NoPen);
1480
1481 QPalette::ColorRole textRole = !enabled
1482 ? QPalette::Text :
1483 selected ? QPalette::HighlightedText
1484 : QPalette::ButtonText;
1485 painter->setBrush(option->palette.brush( cg: option->palette.currentColorGroup(), cr: textRole));
1486 const int adjustment = checkRect.height() * 0.3;
1487 painter->drawEllipse(r: checkRect.adjusted(xp1: adjustment, yp1: adjustment, xp2: -adjustment, yp2: -adjustment));
1488 }
1489 } else {
1490 // Check box
1491 if (menuItem->icon.isNull()) {
1492 QStyleOptionButton box;
1493 box.QStyleOption::operator=(other: *option);
1494 box.rect = checkRect;
1495 if (checked || menuItem->state & State_On)
1496 box.state |= State_On;
1497 else
1498 box.state |= State_Off;
1499 proxy()->drawPrimitive(pe: PE_IndicatorCheckBox, opt: &box, p: painter, w: widget);
1500 }
1501 }
1502 }
1503 } else { //ignore checkmark
1504 if (menuItem->icon.isNull())
1505 checkcol = 0;
1506 else
1507 checkcol = menuItem->maxIconWidth;
1508 }
1509
1510 // Text and icon, ripped from windows style
1511 const bool dis = !(menuItem->state & State_Enabled);
1512 const bool act = menuItem->state & State_Selected;
1513 const QStyleOption *opt = option;
1514 const QStyleOptionMenuItem *menuitem = menuItem;
1515
1516 QPainter *p = painter;
1517 QRect vCheckRect = visualRect(direction: opt->direction, boundingRect: menuitem->rect,
1518 logicalRect: QRect(menuitem->rect.x() + checkColHOffset, menuitem->rect.y(),
1519 checkcol, menuitem->rect.height()));
1520 if (!menuItem->icon.isNull()) {
1521 QIcon::Mode mode = dis ? QIcon::Disabled : QIcon::Normal;
1522 if (act && !dis)
1523 mode = QIcon::Active;
1524 QPixmap pixmap;
1525
1526 int smallIconSize = proxy()->pixelMetric(metric: PM_SmallIconSize, option, widget);
1527 QSize iconSize(smallIconSize, smallIconSize);
1528#if QT_CONFIG(combobox)
1529 if (const QComboBox *combo = qobject_cast<const QComboBox*>(object: widget))
1530 iconSize = combo->iconSize();
1531#endif
1532 if (checked)
1533 pixmap = menuItem->icon.pixmap(size: iconSize, devicePixelRatio: painter->device()->devicePixelRatio(), mode, state: QIcon::On);
1534 else
1535 pixmap = menuItem->icon.pixmap(size: iconSize, devicePixelRatio: painter->device()->devicePixelRatio(), mode);
1536
1537 QRect pmr(QPoint(0, 0), pixmap.deviceIndependentSize().toSize());
1538 pmr.moveCenter(p: vCheckRect.center());
1539 painter->setPen(menuItem->palette.text().color());
1540 if (!ignoreCheckMark && checkable && checked) {
1541 QStyleOption opt = *option;
1542 if (act) {
1543 QColor activeColor = mergedColors(colorA: option->palette.window().color(),
1544 colorB: option->palette.highlight().color());
1545 opt.palette.setBrush(acr: QPalette::Button, abrush: activeColor);
1546 }
1547 opt.state |= State_Sunken;
1548 opt.rect = vCheckRect;
1549 proxy()->drawPrimitive(pe: PE_PanelButtonCommand, opt: &opt, p: painter, w: widget);
1550 }
1551 painter->drawPixmap(p: pmr.topLeft(), pm: pixmap);
1552 }
1553 if (selected) {
1554 painter->setPen(menuItem->palette.highlightedText().color());
1555 } else {
1556 painter->setPen(menuItem->palette.text().color());
1557 }
1558 int x, y, w, h;
1559 menuitem->rect.getRect(ax: &x, ay: &y, aw: &w, ah: &h);
1560 QColor discol;
1561 if (dis) {
1562 discol = menuitem->palette.text().color();
1563 p->setPen(discol);
1564 }
1565 const int xm = checkColHOffset + checkcol + QFusionStylePrivate::menuItemHMargin;
1566 const int xpos = menuitem->rect.x() + xm;
1567
1568 const QRect textRect(xpos, y + windowsItemVMargin,
1569 w - xm - QFusionStylePrivate::menuRightBorder - menuitem->reservedShortcutWidth + 2,
1570 h - 2 * windowsItemVMargin);
1571 const QRect vTextRect = visualRect(direction: opt->direction, boundingRect: menuitem->rect, logicalRect: textRect);
1572 QStringView s(menuitem->text);
1573 if (!s.isEmpty()) { // draw text
1574 p->save();
1575 const qsizetype tabIndex = s.indexOf(c: u'\t');
1576 int text_flags = Qt::AlignVCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine;
1577 if (!proxy()->styleHint(stylehint: SH_UnderlineShortcut, opt: menuitem, widget))
1578 text_flags |= Qt::TextHideMnemonic;
1579 text_flags |= Qt::AlignLeft;
1580 if (tabIndex >= 0) {
1581 QRect vShortcutRect = visualRect(direction: opt->direction, boundingRect: menuitem->rect,
1582 logicalRect: QRect(textRect.topRight(),
1583 QPoint(menuitem->rect.right(), textRect.bottom())));
1584 const QString textToDraw = s.mid(pos: tabIndex + 1).toString();
1585 if (dis && !act && proxy()->styleHint(stylehint: SH_EtchDisabledText, opt: option, widget)) {
1586 p->setPen(menuitem->palette.light().color());
1587 p->drawText(r: vShortcutRect.adjusted(xp1: 1, yp1: 1, xp2: 1, yp2: 1), flags: text_flags, text: textToDraw);
1588 p->setPen(discol);
1589 }
1590 p->drawText(r: vShortcutRect, flags: text_flags, text: textToDraw);
1591 s = s.left(n: tabIndex);
1592 }
1593 QFont font = menuitem->font;
1594 // font may not have any "hard" flags set. We override
1595 // the point size so that when it is resolved against the device, this font will win.
1596 // This is mainly to handle cases where someone sets the font on the window
1597 // and then the combo inherits it and passes it onward. At that point the resolve mask
1598 // is very, very weak. This makes it stonger.
1599 font.setPointSizeF(QFontInfo(menuItem->font).pointSizeF());
1600
1601 if (menuitem->menuItemType == QStyleOptionMenuItem::DefaultItem)
1602 font.setBold(true);
1603
1604 p->setFont(font);
1605 const QFontMetrics fontMetrics(font);
1606 const QString textToDraw = fontMetrics.elidedText(text: s.left(n: tabIndex).toString(),
1607 mode: Qt::ElideMiddle, width: vTextRect.width(),
1608 flags: text_flags);
1609 if (dis && !act && proxy()->styleHint(stylehint: SH_EtchDisabledText, opt: option, widget)) {
1610 p->setPen(menuitem->palette.light().color());
1611 p->drawText(r: vTextRect.adjusted(xp1: 1, yp1: 1, xp2: 1, yp2: 1), flags: text_flags, text: textToDraw);
1612 p->setPen(discol);
1613 }
1614 p->drawText(r: vTextRect, flags: text_flags, text: textToDraw);
1615 p->restore();
1616 }
1617
1618 // Arrow
1619 if (menuItem->menuItemType == QStyleOptionMenuItem::SubMenu) {// draw sub menu arrow
1620 const int dim = (menuItem->rect.height() - 4) / 2;
1621 PrimitiveElement arrow;
1622 arrow = option->direction == Qt::RightToLeft ? PE_IndicatorArrowLeft : PE_IndicatorArrowRight;
1623 const int xpos = menuItem->rect.left() + menuItem->rect.width() - 3 - dim;
1624 QRect vSubMenuRect = visualRect(direction: option->direction, boundingRect: menuItem->rect,
1625 logicalRect: QRect(xpos, menuItem->rect.top() + menuItem->rect.height() / 2 - dim / 2, dim, dim));
1626 QStyleOptionMenuItem newMI = *menuItem;
1627 newMI.rect = vSubMenuRect;
1628 newMI.state = !enabled ? State_None : State_Enabled;
1629 if (selected)
1630 newMI.palette.setColor(acr: QPalette::WindowText,
1631 acolor: newMI.palette.highlightedText().color());
1632 proxy()->drawPrimitive(pe: arrow, opt: &newMI, p: painter, w: widget);
1633 }
1634 }
1635 painter->restore();
1636 break;
1637 case CE_MenuHMargin:
1638 case CE_MenuVMargin:
1639 break;
1640 case CE_MenuEmptyArea:
1641 break;
1642 case CE_PushButton:
1643 if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt: option)) {
1644 proxy()->drawControl(element: CE_PushButtonBevel, opt: btn, p: painter, w: widget);
1645 QStyleOptionButton subopt = *btn;
1646 subopt.rect = subElementRect(r: SE_PushButtonContents, opt: btn, widget);
1647 proxy()->drawControl(element: CE_PushButtonLabel, opt: &subopt, p: painter, w: widget);
1648 }
1649 break;
1650 case CE_MenuBarEmptyArea:
1651 painter->save();
1652 {
1653 painter->fillRect(rect, option->palette.window());
1654 QColor shadow = mergedColors(colorA: option->palette.window().color().darker(f: 120),
1655 colorB: outline.lighter(f: 140), factor: 60);
1656 painter->setPen(QPen(shadow));
1657 painter->drawLine(p1: option->rect.bottomLeft(), p2: option->rect.bottomRight());
1658 }
1659 painter->restore();
1660 break;
1661#if QT_CONFIG(tabbar)
1662 case CE_TabBarTabShape:
1663 painter->save();
1664 if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(opt: option)) {
1665
1666 bool rtlHorTabs = (tab->direction == Qt::RightToLeft
1667 && (tab->shape == QTabBar::RoundedNorth
1668 || tab->shape == QTabBar::RoundedSouth));
1669 bool selected = tab->state & State_Selected;
1670 bool lastTab = ((!rtlHorTabs && tab->position == QStyleOptionTab::End)
1671 || (rtlHorTabs
1672 && tab->position == QStyleOptionTab::Beginning));
1673 bool onlyOne = tab->position == QStyleOptionTab::OnlyOneTab;
1674 int tabOverlap = pixelMetric(metric: PM_TabBarTabOverlap, option, widget);
1675 QRect rect = option->rect.adjusted(xp1: 0, yp1: 0, xp2: (onlyOne || lastTab) ? 0 : tabOverlap, yp2: 0);
1676
1677 QTransform rotMatrix;
1678 bool flip = false;
1679 painter->setPen(shadow);
1680
1681 switch (tab->shape) {
1682 case QTabBar::RoundedNorth:
1683 break;
1684 case QTabBar::RoundedSouth:
1685 rotMatrix.rotate(a: 180);
1686 rotMatrix.translate(dx: 0, dy: -rect.height() + 1);
1687 rotMatrix.scale(sx: -1, sy: 1);
1688 painter->setTransform(transform: rotMatrix, combine: true);
1689 break;
1690 case QTabBar::RoundedWest:
1691 rotMatrix.rotate(a: 180 + 90);
1692 rotMatrix.scale(sx: -1, sy: 1);
1693 flip = true;
1694 painter->setTransform(transform: rotMatrix, combine: true);
1695 break;
1696 case QTabBar::RoundedEast:
1697 rotMatrix.rotate(a: 90);
1698 rotMatrix.translate(dx: 0, dy: - rect.width() + 1);
1699 flip = true;
1700 painter->setTransform(transform: rotMatrix, combine: true);
1701 break;
1702 default:
1703 painter->restore();
1704 QCommonStyle::drawControl(element, opt: tab, p: painter, w: widget);
1705 return;
1706 }
1707
1708 if (flip)
1709 rect = QRect(rect.y(), rect.x(), rect.height(), rect.width());
1710
1711 painter->setRenderHint(hint: QPainter::Antialiasing, on: true);
1712 painter->translate(dx: 0.5, dy: 0.5);
1713
1714 QColor tabFrameColor = tab->features & QStyleOptionTab::HasFrame ?
1715 d->tabFrameColor(pal: option->palette) :
1716 option->palette.window().color();
1717
1718 QLinearGradient fillGradient(rect.topLeft(), rect.bottomLeft());
1719 QLinearGradient outlineGradient(rect.topLeft(), rect.bottomLeft());
1720 QPen outlinePen = outline.lighter(f: 110);
1721 if (selected) {
1722 fillGradient.setColorAt(pos: 0, color: tabFrameColor.lighter(f: 104));
1723 // QColor highlight = option->palette.highlight().color();
1724 // if (option->state & State_HasFocus && option->state & State_KeyboardFocusChange) {
1725 // fillGradient.setColorAt(0, highlight.lighter(130));
1726 // outlineGradient.setColorAt(0, highlight.darker(130));
1727 // fillGradient.setColorAt(0.14, highlight);
1728 // outlineGradient.setColorAt(0.14, highlight.darker(130));
1729 // fillGradient.setColorAt(0.1401, tabFrameColor);
1730 // outlineGradient.setColorAt(0.1401, highlight.darker(130));
1731 // }
1732 fillGradient.setColorAt(pos: 1, color: tabFrameColor);
1733 outlineGradient.setColorAt(pos: 1, color: outline);
1734 outlinePen = QPen(outlineGradient, 1);
1735 } else {
1736 fillGradient.setColorAt(pos: 0, color: tabFrameColor.darker(f: 108));
1737 fillGradient.setColorAt(pos: 0.85, color: tabFrameColor.darker(f: 108));
1738 fillGradient.setColorAt(pos: 1, color: tabFrameColor.darker(f: 116));
1739 }
1740
1741 QRect drawRect = rect.adjusted(xp1: 0, yp1: selected ? 0 : 2, xp2: 0, yp2: 3);
1742 painter->setPen(outlinePen);
1743 painter->save();
1744 painter->setClipRect(rect.adjusted(xp1: -1, yp1: -1, xp2: 1, yp2: selected ? -2 : -3));
1745 painter->setBrush(fillGradient);
1746 painter->drawRoundedRect(rect: drawRect.adjusted(xp1: 0, yp1: 0, xp2: -1, yp2: -1), xRadius: 2.0, yRadius: 2.0);
1747 painter->setBrush(Qt::NoBrush);
1748 painter->setPen(d->innerContrastLine());
1749 painter->drawRoundedRect(rect: drawRect.adjusted(xp1: 1, yp1: 1, xp2: -2, yp2: -1), xRadius: 2.0, yRadius: 2.0);
1750 painter->restore();
1751
1752 if (selected) {
1753 painter->fillRect(x: rect.left() + 1, y: rect.bottom() - 1, w: rect.width() - 2, h: rect.bottom() - 1, b: tabFrameColor);
1754 painter->fillRect(QRect(rect.bottomRight() + QPoint(-2, -1), QSize(1, 1)), color: d->innerContrastLine());
1755 painter->fillRect(QRect(rect.bottomLeft() + QPoint(0, -1), QSize(1, 1)), color: d->innerContrastLine());
1756 painter->fillRect(QRect(rect.bottomRight() + QPoint(-1, -1), QSize(1, 1)), color: d->innerContrastLine());
1757 }
1758 }
1759 painter->restore();
1760 break;
1761#endif //QT_CONFIG(tabbar)
1762 default:
1763 QCommonStyle::drawControl(element,opt: option,p: painter,w: widget);
1764 break;
1765 }
1766}
1767
1768extern QPalette qt_fusionPalette();
1769
1770/*!
1771 \reimp
1772*/
1773QPalette QFusionStyle::standardPalette () const
1774{
1775 return qt_fusionPalette();
1776}
1777
1778/*!
1779 \reimp
1780*/
1781void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOptionComplex *option,
1782 QPainter *painter, const QWidget *widget) const
1783{
1784
1785 Q_D (const QFusionStyle);
1786
1787#if QT_CONFIG(spinbox) || QT_CONFIG(slider)
1788 QColor buttonColor = d->buttonColor(pal: option->palette);
1789 QColor gradientStopColor = buttonColor;
1790#endif
1791#if QT_CONFIG(slider)
1792 QColor gradientStartColor = buttonColor.lighter(f: 118);
1793#endif
1794 QColor outline = d->outline(pal: option->palette);
1795
1796 QColor alphaCornerColor;
1797 if (widget) {
1798 // ### backgroundrole/foregroundrole should be part of the style option
1799 alphaCornerColor = mergedColors(colorA: option->palette.color(cr: widget->backgroundRole()), colorB: outline);
1800 } else {
1801 alphaCornerColor = mergedColors(colorA: option->palette.window().color(), colorB: outline);
1802 }
1803
1804 switch (control) {
1805 case CC_GroupBox:
1806 painter->save();
1807 if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast<const QStyleOptionGroupBox *>(opt: option)) {
1808 // Draw frame
1809 QRect textRect = proxy()->subControlRect(cc: CC_GroupBox, opt: option, sc: SC_GroupBoxLabel, widget);
1810 QRect checkBoxRect = proxy()->subControlRect(cc: CC_GroupBox, opt: option, sc: SC_GroupBoxCheckBox, widget);
1811
1812 if (groupBox->subControls & QStyle::SC_GroupBoxFrame) {
1813 QStyleOptionFrame frame;
1814 frame.QStyleOption::operator=(other: *groupBox);
1815 frame.features = groupBox->features;
1816 frame.lineWidth = groupBox->lineWidth;
1817 frame.midLineWidth = groupBox->midLineWidth;
1818 frame.rect = proxy()->subControlRect(cc: CC_GroupBox, opt: option, sc: SC_GroupBoxFrame, widget);
1819 painter->save();
1820 QRegion region(groupBox->rect);
1821 if (!groupBox->text.isEmpty()) {
1822 bool ltr = groupBox->direction == Qt::LeftToRight;
1823 QRect finalRect;
1824 if (groupBox->subControls & QStyle::SC_GroupBoxCheckBox) {
1825 finalRect = checkBoxRect.united(r: textRect);
1826 finalRect.adjust(dx1: ltr ? -4 : -2, dy1: 0, dx2: ltr ? 2 : 4, dy2: 0);
1827 } else {
1828 finalRect = textRect;
1829 finalRect.adjust(dx1: -2, dy1: 0, dx2: 2, dy2: 0);
1830 }
1831 region -= finalRect.adjusted(xp1: 0, yp1: 0, xp2: 0, yp2: 3 - textRect.height() / 2);
1832 }
1833 painter->setClipRegion(region);
1834 proxy()->drawPrimitive(pe: PE_FrameGroupBox, opt: &frame, p: painter, w: widget);
1835 painter->restore();
1836 }
1837
1838 // Draw title
1839 if ((groupBox->subControls & QStyle::SC_GroupBoxLabel) && !groupBox->text.isEmpty()) {
1840 // groupBox->textColor gets the incorrect palette here
1841 painter->setPen(QPen(option->palette.windowText(), 1));
1842 int alignment = int(groupBox->textAlignment);
1843 if (!proxy()->styleHint(stylehint: QStyle::SH_UnderlineShortcut, opt: option, widget))
1844 alignment |= Qt::TextHideMnemonic;
1845
1846 proxy()->drawItemText(painter, rect: textRect, flags: Qt::TextShowMnemonic | Qt::AlignLeft | alignment,
1847 pal: groupBox->palette, enabled: groupBox->state & State_Enabled, text: groupBox->text, textRole: QPalette::NoRole);
1848
1849 if (groupBox->state & State_HasFocus) {
1850 QStyleOptionFocusRect fropt;
1851 fropt.QStyleOption::operator=(other: *groupBox);
1852 fropt.rect = textRect.adjusted(xp1: -2, yp1: -1, xp2: 2, yp2: 1);
1853 proxy()->drawPrimitive(pe: PE_FrameFocusRect, opt: &fropt, p: painter, w: widget);
1854 }
1855 }
1856
1857 // Draw checkbox
1858 if (groupBox->subControls & SC_GroupBoxCheckBox) {
1859 QStyleOptionButton box;
1860 box.QStyleOption::operator=(other: *groupBox);
1861 box.rect = checkBoxRect;
1862 proxy()->drawPrimitive(pe: PE_IndicatorCheckBox, opt: &box, p: painter, w: widget);
1863 }
1864 }
1865 painter->restore();
1866 break;
1867#if QT_CONFIG(spinbox)
1868 case CC_SpinBox:
1869 if (const QStyleOptionSpinBox *spinBox = qstyleoption_cast<const QStyleOptionSpinBox *>(opt: option)) {
1870 const qreal dpr = painter->device()->devicePixelRatio();
1871 QPixmap cache;
1872 QString pixmapName = QStyleHelper::uniqueName(key: "spinbox"_L1, option: spinBox, size: spinBox->rect.size(), dpr);
1873 if (!QPixmapCache::find(key: pixmapName, pixmap: &cache)) {
1874
1875 cache = styleCachePixmap(size: spinBox->rect.size(), pixelRatio: dpr);
1876
1877 QRect pixmapRect(0, 0, spinBox->rect.width(), spinBox->rect.height());
1878 QRect rect = pixmapRect;
1879 QRect r = rect.adjusted(xp1: 0, yp1: 1, xp2: 0, yp2: -1);
1880 QPainter cachePainter(&cache);
1881 QColor arrowColor = spinBox->palette.windowText().color();
1882 arrowColor.setAlpha(160);
1883
1884 bool isEnabled = (spinBox->state & State_Enabled);
1885 bool hover = isEnabled && (spinBox->state & State_MouseOver);
1886 bool sunken = (spinBox->state & State_Sunken);
1887 bool upIsActive = (spinBox->activeSubControls == SC_SpinBoxUp);
1888 bool downIsActive = (spinBox->activeSubControls == SC_SpinBoxDown);
1889 bool hasFocus = (option->state & State_HasFocus);
1890
1891 QStyleOptionSpinBox spinBoxCopy = *spinBox;
1892 spinBoxCopy.rect = pixmapRect;
1893 QRect upRect = proxy()->subControlRect(cc: CC_SpinBox, opt: &spinBoxCopy, sc: SC_SpinBoxUp, widget);
1894 QRect downRect = proxy()->subControlRect(cc: CC_SpinBox, opt: &spinBoxCopy, sc: SC_SpinBoxDown, widget);
1895
1896 if (spinBox->frame) {
1897 cachePainter.save();
1898 cachePainter.setRenderHint(hint: QPainter::Antialiasing, on: true);
1899 cachePainter.translate(dx: 0.5, dy: 0.5);
1900
1901 // Fill background
1902 cachePainter.setPen(Qt::NoPen);
1903 cachePainter.setBrush(option->palette.base());
1904 cachePainter.drawRoundedRect(rect: r.adjusted(xp1: 0, yp1: 0, xp2: -1, yp2: -1), xRadius: 2, yRadius: 2);
1905
1906 // Draw inner shadow
1907 cachePainter.setPen(d->topShadow());
1908 cachePainter.drawLine(p1: QPoint(r.left() + 2, r.top() + 1), p2: QPoint(r.right() - 2, r.top() + 1));
1909
1910 if (!upRect.isNull()) {
1911 // Draw button gradient
1912 const QColor buttonColor = d->buttonColor(pal: option->palette);
1913 const QRect updownRect = upRect.adjusted(xp1: 0, yp1: -2, xp2: 0, yp2: downRect.height() + 2);
1914 const QLinearGradient gradient = qt_fusion_gradient(rect: updownRect, baseColor: (isEnabled && option->state & State_MouseOver )
1915 ? buttonColor : buttonColor.darker(f: 104));
1916
1917 cachePainter.setPen(Qt::NoPen);
1918 cachePainter.setBrush(gradient);
1919
1920 cachePainter.save();
1921 cachePainter.setClipRect(updownRect);
1922 cachePainter.drawRoundedRect(rect: r.adjusted(xp1: 0, yp1: 0, xp2: -1, yp2: -1), xRadius: 2, yRadius: 2);
1923 cachePainter.setPen(QPen(d->innerContrastLine()));
1924 cachePainter.setBrush(Qt::NoBrush);
1925 cachePainter.drawRoundedRect(rect: r.adjusted(xp1: 1, yp1: 1, xp2: -2, yp2: -2), xRadius: 2, yRadius: 2);
1926 cachePainter.restore();
1927 }
1928
1929 if ((spinBox->stepEnabled & QAbstractSpinBox::StepUpEnabled) && upIsActive) {
1930 if (sunken)
1931 cachePainter.fillRect(upRect.adjusted(xp1: 0, yp1: -1, xp2: 0, yp2: 0), color: gradientStopColor.darker(f: 110));
1932 else if (hover)
1933 cachePainter.fillRect(upRect.adjusted(xp1: 0, yp1: -1, xp2: 0, yp2: 0), color: d->innerContrastLine());
1934 }
1935
1936 if ((spinBox->stepEnabled & QAbstractSpinBox::StepDownEnabled) && downIsActive) {
1937 if (sunken)
1938 cachePainter.fillRect(downRect.adjusted(xp1: 0, yp1: 0, xp2: 0, yp2: 1), color: gradientStopColor.darker(f: 110));
1939 else if (hover)
1940 cachePainter.fillRect(downRect.adjusted(xp1: 0, yp1: 0, xp2: 0, yp2: 1), color: d->innerContrastLine());
1941 }
1942
1943 cachePainter.setPen(hasFocus ? d->highlightedOutline(pal: option->palette) : outline);
1944 cachePainter.setBrush(Qt::NoBrush);
1945 cachePainter.drawRoundedRect(rect: r.adjusted(xp1: 0, yp1: 0, xp2: -1, yp2: -1), xRadius: 2, yRadius: 2);
1946 if (hasFocus) {
1947 QColor softHighlight = option->palette.highlight().color();
1948 softHighlight.setAlpha(40);
1949 cachePainter.setPen(softHighlight);
1950 cachePainter.drawRoundedRect(rect: r.adjusted(xp1: 1, yp1: 1, xp2: -2, yp2: -2), xRadius: 1.7, yRadius: 1.7);
1951 }
1952 cachePainter.restore();
1953 }
1954
1955 if (spinBox->buttonSymbols != QAbstractSpinBox::NoButtons) {
1956 // buttonSymbols == NoButtons results in 'null' rects
1957 // and a tiny rect painted in the corner.
1958 cachePainter.setPen(outline);
1959 if (spinBox->direction == Qt::RightToLeft)
1960 cachePainter.drawLine(l: QLineF(upRect.right(), upRect.top() - 0.5, upRect.right(), downRect.bottom() + 1.5));
1961 else
1962 cachePainter.drawLine(l: QLineF(upRect.left(), upRect.top() - 0.5, upRect.left(), downRect.bottom() + 1.5));
1963 }
1964
1965 if (upIsActive && sunken) {
1966 cachePainter.setPen(gradientStopColor.darker(f: 130));
1967 cachePainter.drawLine(x1: downRect.left() + 1, y1: downRect.top(), x2: downRect.right(), y2: downRect.top());
1968 cachePainter.drawLine(x1: upRect.left() + 1, y1: upRect.top(), x2: upRect.left() + 1, y2: upRect.bottom());
1969 cachePainter.drawLine(x1: upRect.left() + 1, y1: upRect.top() - 1, x2: upRect.right(), y2: upRect.top() - 1);
1970 }
1971
1972 if (downIsActive && sunken) {
1973 cachePainter.setPen(gradientStopColor.darker(f: 130));
1974 cachePainter.drawLine(x1: downRect.left() + 1, y1: downRect.top(), x2: downRect.left() + 1, y2: downRect.bottom() + 1);
1975 cachePainter.drawLine(x1: downRect.left() + 1, y1: downRect.top(), x2: downRect.right(), y2: downRect.top());
1976 cachePainter.setPen(gradientStopColor.darker(f: 110));
1977 cachePainter.drawLine(x1: downRect.left() + 1, y1: downRect.bottom() + 1, x2: downRect.right(), y2: downRect.bottom() + 1);
1978 }
1979
1980 QColor disabledColor = mergedColors(colorA: arrowColor, colorB: option->palette.button().color());
1981 if (spinBox->buttonSymbols == QAbstractSpinBox::PlusMinus) {
1982 int centerX = upRect.center().x();
1983 int centerY = upRect.center().y();
1984
1985 // plus/minus
1986 cachePainter.setPen((spinBox->stepEnabled & QAbstractSpinBox::StepUpEnabled) ? arrowColor : disabledColor);
1987 cachePainter.drawLine(x1: centerX - 1, y1: centerY, x2: centerX + 3, y2: centerY);
1988 cachePainter.drawLine(x1: centerX + 1, y1: centerY - 2, x2: centerX + 1, y2: centerY + 2);
1989
1990 centerX = downRect.center().x();
1991 centerY = downRect.center().y();
1992 cachePainter.setPen((spinBox->stepEnabled & QAbstractSpinBox::StepDownEnabled) ? arrowColor : disabledColor);
1993 cachePainter.drawLine(x1: centerX - 1, y1: centerY, x2: centerX + 3, y2: centerY);
1994
1995 } else if (spinBox->buttonSymbols == QAbstractSpinBox::UpDownArrows){
1996 // arrows
1997 qt_fusion_draw_arrow(type: Qt::UpArrow, painter: &cachePainter, option, rect: upRect.adjusted(xp1: 0, yp1: 0, xp2: 0, yp2: 1),
1998 color: (spinBox->stepEnabled & QAbstractSpinBox::StepUpEnabled) ? arrowColor : disabledColor);
1999 qt_fusion_draw_arrow(type: Qt::DownArrow, painter: &cachePainter, option, rect: downRect,
2000 color: (spinBox->stepEnabled & QAbstractSpinBox::StepDownEnabled) ? arrowColor : disabledColor);
2001 }
2002
2003 cachePainter.end();
2004 QPixmapCache::insert(key: pixmapName, pixmap: cache);
2005 }
2006 painter->drawPixmap(p: spinBox->rect.topLeft(), pm: cache);
2007 }
2008 break;
2009#endif // QT_CONFIG(spinbox)
2010 case CC_TitleBar:
2011 painter->save();
2012 if (const QStyleOptionTitleBar *titleBar = qstyleoption_cast<const QStyleOptionTitleBar *>(opt: option)) {
2013 const int buttonMargin = 5;
2014 bool active = (titleBar->titleBarState & State_Active);
2015 QRect fullRect = titleBar->rect;
2016 QPalette palette = option->palette;
2017 QColor highlight = option->palette.highlight().color();
2018
2019 QColor titleBarFrameBorder(active ? highlight.darker(f: 180): outline.darker(f: 110));
2020 QColor titleBarHighlight(active ? highlight.lighter(f: 120): palette.window().color().lighter(f: 120));
2021 QColor textColor(active ? 0xffffff : 0xff000000);
2022 QColor textAlphaColor(active ? 0xffffff : 0xff000000 );
2023
2024 {
2025 // Fill title bar gradient
2026 QColor titlebarColor = QColor(active ? highlight: palette.window().color());
2027 QLinearGradient gradient(option->rect.center().x(), option->rect.top(),
2028 option->rect.center().x(), option->rect.bottom());
2029
2030 gradient.setColorAt(pos: 0, color: titlebarColor.lighter(f: 114));
2031 gradient.setColorAt(pos: 0.5, color: titlebarColor.lighter(f: 102));
2032 gradient.setColorAt(pos: 0.51, color: titlebarColor.darker(f: 104));
2033 gradient.setColorAt(pos: 1, color: titlebarColor);
2034 painter->fillRect(option->rect.adjusted(xp1: 1, yp1: 1, xp2: -1, yp2: 0), gradient);
2035
2036 // Frame and rounded corners
2037 painter->setPen(titleBarFrameBorder);
2038
2039 // top outline
2040 painter->drawLine(x1: fullRect.left() + 5, y1: fullRect.top(), x2: fullRect.right() - 5, y2: fullRect.top());
2041 painter->drawLine(x1: fullRect.left(), y1: fullRect.top() + 4, x2: fullRect.left(), y2: fullRect.bottom());
2042 const QPoint points[5] = {
2043 QPoint(fullRect.left() + 4, fullRect.top() + 1),
2044 QPoint(fullRect.left() + 3, fullRect.top() + 1),
2045 QPoint(fullRect.left() + 2, fullRect.top() + 2),
2046 QPoint(fullRect.left() + 1, fullRect.top() + 3),
2047 QPoint(fullRect.left() + 1, fullRect.top() + 4)
2048 };
2049 painter->drawPoints(points, pointCount: 5);
2050
2051 painter->drawLine(x1: fullRect.right(), y1: fullRect.top() + 4, x2: fullRect.right(), y2: fullRect.bottom());
2052 const QPoint points2[5] = {
2053 QPoint(fullRect.right() - 3, fullRect.top() + 1),
2054 QPoint(fullRect.right() - 4, fullRect.top() + 1),
2055 QPoint(fullRect.right() - 2, fullRect.top() + 2),
2056 QPoint(fullRect.right() - 1, fullRect.top() + 3),
2057 QPoint(fullRect.right() - 1, fullRect.top() + 4)
2058 };
2059 painter->drawPoints(points: points2, pointCount: 5);
2060
2061 // draw bottomline
2062 painter->drawLine(x1: fullRect.right(), y1: fullRect.bottom(), x2: fullRect.left(), y2: fullRect.bottom());
2063
2064 // top highlight
2065 painter->setPen(titleBarHighlight);
2066 painter->drawLine(x1: fullRect.left() + 6, y1: fullRect.top() + 1, x2: fullRect.right() - 6, y2: fullRect.top() + 1);
2067 }
2068 // draw title
2069 QRect textRect = proxy()->subControlRect(cc: CC_TitleBar, opt: titleBar, sc: SC_TitleBarLabel, widget);
2070 painter->setPen(active? (titleBar->palette.text().color().lighter(f: 120)) :
2071 titleBar->palette.text().color() );
2072 // Note workspace also does elliding but it does not use the correct font
2073 QString title = painter->fontMetrics().elidedText(text: titleBar->text, mode: Qt::ElideRight, width: textRect.width() - 14);
2074 painter->drawText(r: textRect.adjusted(xp1: 1, yp1: 1, xp2: 1, yp2: 1), text: title, o: QTextOption(Qt::AlignHCenter | Qt::AlignVCenter));
2075 painter->setPen(Qt::white);
2076 if (active)
2077 painter->drawText(r: textRect, text: title, o: QTextOption(Qt::AlignHCenter | Qt::AlignVCenter));
2078 // min button
2079 if ((titleBar->subControls & SC_TitleBarMinButton) && (titleBar->titleBarFlags & Qt::WindowMinimizeButtonHint) &&
2080 !(titleBar->titleBarState& Qt::WindowMinimized)) {
2081 QRect minButtonRect = proxy()->subControlRect(cc: CC_TitleBar, opt: titleBar, sc: SC_TitleBarMinButton, widget);
2082 if (minButtonRect.isValid()) {
2083 bool hover = (titleBar->activeSubControls & SC_TitleBarMinButton) && (titleBar->state & State_MouseOver);
2084 bool sunken = (titleBar->activeSubControls & SC_TitleBarMinButton) && (titleBar->state & State_Sunken);
2085 qt_fusion_draw_mdibutton(painter, option: titleBar, tmp: minButtonRect, hover, sunken);
2086 QRect minButtonIconRect = minButtonRect.adjusted(xp1: buttonMargin ,yp1: buttonMargin , xp2: -buttonMargin, yp2: -buttonMargin);
2087 painter->setPen(textColor);
2088 painter->drawLine(x1: minButtonIconRect.center().x() - 2, y1: minButtonIconRect.center().y() + 3,
2089 x2: minButtonIconRect.center().x() + 3, y2: minButtonIconRect.center().y() + 3);
2090 painter->drawLine(x1: minButtonIconRect.center().x() - 2, y1: minButtonIconRect.center().y() + 4,
2091 x2: minButtonIconRect.center().x() + 3, y2: minButtonIconRect.center().y() + 4);
2092 painter->setPen(textAlphaColor);
2093 painter->drawLine(x1: minButtonIconRect.center().x() - 3, y1: minButtonIconRect.center().y() + 3,
2094 x2: minButtonIconRect.center().x() - 3, y2: minButtonIconRect.center().y() + 4);
2095 painter->drawLine(x1: minButtonIconRect.center().x() + 4, y1: minButtonIconRect.center().y() + 3,
2096 x2: minButtonIconRect.center().x() + 4, y2: minButtonIconRect.center().y() + 4);
2097 }
2098 }
2099 // max button
2100 if ((titleBar->subControls & SC_TitleBarMaxButton) && (titleBar->titleBarFlags & Qt::WindowMaximizeButtonHint) &&
2101 !(titleBar->titleBarState & Qt::WindowMaximized)) {
2102 QRect maxButtonRect = proxy()->subControlRect(cc: CC_TitleBar, opt: titleBar, sc: SC_TitleBarMaxButton, widget);
2103 if (maxButtonRect.isValid()) {
2104 bool hover = (titleBar->activeSubControls & SC_TitleBarMaxButton) && (titleBar->state & State_MouseOver);
2105 bool sunken = (titleBar->activeSubControls & SC_TitleBarMaxButton) && (titleBar->state & State_Sunken);
2106 qt_fusion_draw_mdibutton(painter, option: titleBar, tmp: maxButtonRect, hover, sunken);
2107
2108 QRect maxButtonIconRect = maxButtonRect.adjusted(xp1: buttonMargin, yp1: buttonMargin, xp2: -buttonMargin, yp2: -buttonMargin);
2109
2110 painter->setPen(textColor);
2111 painter->drawRect(r: maxButtonIconRect.adjusted(xp1: 0, yp1: 0, xp2: -1, yp2: -1));
2112 painter->drawLine(x1: maxButtonIconRect.left() + 1, y1: maxButtonIconRect.top() + 1,
2113 x2: maxButtonIconRect.right() - 1, y2: maxButtonIconRect.top() + 1);
2114 painter->setPen(textAlphaColor);
2115 const QPoint points[4] = {
2116 maxButtonIconRect.topLeft(),
2117 maxButtonIconRect.topRight(),
2118 maxButtonIconRect.bottomLeft(),
2119 maxButtonIconRect.bottomRight()
2120 };
2121 painter->drawPoints(points, pointCount: 4);
2122 }
2123 }
2124
2125 // close button
2126 if ((titleBar->subControls & SC_TitleBarCloseButton) && (titleBar->titleBarFlags & Qt::WindowSystemMenuHint)) {
2127 QRect closeButtonRect = proxy()->subControlRect(cc: CC_TitleBar, opt: titleBar, sc: SC_TitleBarCloseButton, widget);
2128 if (closeButtonRect.isValid()) {
2129 bool hover = (titleBar->activeSubControls & SC_TitleBarCloseButton) && (titleBar->state & State_MouseOver);
2130 bool sunken = (titleBar->activeSubControls & SC_TitleBarCloseButton) && (titleBar->state & State_Sunken);
2131 qt_fusion_draw_mdibutton(painter, option: titleBar, tmp: closeButtonRect, hover, sunken);
2132 QRect closeIconRect = closeButtonRect.adjusted(xp1: buttonMargin, yp1: buttonMargin, xp2: -buttonMargin, yp2: -buttonMargin);
2133 painter->setPen(textAlphaColor);
2134 const QLine lines[4] = {
2135 QLine(closeIconRect.left() + 1, closeIconRect.top(),
2136 closeIconRect.right(), closeIconRect.bottom() - 1),
2137 QLine(closeIconRect.left(), closeIconRect.top() + 1,
2138 closeIconRect.right() - 1, closeIconRect.bottom()),
2139 QLine(closeIconRect.right() - 1, closeIconRect.top(),
2140 closeIconRect.left(), closeIconRect.bottom() - 1),
2141 QLine(closeIconRect.right(), closeIconRect.top() + 1,
2142 closeIconRect.left() + 1, closeIconRect.bottom())
2143 };
2144 painter->drawLines(lines, lineCount: 4);
2145 const QPoint points[4] = {
2146 closeIconRect.topLeft(),
2147 closeIconRect.topRight(),
2148 closeIconRect.bottomLeft(),
2149 closeIconRect.bottomRight()
2150 };
2151 painter->drawPoints(points, pointCount: 4);
2152
2153 painter->setPen(textColor);
2154 painter->drawLine(x1: closeIconRect.left() + 1, y1: closeIconRect.top() + 1,
2155 x2: closeIconRect.right() - 1, y2: closeIconRect.bottom() - 1);
2156 painter->drawLine(x1: closeIconRect.left() + 1, y1: closeIconRect.bottom() - 1,
2157 x2: closeIconRect.right() - 1, y2: closeIconRect.top() + 1);
2158 }
2159 }
2160
2161 // normalize button
2162 if ((titleBar->subControls & SC_TitleBarNormalButton) &&
2163 (((titleBar->titleBarFlags & Qt::WindowMinimizeButtonHint) &&
2164 (titleBar->titleBarState & Qt::WindowMinimized)) ||
2165 ((titleBar->titleBarFlags & Qt::WindowMaximizeButtonHint) &&
2166 (titleBar->titleBarState & Qt::WindowMaximized)))) {
2167 QRect normalButtonRect = proxy()->subControlRect(cc: CC_TitleBar, opt: titleBar, sc: SC_TitleBarNormalButton, widget);
2168 if (normalButtonRect.isValid()) {
2169
2170 bool hover = (titleBar->activeSubControls & SC_TitleBarNormalButton) && (titleBar->state & State_MouseOver);
2171 bool sunken = (titleBar->activeSubControls & SC_TitleBarNormalButton) && (titleBar->state & State_Sunken);
2172 QRect normalButtonIconRect = normalButtonRect.adjusted(xp1: buttonMargin, yp1: buttonMargin, xp2: -buttonMargin, yp2: -buttonMargin);
2173 qt_fusion_draw_mdibutton(painter, option: titleBar, tmp: normalButtonRect, hover, sunken);
2174
2175 QRect frontWindowRect = normalButtonIconRect.adjusted(xp1: 0, yp1: 3, xp2: -3, yp2: 0);
2176 painter->setPen(textColor);
2177 painter->drawRect(r: frontWindowRect.adjusted(xp1: 0, yp1: 0, xp2: -1, yp2: -1));
2178 painter->drawLine(x1: frontWindowRect.left() + 1, y1: frontWindowRect.top() + 1,
2179 x2: frontWindowRect.right() - 1, y2: frontWindowRect.top() + 1);
2180 painter->setPen(textAlphaColor);
2181 const QPoint points[4] = {
2182 frontWindowRect.topLeft(),
2183 frontWindowRect.topRight(),
2184 frontWindowRect.bottomLeft(),
2185 frontWindowRect.bottomRight()
2186 };
2187 painter->drawPoints(points, pointCount: 4);
2188
2189 QRect backWindowRect = normalButtonIconRect.adjusted(xp1: 3, yp1: 0, xp2: 0, yp2: -3);
2190 QRegion clipRegion = backWindowRect;
2191 clipRegion -= frontWindowRect;
2192 painter->save();
2193 painter->setClipRegion(clipRegion);
2194 painter->setPen(textColor);
2195 painter->drawRect(r: backWindowRect.adjusted(xp1: 0, yp1: 0, xp2: -1, yp2: -1));
2196 painter->drawLine(x1: backWindowRect.left() + 1, y1: backWindowRect.top() + 1,
2197 x2: backWindowRect.right() - 1, y2: backWindowRect.top() + 1);
2198 painter->setPen(textAlphaColor);
2199 const QPoint points2[4] = {
2200 backWindowRect.topLeft(),
2201 backWindowRect.topRight(),
2202 backWindowRect.bottomLeft(),
2203 backWindowRect.bottomRight()
2204 };
2205 painter->drawPoints(points: points2, pointCount: 4);
2206 painter->restore();
2207 }
2208 }
2209
2210 // context help button
2211 if (titleBar->subControls & SC_TitleBarContextHelpButton
2212 && (titleBar->titleBarFlags & Qt::WindowContextHelpButtonHint)) {
2213 QRect contextHelpButtonRect = proxy()->subControlRect(cc: CC_TitleBar, opt: titleBar, sc: SC_TitleBarContextHelpButton, widget);
2214 if (contextHelpButtonRect.isValid()) {
2215 bool hover = (titleBar->activeSubControls & SC_TitleBarContextHelpButton) && (titleBar->state & State_MouseOver);
2216 bool sunken = (titleBar->activeSubControls & SC_TitleBarContextHelpButton) && (titleBar->state & State_Sunken);
2217 qt_fusion_draw_mdibutton(painter, option: titleBar, tmp: contextHelpButtonRect, hover, sunken);
2218#if QT_CONFIG(imageformat_xpm)
2219 QImage image(qt_titlebar_context_help);
2220 QColor alpha = textColor;
2221 alpha.setAlpha(128);
2222 image.setColor(i: 1, c: textColor.rgba());
2223 image.setColor(i: 2, c: alpha.rgba());
2224 painter->setRenderHint(hint: QPainter::SmoothPixmapTransform);
2225 painter->drawImage(r: contextHelpButtonRect.adjusted(xp1: 4, yp1: 4, xp2: -4, yp2: -4), image);
2226#endif
2227 }
2228 }
2229
2230 // shade button
2231 if (titleBar->subControls & SC_TitleBarShadeButton && (titleBar->titleBarFlags & Qt::WindowShadeButtonHint)) {
2232 QRect shadeButtonRect = proxy()->subControlRect(cc: CC_TitleBar, opt: titleBar, sc: SC_TitleBarShadeButton, widget);
2233 if (shadeButtonRect.isValid()) {
2234 bool hover = (titleBar->activeSubControls & SC_TitleBarShadeButton) && (titleBar->state & State_MouseOver);
2235 bool sunken = (titleBar->activeSubControls & SC_TitleBarShadeButton) && (titleBar->state & State_Sunken);
2236 qt_fusion_draw_mdibutton(painter, option: titleBar, tmp: shadeButtonRect, hover, sunken);
2237 qt_fusion_draw_arrow(type: Qt::UpArrow, painter, option, rect: shadeButtonRect.adjusted(xp1: 5, yp1: 7, xp2: -5, yp2: -7), color: textColor);
2238 }
2239 }
2240
2241 // unshade button
2242 if (titleBar->subControls & SC_TitleBarUnshadeButton && (titleBar->titleBarFlags & Qt::WindowShadeButtonHint)) {
2243 QRect unshadeButtonRect = proxy()->subControlRect(cc: CC_TitleBar, opt: titleBar, sc: SC_TitleBarUnshadeButton, widget);
2244 if (unshadeButtonRect.isValid()) {
2245 bool hover = (titleBar->activeSubControls & SC_TitleBarUnshadeButton) && (titleBar->state & State_MouseOver);
2246 bool sunken = (titleBar->activeSubControls & SC_TitleBarUnshadeButton) && (titleBar->state & State_Sunken);
2247 qt_fusion_draw_mdibutton(painter, option: titleBar, tmp: unshadeButtonRect, hover, sunken);
2248 qt_fusion_draw_arrow(type: Qt::DownArrow, painter, option, rect: unshadeButtonRect.adjusted(xp1: 5, yp1: 7, xp2: -5, yp2: -7), color: textColor);
2249 }
2250 }
2251
2252 if ((titleBar->subControls & SC_TitleBarSysMenu) && (titleBar->titleBarFlags & Qt::WindowSystemMenuHint)) {
2253 QRect iconRect = proxy()->subControlRect(cc: CC_TitleBar, opt: titleBar, sc: SC_TitleBarSysMenu, widget);
2254 if (iconRect.isValid()) {
2255 if (!titleBar->icon.isNull()) {
2256 titleBar->icon.paint(painter, rect: iconRect);
2257 } else {
2258 QStyleOption tool = *titleBar;
2259 QPixmap pm = proxy()->standardIcon(standardIcon: SP_TitleBarMenuButton, option: &tool, widget).pixmap(w: 16, h: 16);
2260 tool.rect = iconRect;
2261 painter->save();
2262 proxy()->drawItemPixmap(painter, rect: iconRect, alignment: Qt::AlignCenter, pixmap: pm);
2263 painter->restore();
2264 }
2265 }
2266 }
2267 }
2268 painter->restore();
2269 break;
2270#if QT_CONFIG(slider)
2271 case CC_ScrollBar:
2272 painter->save();
2273 if (const QStyleOptionSlider *scrollBar = qstyleoption_cast<const QStyleOptionSlider *>(opt: option)) {
2274 bool wasActive = false;
2275 qreal expandScale = 1.0;
2276 qreal expandOffset = -1.0;
2277 QObject *styleObject = option->styleObject;
2278 if (styleObject && proxy()->styleHint(stylehint: SH_ScrollBar_Transient, opt: option, widget)) {
2279#if QT_CONFIG(animation)
2280 qreal opacity = 0.0;
2281 bool shouldExpand = false;
2282 const qreal maxExpandScale = 13.0 / 9.0;
2283#endif
2284
2285 int oldPos = styleObject->property(name: "_q_stylepos").toInt();
2286 int oldMin = styleObject->property(name: "_q_stylemin").toInt();
2287 int oldMax = styleObject->property(name: "_q_stylemax").toInt();
2288 QRect oldRect = styleObject->property(name: "_q_stylerect").toRect();
2289 QStyle::State oldState = static_cast<QStyle::State>(qvariant_cast<QStyle::State::Int>(v: styleObject->property(name: "_q_stylestate")));
2290 uint oldActiveControls = styleObject->property(name: "_q_stylecontrols").toUInt();
2291
2292 // a scrollbar is transient when the scrollbar itself and
2293 // its sibling are both inactive (ie. not pressed/hovered/moved)
2294 bool transient = !option->activeSubControls && !(option->state & State_On);
2295
2296 if (!transient ||
2297 oldPos != scrollBar->sliderPosition ||
2298 oldMin != scrollBar->minimum ||
2299 oldMax != scrollBar->maximum ||
2300 oldRect != scrollBar->rect ||
2301 oldState != scrollBar->state ||
2302 oldActiveControls != scrollBar->activeSubControls) {
2303
2304 styleObject->setProperty(name: "_q_stylepos", value: scrollBar->sliderPosition);
2305 styleObject->setProperty(name: "_q_stylemin", value: scrollBar->minimum);
2306 styleObject->setProperty(name: "_q_stylemax", value: scrollBar->maximum);
2307 styleObject->setProperty(name: "_q_stylerect", value: scrollBar->rect);
2308 styleObject->setProperty(name: "_q_stylestate", value: static_cast<QStyle::State::Int>(scrollBar->state));
2309 styleObject->setProperty(name: "_q_stylecontrols", value: static_cast<uint>(scrollBar->activeSubControls));
2310
2311#if QT_CONFIG(animation)
2312 // if the scrollbar is transient or its attributes, geometry or
2313 // state has changed, the opacity is reset back to 100% opaque
2314 opacity = 1.0;
2315
2316 QScrollbarStyleAnimation *anim = qobject_cast<QScrollbarStyleAnimation *>(object: d->animation(target: styleObject));
2317 if (transient) {
2318 if (!anim) {
2319 anim = new QScrollbarStyleAnimation(QScrollbarStyleAnimation::Deactivating, styleObject);
2320 d->startAnimation(animation: anim);
2321 } else if (anim->mode() == QScrollbarStyleAnimation::Deactivating) {
2322 // the scrollbar was already fading out while the
2323 // state changed -> restart the fade out animation
2324 anim->setCurrentTime(0);
2325 }
2326 } else if (anim && anim->mode() == QScrollbarStyleAnimation::Deactivating) {
2327 d->stopAnimation(target: styleObject);
2328 }
2329#endif // animation
2330 }
2331
2332#if QT_CONFIG(animation)
2333 QScrollbarStyleAnimation *anim = qobject_cast<QScrollbarStyleAnimation *>(object: d->animation(target: styleObject));
2334 if (anim && anim->mode() == QScrollbarStyleAnimation::Deactivating) {
2335 // once a scrollbar was active (hovered/pressed), it retains
2336 // the active look even if it's no longer active while fading out
2337 if (oldActiveControls)
2338 anim->setActive(true);
2339
2340 wasActive = anim->wasActive();
2341 opacity = anim->currentValue();
2342 }
2343
2344 shouldExpand = (option->activeSubControls || wasActive);
2345 if (shouldExpand) {
2346 if (!anim && !oldActiveControls) {
2347 // Start expand animation only once and when entering
2348 anim = new QScrollbarStyleAnimation(QScrollbarStyleAnimation::Activating, styleObject);
2349 d->startAnimation(animation: anim);
2350 }
2351 if (anim && anim->mode() == QScrollbarStyleAnimation::Activating) {
2352 expandScale = 1.0 + (maxExpandScale - 1.0) * anim->currentValue();
2353 expandOffset = 5.5 * anim->currentValue() - 1;
2354 } else {
2355 // Keep expanded state after the animation ends, and when fading out
2356 expandScale = maxExpandScale;
2357 expandOffset = 4.5;
2358 }
2359 }
2360 painter->setOpacity(opacity);
2361#endif // animation
2362 }
2363
2364 bool transient = proxy()->styleHint(stylehint: SH_ScrollBar_Transient, opt: option, widget);
2365 bool horizontal = scrollBar->orientation == Qt::Horizontal;
2366 bool sunken = scrollBar->state & State_Sunken;
2367
2368 QRect scrollBarSubLine = proxy()->subControlRect(cc: control, opt: scrollBar, sc: SC_ScrollBarSubLine, widget);
2369 QRect scrollBarAddLine = proxy()->subControlRect(cc: control, opt: scrollBar, sc: SC_ScrollBarAddLine, widget);
2370 QRect scrollBarSlider = proxy()->subControlRect(cc: control, opt: scrollBar, sc: SC_ScrollBarSlider, widget);
2371 QRect scrollBarGroove = proxy()->subControlRect(cc: control, opt: scrollBar, sc: SC_ScrollBarGroove, widget);
2372
2373 QRect rect = option->rect;
2374 QColor alphaOutline = outline;
2375 alphaOutline.setAlpha(180);
2376
2377 QColor arrowColor = option->palette.windowText().color();
2378 arrowColor.setAlpha(160);
2379
2380 const QColor bgColor = QStyleHelper::backgroundColor(pal: option->palette, widget);
2381 const bool isDarkBg = bgColor.red() < 128 && bgColor.green() < 128 && bgColor.blue() < 128;
2382
2383 if (transient) {
2384 if (horizontal) {
2385 rect.setY(rect.y() + 4.5 - expandOffset);
2386 scrollBarSlider.setY(scrollBarSlider.y() + 4.5 - expandOffset);
2387 scrollBarGroove.setY(scrollBarGroove.y() + 4.5 - expandOffset);
2388
2389 rect.setHeight(rect.height() * expandScale);
2390 scrollBarGroove.setHeight(scrollBarGroove.height() * expandScale);
2391 } else {
2392 rect.setX(rect.x() + 4.5 - expandOffset);
2393 scrollBarSlider.setX(scrollBarSlider.x() + 4.5 - expandOffset);
2394 scrollBarGroove.setX(scrollBarGroove.x() + 4.5 - expandOffset);
2395
2396 rect.setWidth(rect.width() * expandScale);
2397 scrollBarGroove.setWidth(scrollBarGroove.width() * expandScale);
2398 }
2399 }
2400
2401 // Paint groove
2402 if ((!transient || scrollBar->activeSubControls || wasActive) && scrollBar->subControls & SC_ScrollBarGroove) {
2403 QLinearGradient gradient(rect.center().x(), rect.top(),
2404 rect.center().x(), rect.bottom());
2405 if (!horizontal)
2406 gradient = QLinearGradient(rect.left(), rect.center().y(),
2407 rect.right(), rect.center().y());
2408 if (!transient || !isDarkBg) {
2409 gradient.setColorAt(pos: 0, color: buttonColor.darker(f: 107));
2410 gradient.setColorAt(pos: 0.1, color: buttonColor.darker(f: 105));
2411 gradient.setColorAt(pos: 0.9, color: buttonColor.darker(f: 105));
2412 gradient.setColorAt(pos: 1, color: buttonColor.darker(f: 107));
2413 } else {
2414 gradient.setColorAt(pos: 0, color: bgColor.lighter(f: 157));
2415 gradient.setColorAt(pos: 0.1, color: bgColor.lighter(f: 155));
2416 gradient.setColorAt(pos: 0.9, color: bgColor.lighter(f: 155));
2417 gradient.setColorAt(pos: 1, color: bgColor.lighter(f: 157));
2418 }
2419
2420 painter->save();
2421 if (transient)
2422 painter->setOpacity(0.8);
2423 painter->fillRect(rect, gradient);
2424 painter->setPen(Qt::NoPen);
2425 if (transient)
2426 painter->setOpacity(0.4);
2427 painter->setPen(alphaOutline);
2428 if (horizontal)
2429 painter->drawLine(p1: rect.topLeft(), p2: rect.topRight());
2430 else
2431 painter->drawLine(p1: rect.topLeft(), p2: rect.bottomLeft());
2432
2433 QColor subtleEdge = alphaOutline;
2434 subtleEdge.setAlpha(40);
2435 painter->setPen(subtleEdge);
2436 painter->setBrush(Qt::NoBrush);
2437 painter->drawRect(r: scrollBarGroove.adjusted(xp1: 1, yp1: 0, xp2: -1, yp2: -1));
2438 painter->restore();
2439 }
2440
2441 QRect pixmapRect = scrollBarSlider;
2442 QLinearGradient gradient(pixmapRect.center().x(), pixmapRect.top(),
2443 pixmapRect.center().x(), pixmapRect.bottom());
2444 if (!horizontal)
2445 gradient = QLinearGradient(pixmapRect.left(), pixmapRect.center().y(),
2446 pixmapRect.right(), pixmapRect.center().y());
2447
2448 QLinearGradient highlightedGradient = gradient;
2449
2450 QColor midColor2 = mergedColors(colorA: gradientStartColor, colorB: gradientStopColor, factor: 40);
2451 gradient.setColorAt(pos: 0, color: d->buttonColor(pal: option->palette).lighter(f: 108));
2452 gradient.setColorAt(pos: 1, color: d->buttonColor(pal: option->palette));
2453
2454 highlightedGradient.setColorAt(pos: 0, color: gradientStartColor.darker(f: 102));
2455 highlightedGradient.setColorAt(pos: 1, color: gradientStopColor.lighter(f: 102));
2456
2457 // Paint slider
2458 if (scrollBar->subControls & SC_ScrollBarSlider) {
2459 if (transient) {
2460 QRect rect = scrollBarSlider.adjusted(xp1: horizontal ? 1 : 2, yp1: horizontal ? 2 : 1, xp2: -1, yp2: -1);
2461 painter->setPen(Qt::NoPen);
2462 painter->setBrush(isDarkBg ? d->lightShade() : d->darkShade());
2463 int r = qMin(a: rect.width(), b: rect.height()) / 2;
2464
2465 painter->save();
2466 painter->setRenderHint(hint: QPainter::Antialiasing, on: true);
2467 painter->drawRoundedRect(rect, xRadius: r, yRadius: r);
2468 painter->restore();
2469 } else {
2470 QRect pixmapRect = scrollBarSlider;
2471 painter->setPen(QPen(alphaOutline));
2472 if (option->state & State_Sunken && scrollBar->activeSubControls & SC_ScrollBarSlider)
2473 painter->setBrush(midColor2);
2474 else if (option->state & State_MouseOver && scrollBar->activeSubControls & SC_ScrollBarSlider)
2475 painter->setBrush(highlightedGradient);
2476 else if (!isDarkBg)
2477 painter->setBrush(gradient);
2478 else
2479 painter->setBrush(midColor2);
2480
2481 painter->drawRect(r: pixmapRect.adjusted(xp1: horizontal ? -1 : 0, yp1: horizontal ? 0 : -1, xp2: horizontal ? 0 : -1, yp2: horizontal ? -1 : 0));
2482
2483 painter->setPen(d->innerContrastLine());
2484 painter->drawRect(r: scrollBarSlider.adjusted(xp1: horizontal ? 0 : 1, yp1: horizontal ? 1 : 0, xp2: -1, yp2: -1));
2485
2486 // Outer shadow
2487 // painter->setPen(subtleEdge);
2488 // if (horizontal) {
2489 //// painter->drawLine(scrollBarSlider.topLeft() + QPoint(-2, 0), scrollBarSlider.bottomLeft() + QPoint(2, 0));
2490 //// painter->drawLine(scrollBarSlider.topRight() + QPoint(-2, 0), scrollBarSlider.bottomRight() + QPoint(2, 0));
2491 // } else {
2492 //// painter->drawLine(pixmapRect.topLeft() + QPoint(0, -2), pixmapRect.bottomLeft() + QPoint(0, -2));
2493 //// painter->drawLine(pixmapRect.topRight() + QPoint(0, 2), pixmapRect.bottomRight() + QPoint(0, 2));
2494 // }
2495 }
2496 }
2497
2498 // The SubLine (up/left) buttons
2499 if (!transient && scrollBar->subControls & SC_ScrollBarSubLine) {
2500 if ((scrollBar->activeSubControls & SC_ScrollBarSubLine) && sunken)
2501 painter->setBrush(gradientStopColor);
2502 else if ((scrollBar->activeSubControls & SC_ScrollBarSubLine))
2503 painter->setBrush(highlightedGradient);
2504 else
2505 painter->setBrush(gradient);
2506
2507 painter->setPen(Qt::NoPen);
2508 painter->drawRect(r: scrollBarSubLine.adjusted(xp1: horizontal ? 0 : 1, yp1: horizontal ? 1 : 0, xp2: 0, yp2: 0));
2509 painter->setPen(QPen(alphaOutline));
2510 if (option->state & State_Horizontal) {
2511 painter->drawRect(r: scrollBarSubLine.adjusted(xp1: horizontal ? 0 : 1, yp1: 0, xp2: horizontal ? 1 : 0, yp2: horizontal ? -1 : 0));
2512 } else {
2513 painter->drawRect(r: scrollBarSubLine.adjusted(xp1: 0, yp1: 0, xp2: horizontal ? 0 : -1, yp2: 0));
2514 }
2515
2516 QRect upRect = scrollBarSubLine.adjusted(xp1: horizontal ? 0 : 1, yp1: horizontal ? 1 : 0, xp2: horizontal ? -2 : -1, yp2: horizontal ? -1 : -2);
2517 painter->setBrush(Qt::NoBrush);
2518 painter->setPen(d->innerContrastLine());
2519 painter->drawRect(r: upRect);
2520
2521 // Arrows
2522 Qt::ArrowType arrowType = Qt::UpArrow;
2523 if (option->state & State_Horizontal)
2524 arrowType = option->direction == Qt::LeftToRight ? Qt::LeftArrow : Qt::RightArrow;
2525 qt_fusion_draw_arrow(type: arrowType, painter, option, rect: upRect.adjusted(xp1: 1, yp1: 1, xp2: 0, yp2: 0), color: arrowColor);
2526 }
2527
2528 // The AddLine (down/right) button
2529 if (!transient && scrollBar->subControls & SC_ScrollBarAddLine) {
2530 if ((scrollBar->activeSubControls & SC_ScrollBarAddLine) && sunken)
2531 painter->setBrush(gradientStopColor);
2532 else if ((scrollBar->activeSubControls & SC_ScrollBarAddLine))
2533 painter->setBrush(midColor2);
2534 else
2535 painter->setBrush(gradient);
2536
2537 painter->setPen(Qt::NoPen);
2538 painter->drawRect(r: scrollBarAddLine.adjusted(xp1: horizontal ? 0 : 1, yp1: horizontal ? 1 : 0, xp2: 0, yp2: 0));
2539 painter->setPen(QPen(alphaOutline, 1));
2540 if (option->state & State_Horizontal) {
2541 painter->drawRect(r: scrollBarAddLine.adjusted(xp1: horizontal ? -1 : 0, yp1: 0, xp2: horizontal ? -1 : 0, yp2: horizontal ? -1 : 0));
2542 } else {
2543 painter->drawRect(r: scrollBarAddLine.adjusted(xp1: 0, yp1: horizontal ? 0 : -1, xp2: horizontal ? 0 : -1, yp2: horizontal ? 0 : -1));
2544 }
2545
2546 QRect downRect = scrollBarAddLine.adjusted(xp1: 1, yp1: 1, xp2: -1, yp2: -1);
2547 painter->setPen(d->innerContrastLine());
2548 painter->setBrush(Qt::NoBrush);
2549 painter->drawRect(r: downRect);
2550
2551 Qt::ArrowType arrowType = Qt::DownArrow;
2552 if (option->state & State_Horizontal)
2553 arrowType = option->direction == Qt::LeftToRight ? Qt::RightArrow : Qt::LeftArrow;
2554 qt_fusion_draw_arrow(type: arrowType, painter, option, rect: downRect.adjusted(xp1: 1, yp1: 1, xp2: 0, yp2: 0), color: arrowColor);
2555 }
2556
2557 }
2558 painter->restore();
2559 break;
2560#endif // QT_CONFIG(slider)
2561 case CC_ComboBox:
2562 painter->save();
2563 if (const QStyleOptionComboBox *comboBox = qstyleoption_cast<const QStyleOptionComboBox *>(opt: option)) {
2564 bool hasFocus = option->state & State_HasFocus && option->state & State_KeyboardFocusChange;
2565 bool sunken = comboBox->state & State_On; // play dead, if combobox has no items
2566 bool isEnabled = (comboBox->state & State_Enabled);
2567 const qreal dpr = painter->device()->devicePixelRatio();
2568 QPixmap cache;
2569 const QString pixmapName = QStyleHelper::uniqueName(key: "combobox"_L1
2570 % QLatin1StringView(sunken ? "-sunken" : "")
2571 % QLatin1StringView(comboBox->editable ? "-editable" : "")
2572 % QLatin1StringView(isEnabled ? "-enabled" : "")
2573 % QLatin1StringView(!comboBox->frame ? "-frameless" : ""),
2574 option, size: comboBox->rect.size(), dpr);
2575 if (!QPixmapCache::find(key: pixmapName, pixmap: &cache)) {
2576 cache = styleCachePixmap(size: comboBox->rect.size(), pixelRatio: dpr);
2577 QPainter cachePainter(&cache);
2578 QRect pixmapRect(0, 0, comboBox->rect.width(), comboBox->rect.height());
2579 QStyleOptionComboBox comboBoxCopy = *comboBox;
2580 comboBoxCopy.rect = pixmapRect;
2581
2582 QRect rect = pixmapRect;
2583 QRect downArrowRect = proxy()->subControlRect(cc: CC_ComboBox, opt: &comboBoxCopy,
2584 sc: SC_ComboBoxArrow, widget);
2585 // Draw a line edit
2586 if (comboBox->editable) {
2587 QStyleOptionFrame buttonOption;
2588 buttonOption.QStyleOption::operator=(other: *comboBox);
2589 buttonOption.rect = rect;
2590 buttonOption.state = (comboBox->state & (State_Enabled | State_MouseOver | State_HasFocus))
2591 | State_KeyboardFocusChange; // Always show hig
2592
2593 if (sunken) {
2594 buttonOption.state |= State_Sunken;
2595 buttonOption.state &= ~State_MouseOver;
2596 }
2597
2598 if (comboBox->frame) {
2599 cachePainter.save();
2600 cachePainter.setRenderHint(hint: QPainter::Antialiasing, on: true);
2601 cachePainter.translate(dx: 0.5, dy: 0.5);
2602 cachePainter.setPen(Qt::NoPen);
2603 cachePainter.setBrush(buttonOption.palette.base());
2604 cachePainter.drawRoundedRect(rect: rect.adjusted(xp1: 0, yp1: 0, xp2: -1, yp2: -1), xRadius: 2, yRadius: 2);
2605 cachePainter.restore();
2606 proxy()->drawPrimitive(pe: PE_FrameLineEdit, opt: &buttonOption, p: &cachePainter, w: widget);
2607 }
2608
2609 // Draw button clipped
2610 cachePainter.save();
2611 cachePainter.setClipRect(downArrowRect.adjusted(xp1: 0, yp1: 0, xp2: 1, yp2: 0));
2612 buttonOption.rect.setLeft(comboBox->direction == Qt::LeftToRight ?
2613 downArrowRect.left() - 6: downArrowRect.right() + 6);
2614 proxy()->drawPrimitive(pe: PE_PanelButtonCommand, opt: &buttonOption, p: &cachePainter, w: widget);
2615 cachePainter.restore();
2616 cachePainter.setPen( QPen(hasFocus ? option->palette.highlight() : outline.lighter(f: 110), 1));
2617
2618 if (!sunken) {
2619 int borderSize = 1;
2620 if (comboBox->direction == Qt::RightToLeft) {
2621 cachePainter.drawLine(p1: QPoint(downArrowRect.right() - 1, downArrowRect.top() + borderSize ),
2622 p2: QPoint(downArrowRect.right() - 1, downArrowRect.bottom() - borderSize));
2623 } else {
2624 cachePainter.drawLine(p1: QPoint(downArrowRect.left() , downArrowRect.top() + borderSize),
2625 p2: QPoint(downArrowRect.left() , downArrowRect.bottom() - borderSize));
2626 }
2627 } else {
2628 if (comboBox->direction == Qt::RightToLeft) {
2629 cachePainter.drawLine(p1: QPoint(downArrowRect.right(), downArrowRect.top() + 2),
2630 p2: QPoint(downArrowRect.right(), downArrowRect.bottom() - 2));
2631
2632 } else {
2633 cachePainter.drawLine(p1: QPoint(downArrowRect.left(), downArrowRect.top() + 2),
2634 p2: QPoint(downArrowRect.left(), downArrowRect.bottom() - 2));
2635 }
2636 }
2637 } else {
2638 QStyleOptionButton buttonOption;
2639 buttonOption.QStyleOption::operator=(other: *comboBox);
2640 buttonOption.rect = rect;
2641 buttonOption.state = comboBox->state & (State_Enabled | State_MouseOver | State_HasFocus | State_KeyboardFocusChange);
2642 if (sunken) {
2643 buttonOption.state |= State_Sunken;
2644 buttonOption.state &= ~State_MouseOver;
2645 }
2646 proxy()->drawPrimitive(pe: PE_PanelButtonCommand, opt: &buttonOption, p: &cachePainter, w: widget);
2647 }
2648 if (comboBox->subControls & SC_ComboBoxArrow) {
2649 // Draw the up/down arrow
2650 QColor arrowColor = option->palette.buttonText().color();
2651 arrowColor.setAlpha(160);
2652 qt_fusion_draw_arrow(type: Qt::DownArrow, painter: &cachePainter, option, rect: downArrowRect, color: arrowColor);
2653 }
2654 cachePainter.end();
2655 QPixmapCache::insert(key: pixmapName, pixmap: cache);
2656 }
2657 painter->drawPixmap(p: comboBox->rect.topLeft(), pm: cache);
2658 }
2659 painter->restore();
2660 break;
2661#if QT_CONFIG(slider)
2662 case CC_Slider:
2663 if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(opt: option)) {
2664 const qreal dpr = painter->device()->devicePixelRatio();
2665 QRect groove = proxy()->subControlRect(cc: CC_Slider, opt: option, sc: SC_SliderGroove, widget);
2666 QRect handle = proxy()->subControlRect(cc: CC_Slider, opt: option, sc: SC_SliderHandle, widget);
2667
2668 bool horizontal = slider->orientation == Qt::Horizontal;
2669 bool ticksAbove = slider->tickPosition & QSlider::TicksAbove;
2670 bool ticksBelow = slider->tickPosition & QSlider::TicksBelow;
2671 QColor activeHighlight = d->highlight(pal: option->palette);
2672 QPixmap cache;
2673 QBrush oldBrush = painter->brush();
2674 QPen oldPen = painter->pen();
2675 QColor shadowAlpha(Qt::black);
2676 shadowAlpha.setAlpha(10);
2677 if (option->state & State_HasFocus && option->state & State_KeyboardFocusChange)
2678 outline = d->highlightedOutline(pal: option->palette);
2679
2680
2681 if ((option->subControls & SC_SliderGroove) && groove.isValid()) {
2682 QColor grooveColor;
2683 grooveColor.setHsv(h: buttonColor.hue(),
2684 s: qMin(a: 255, b: (int)(buttonColor.saturation())),
2685 v: qMin(a: 255, b: (int)(buttonColor.value()*0.9)));
2686 QString groovePixmapName = QStyleHelper::uniqueName(key: "slider_groove"_L1, option,
2687 size: groove.size(), dpr);
2688 QRect pixmapRect(0, 0, groove.width(), groove.height());
2689
2690 // draw background groove
2691 if (!QPixmapCache::find(key: groovePixmapName, pixmap: &cache)) {
2692 cache = styleCachePixmap(size: pixmapRect.size(), pixelRatio: dpr);
2693 QPainter groovePainter(&cache);
2694 groovePainter.setRenderHint(hint: QPainter::Antialiasing, on: true);
2695 groovePainter.translate(dx: 0.5, dy: 0.5);
2696 QLinearGradient gradient;
2697 if (horizontal) {
2698 gradient.setStart(x: pixmapRect.center().x(), y: pixmapRect.top());
2699 gradient.setFinalStop(x: pixmapRect.center().x(), y: pixmapRect.bottom());
2700 }
2701 else {
2702 gradient.setStart(x: pixmapRect.left(), y: pixmapRect.center().y());
2703 gradient.setFinalStop(x: pixmapRect.right(), y: pixmapRect.center().y());
2704 }
2705 groovePainter.setPen(QPen(outline));
2706 gradient.setColorAt(pos: 0, color: grooveColor.darker(f: 110));
2707 gradient.setColorAt(pos: 1, color: grooveColor.lighter(f: 110));//palette.button().color().darker(115));
2708 groovePainter.setBrush(gradient);
2709 groovePainter.drawRoundedRect(rect: pixmapRect.adjusted(xp1: 1, yp1: 1, xp2: -2, yp2: -2), xRadius: 1, yRadius: 1);
2710 groovePainter.end();
2711 QPixmapCache::insert(key: groovePixmapName, pixmap: cache);
2712 }
2713 painter->drawPixmap(p: groove.topLeft(), pm: cache);
2714
2715 // draw blue groove highlight
2716 QRect clipRect;
2717 if (!groovePixmapName.isEmpty())
2718 groovePixmapName += "_blue"_L1;
2719 if (!QPixmapCache::find(key: groovePixmapName, pixmap: &cache)) {
2720 cache = styleCachePixmap(size: pixmapRect.size(), pixelRatio: dpr);
2721 QPainter groovePainter(&cache);
2722 QLinearGradient gradient;
2723 if (horizontal) {
2724 gradient.setStart(x: pixmapRect.center().x(), y: pixmapRect.top());
2725 gradient.setFinalStop(x: pixmapRect.center().x(), y: pixmapRect.bottom());
2726 }
2727 else {
2728 gradient.setStart(x: pixmapRect.left(), y: pixmapRect.center().y());
2729 gradient.setFinalStop(x: pixmapRect.right(), y: pixmapRect.center().y());
2730 }
2731 QColor highlight = d->highlight(pal: option->palette);
2732 QColor highlightedoutline = highlight.darker(f: 140);
2733 QColor grooveOutline = outline;
2734 if (qGray(rgb: grooveOutline.rgb()) > qGray(rgb: highlightedoutline.rgb()))
2735 grooveOutline = highlightedoutline;
2736
2737 groovePainter.setRenderHint(hint: QPainter::Antialiasing, on: true);
2738 groovePainter.translate(dx: 0.5, dy: 0.5);
2739 groovePainter.setPen(QPen(grooveOutline));
2740 gradient.setColorAt(pos: 0, color: activeHighlight);
2741 gradient.setColorAt(pos: 1, color: activeHighlight.lighter(f: 130));
2742 groovePainter.setBrush(gradient);
2743 groovePainter.drawRoundedRect(rect: pixmapRect.adjusted(xp1: 1, yp1: 1, xp2: -2, yp2: -2), xRadius: 1, yRadius: 1);
2744 groovePainter.setPen(d->innerContrastLine());
2745 groovePainter.setBrush(Qt::NoBrush);
2746 groovePainter.drawRoundedRect(rect: pixmapRect.adjusted(xp1: 2, yp1: 2, xp2: -3, yp2: -3), xRadius: 1, yRadius: 1);
2747 groovePainter.end();
2748 QPixmapCache::insert(key: groovePixmapName, pixmap: cache);
2749 }
2750 if (horizontal) {
2751 if (slider->upsideDown)
2752 clipRect = QRect(handle.right(), groove.top(), groove.right() - handle.right(), groove.height());
2753 else
2754 clipRect = QRect(groove.left(), groove.top(),
2755 handle.left() - slider->rect.left(), groove.height());
2756 } else {
2757 if (slider->upsideDown)
2758 clipRect = QRect(groove.left(), handle.bottom(), groove.width(), groove.height() - (handle.bottom() - slider->rect.top()));
2759 else
2760 clipRect = QRect(groove.left(), groove.top(), groove.width(), handle.top() - groove.top());
2761 }
2762 painter->save();
2763 painter->setClipRect(clipRect.adjusted(xp1: 0, yp1: 0, xp2: 1, yp2: 1), op: Qt::IntersectClip);
2764 painter->drawPixmap(p: groove.topLeft(), pm: cache);
2765 painter->restore();
2766 }
2767
2768 if (option->subControls & SC_SliderTickmarks) {
2769 painter->save();
2770 painter->translate(dx: slider->rect.x(), dy: slider->rect.y());
2771 painter->setPen(outline);
2772 int tickSize = proxy()->pixelMetric(metric: PM_SliderTickmarkOffset, option, widget);
2773 int available = proxy()->pixelMetric(metric: PM_SliderSpaceAvailable, option: slider, widget);
2774 int interval = slider->tickInterval;
2775 if (interval <= 0) {
2776 interval = slider->singleStep;
2777 if (QStyle::sliderPositionFromValue(min: slider->minimum, max: slider->maximum, val: interval,
2778 space: available)
2779 - QStyle::sliderPositionFromValue(min: slider->minimum, max: slider->maximum,
2780 val: 0, space: available) < 3)
2781 interval = slider->pageStep;
2782 }
2783 if (interval <= 0)
2784 interval = 1;
2785
2786 int v = slider->minimum;
2787 int len = proxy()->pixelMetric(metric: PM_SliderLength, option: slider, widget);
2788 QVector<QLine> lines;
2789 while (v <= slider->maximum + 1) {
2790 if (v == slider->maximum + 1 && interval == 1)
2791 break;
2792 const int v_ = qMin(a: v, b: slider->maximum);
2793 int pos = sliderPositionFromValue(min: slider->minimum, max: slider->maximum,
2794 val: v_, space: (horizontal
2795 ? slider->rect.width()
2796 : slider->rect.height()) - len,
2797 upsideDown: slider->upsideDown) + len / 2;
2798 int extra = 2 - ((v_ == slider->minimum || v_ == slider->maximum) ? 1 : 0);
2799
2800 if (horizontal) {
2801 if (ticksAbove) {
2802 lines += QLine(pos, slider->rect.top() + extra,
2803 pos, slider->rect.top() + tickSize);
2804 }
2805 if (ticksBelow) {
2806 lines += QLine(pos, slider->rect.bottom() - extra,
2807 pos, slider->rect.bottom() - tickSize);
2808 }
2809 } else {
2810 if (ticksAbove) {
2811 lines += QLine(slider->rect.left() + extra, pos,
2812 slider->rect.left() + tickSize, pos);
2813 }
2814 if (ticksBelow) {
2815 lines += QLine(slider->rect.right() - extra, pos,
2816 slider->rect.right() - tickSize, pos);
2817 }
2818 }
2819 // in the case where maximum is max int
2820 int nextInterval = v + interval;
2821 if (nextInterval < v)
2822 break;
2823 v = nextInterval;
2824 }
2825 painter->drawLines(lines);
2826 painter->restore();
2827 }
2828 // draw handle
2829 if ((option->subControls & SC_SliderHandle) ) {
2830 QString handlePixmapName = QStyleHelper::uniqueName(key: "slider_handle"_L1, option,
2831 size: handle.size(), dpr);
2832 if (!QPixmapCache::find(key: handlePixmapName, pixmap: &cache)) {
2833 cache = styleCachePixmap(size: handle.size(), pixelRatio: dpr);
2834 QRect pixmapRect(0, 0, handle.width(), handle.height());
2835 QPainter handlePainter(&cache);
2836 QRect gradRect = pixmapRect.adjusted(xp1: 2, yp1: 2, xp2: -2, yp2: -2);
2837
2838 // gradient fill
2839 QRect r = pixmapRect.adjusted(xp1: 1, yp1: 1, xp2: -2, yp2: -2);
2840 QLinearGradient gradient = qt_fusion_gradient(rect: gradRect, baseColor: d->buttonColor(pal: option->palette),direction: horizontal ? TopDown : FromLeft);
2841
2842 handlePainter.setRenderHint(hint: QPainter::Antialiasing, on: true);
2843 handlePainter.translate(dx: 0.5, dy: 0.5);
2844
2845 handlePainter.setPen(Qt::NoPen);
2846 handlePainter.setBrush(QColor(0, 0, 0, 40));
2847 handlePainter.drawRect(r: horizontal ? r.adjusted(xp1: -1, yp1: 2, xp2: 1, yp2: -2) : r.adjusted(xp1: 2, yp1: -1, xp2: -2, yp2: 1));
2848
2849 handlePainter.setPen(QPen(d->outline(pal: option->palette)));
2850 if (option->state & State_HasFocus && option->state & State_KeyboardFocusChange)
2851 handlePainter.setPen(QPen(d->highlightedOutline(pal: option->palette)));
2852
2853 handlePainter.setBrush(gradient);
2854 handlePainter.drawRoundedRect(rect: r, xRadius: 2, yRadius: 2);
2855 handlePainter.setBrush(Qt::NoBrush);
2856 handlePainter.setPen(d->innerContrastLine());
2857 handlePainter.drawRoundedRect(rect: r.adjusted(xp1: 1, yp1: 1, xp2: -1, yp2: -1), xRadius: 2, yRadius: 2);
2858
2859 QColor cornerAlpha = outline.darker(f: 120);
2860 cornerAlpha.setAlpha(80);
2861
2862 //handle shadow
2863 handlePainter.setPen(shadowAlpha);
2864 handlePainter.drawLine(p1: QPoint(r.left() + 2, r.bottom() + 1), p2: QPoint(r.right() - 2, r.bottom() + 1));
2865 handlePainter.drawLine(p1: QPoint(r.right() + 1, r.bottom() - 3), p2: QPoint(r.right() + 1, r.top() + 4));
2866 handlePainter.drawLine(p1: QPoint(r.right() - 1, r.bottom()), p2: QPoint(r.right() + 1, r.bottom() - 2));
2867
2868 handlePainter.end();
2869 QPixmapCache::insert(key: handlePixmapName, pixmap: cache);
2870 }
2871
2872 painter->drawPixmap(p: handle.topLeft(), pm: cache);
2873
2874 }
2875 painter->setBrush(oldBrush);
2876 painter->setPen(oldPen);
2877 }
2878 break;
2879#endif // QT_CONFIG(slider)
2880#if QT_CONFIG(dial)
2881 case CC_Dial:
2882 if (const QStyleOptionSlider *dial = qstyleoption_cast<const QStyleOptionSlider *>(opt: option))
2883 QStyleHelper::drawDial(dial, painter);
2884 break;
2885#endif
2886 default:
2887 QCommonStyle::drawComplexControl(cc: control, opt: option, p: painter, w: widget);
2888 break;
2889 }
2890}
2891
2892/*!
2893 \reimp
2894*/
2895int QFusionStyle::pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const
2896{
2897 int val = -1;
2898 switch (metric) {
2899 case PM_SliderTickmarkOffset:
2900 val = 4;
2901 break;
2902 case PM_HeaderMargin:
2903 case PM_ToolTipLabelFrameWidth:
2904 val = 2;
2905 break;
2906 case PM_ButtonDefaultIndicator:
2907 case PM_ButtonShiftHorizontal:
2908 case PM_ButtonShiftVertical:
2909 val = 0;
2910 break;
2911 case PM_MessageBoxIconSize:
2912 val = 48;
2913 break;
2914 case PM_ListViewIconSize:
2915 val = 24;
2916 break;
2917 case PM_ScrollBarSliderMin:
2918 val = 26;
2919 break;
2920 case PM_TitleBarHeight:
2921 val = 24;
2922 break;
2923 case PM_ScrollBarExtent:
2924 val = 14;
2925 break;
2926 case PM_SliderThickness:
2927 case PM_SliderLength:
2928 val = 15;
2929 break;
2930 case PM_DockWidgetTitleMargin:
2931 val = 1;
2932 break;
2933 case PM_SpinBoxFrameWidth:
2934 val = 3;
2935 break;
2936 case PM_MenuVMargin:
2937 case PM_MenuHMargin:
2938 case PM_MenuPanelWidth:
2939 val = 0;
2940 break;
2941 case PM_MenuBarItemSpacing:
2942 val = 6;
2943 break;
2944 case PM_MenuBarVMargin:
2945 case PM_MenuBarHMargin:
2946 case PM_MenuBarPanelWidth:
2947 val = 0;
2948 break;
2949 case PM_ToolBarHandleExtent:
2950 val = 9;
2951 break;
2952 case PM_ToolBarItemSpacing:
2953 val = 1;
2954 break;
2955 case PM_ToolBarFrameWidth:
2956 case PM_ToolBarItemMargin:
2957 val = 2;
2958 break;
2959 case PM_SmallIconSize:
2960 case PM_ButtonIconSize:
2961 val = 16;
2962 break;
2963 case PM_DockWidgetTitleBarButtonMargin:
2964 val = 2;
2965 break;
2966 case PM_TitleBarButtonSize:
2967 val = 19;
2968 break;
2969 case PM_MaximumDragDistance:
2970 return -1; // Do not dpi-scale because the value is magic
2971 case PM_TabCloseIndicatorWidth:
2972 case PM_TabCloseIndicatorHeight:
2973 val = 20;
2974 break;
2975 case PM_TabBarTabVSpace:
2976 val = 12;
2977 break;
2978 case PM_TabBarTabOverlap:
2979 val = 1;
2980 break;
2981 case PM_TabBarBaseOverlap:
2982 val = 2;
2983 break;
2984 case PM_SubMenuOverlap:
2985 val = -1;
2986 break;
2987 case PM_DockWidgetHandleExtent:
2988 case PM_SplitterWidth:
2989 val = 4;
2990 break;
2991 case PM_IndicatorHeight:
2992 case PM_IndicatorWidth:
2993 case PM_ExclusiveIndicatorHeight:
2994 case PM_ExclusiveIndicatorWidth:
2995 val = 14;
2996 break;
2997 case PM_ScrollView_ScrollBarSpacing:
2998 val = 0;
2999 break;
3000 case PM_ScrollView_ScrollBarOverlap:
3001 if (proxy()->styleHint(stylehint: SH_ScrollBar_Transient, opt: option, widget))
3002 return proxy()->pixelMetric(metric: PM_ScrollBarExtent, option, widget);
3003 val = 0;
3004 break;
3005 case PM_DefaultFrameWidth:
3006 return 1; // Do not dpi-scale because the drawn frame is always exactly 1 pixel thick
3007 default:
3008 return QCommonStyle::pixelMetric(m: metric, opt: option, widget);
3009 }
3010 return QStyleHelper::dpiScaled(value: val, option);
3011}
3012
3013/*!
3014 \reimp
3015*/
3016QSize QFusionStyle::sizeFromContents(ContentsType type, const QStyleOption *option,
3017 const QSize &size, const QWidget *widget) const
3018{
3019 QSize newSize = QCommonStyle::sizeFromContents(ct: type, opt: option, contentsSize: size, widget);
3020 switch (type) {
3021 case CT_PushButton:
3022 if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt: option)) {
3023 if (!btn->text.isEmpty() && newSize.width() < 80)
3024 newSize.setWidth(80);
3025 if (!btn->icon.isNull() && btn->iconSize.height() > 16)
3026 newSize -= QSize(0, 2);
3027 }
3028 break;
3029 case CT_GroupBox:
3030 if (option) {
3031 int topMargin = qMax(a: pixelMetric(metric: PM_IndicatorHeight, option, widget), b: option->fontMetrics.height()) + groupBoxTopMargin;
3032 newSize += QSize(10, topMargin); // Add some space below the groupbox
3033 }
3034 break;
3035 case CT_RadioButton:
3036 case CT_CheckBox:
3037 newSize += QSize(0, 1);
3038 break;
3039 case CT_ToolButton:
3040 newSize += QSize(2, 2);
3041 break;
3042 case CT_SpinBox:
3043 newSize += QSize(0, -3);
3044 break;
3045 case CT_ComboBox:
3046 newSize += QSize(2, 4);
3047 break;
3048 case CT_LineEdit:
3049 newSize += QSize(0, 4);
3050 break;
3051 case CT_MenuBarItem:
3052 newSize += QSize(8, 5);
3053 break;
3054 case CT_MenuItem:
3055 if (const QStyleOptionMenuItem *menuItem = qstyleoption_cast<const QStyleOptionMenuItem *>(opt: option)) {
3056 int w = size.width(); // Don't rely of QCommonStyle's width calculation here
3057 if (menuItem->text.contains(c: u'\t'))
3058 w += menuItem->reservedShortcutWidth;
3059 else if (menuItem->menuItemType == QStyleOptionMenuItem::SubMenu)
3060 w += 2 * QStyleHelper::dpiScaled(value: QFusionStylePrivate::menuArrowHMargin, option);
3061 else if (menuItem->menuItemType == QStyleOptionMenuItem::DefaultItem) {
3062 const QFontMetrics fm(menuItem->font);
3063 QFont fontBold = menuItem->font;
3064 fontBold.setBold(true);
3065 const QFontMetrics fmBold(fontBold);
3066 w += fmBold.horizontalAdvance(menuItem->text) - fm.horizontalAdvance(menuItem->text);
3067 }
3068 const qreal dpi = QStyleHelper::dpi(option);
3069 // Windows always shows a check column
3070 const int checkcol = qMax<int>(a: menuItem->maxIconWidth,
3071 b: QStyleHelper::dpiScaled(value: QFusionStylePrivate::menuCheckMarkWidth, dpi));
3072 w += checkcol + windowsItemFrame;
3073 w += QStyleHelper::dpiScaled(value: int(QFusionStylePrivate::menuRightBorder) + 10, dpi);
3074 newSize.setWidth(w);
3075 if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) {
3076 if (!menuItem->text.isEmpty()) {
3077 newSize.setHeight(menuItem->fontMetrics.height());
3078 }
3079 }
3080 else if (!menuItem->icon.isNull()) {
3081#if QT_CONFIG(combobox)
3082 if (const QComboBox *combo = qobject_cast<const QComboBox*>(object: widget)) {
3083 newSize.setHeight(qMax(a: combo->iconSize().height() + 2, b: newSize.height()));
3084 }
3085#endif
3086 }
3087 newSize.setWidth(newSize.width() + int(QStyleHelper::dpiScaled(value: 12, dpi)));
3088 newSize.setWidth(qMax<int>(a: newSize.width(), b: int(QStyleHelper::dpiScaled(value: 120, dpi))));
3089 }
3090 break;
3091 case CT_SizeGrip:
3092 newSize += QSize(4, 4);
3093 break;
3094 case CT_MdiControls:
3095 newSize -= QSize(1, 0);
3096 break;
3097 default:
3098 break;
3099 }
3100 return newSize;
3101}
3102
3103/*!
3104 \reimp
3105*/
3106void QFusionStyle::polish(QApplication *app)
3107{
3108 QCommonStyle::polish(app);
3109}
3110
3111/*!
3112 \reimp
3113*/
3114void QFusionStyle::polish(QWidget *widget)
3115{
3116 QCommonStyle::polish(widget);
3117 if (false
3118#if QT_CONFIG(abstractbutton)
3119 || qobject_cast<QAbstractButton*>(object: widget)
3120#endif
3121#if QT_CONFIG(combobox)
3122 || qobject_cast<QComboBox *>(object: widget)
3123#endif
3124#if QT_CONFIG(progressbar)
3125 || qobject_cast<QProgressBar *>(object: widget)
3126#endif
3127#if QT_CONFIG(scrollbar)
3128 || qobject_cast<QScrollBar *>(object: widget)
3129#endif
3130#if QT_CONFIG(splitter)
3131 || qobject_cast<QSplitterHandle *>(object: widget)
3132#endif
3133#if QT_CONFIG(abstractslider)
3134 || qobject_cast<QAbstractSlider *>(object: widget)
3135#endif
3136#if QT_CONFIG(spinbox)
3137 || qobject_cast<QAbstractSpinBox *>(object: widget)
3138#endif
3139 || (widget->inherits(classname: "QDockSeparator"))
3140 || (widget->inherits(classname: "QDockWidgetSeparator"))
3141 ) {
3142 widget->setAttribute(Qt::WA_Hover, on: true);
3143 widget->setAttribute(Qt::WA_OpaquePaintEvent, on: false);
3144 }
3145}
3146
3147/*!
3148 \reimp
3149*/
3150void QFusionStyle::polish(QPalette &pal)
3151{
3152 QCommonStyle::polish(pal);
3153}
3154
3155/*!
3156 \reimp
3157*/
3158void QFusionStyle::unpolish(QWidget *widget)
3159{
3160 QCommonStyle::unpolish(widget);
3161 if (false
3162#if QT_CONFIG(abstractbutton)
3163 || qobject_cast<QAbstractButton*>(object: widget)
3164#endif
3165#if QT_CONFIG(combobox)
3166 || qobject_cast<QComboBox *>(object: widget)
3167#endif
3168#if QT_CONFIG(progressbar)
3169 || qobject_cast<QProgressBar *>(object: widget)
3170#endif
3171#if QT_CONFIG(scrollbar)
3172 || qobject_cast<QScrollBar *>(object: widget)
3173#endif
3174#if QT_CONFIG(splitter)
3175 || qobject_cast<QSplitterHandle *>(object: widget)
3176#endif
3177#if QT_CONFIG(abstractslider)
3178 || qobject_cast<QAbstractSlider *>(object: widget)
3179#endif
3180#if QT_CONFIG(spinbox)
3181 || qobject_cast<QAbstractSpinBox *>(object: widget)
3182#endif
3183 || (widget->inherits(classname: "QDockSeparator"))
3184 || (widget->inherits(classname: "QDockWidgetSeparator"))
3185 ) {
3186 widget->setAttribute(Qt::WA_Hover, on: false);
3187 }
3188}
3189
3190/*!
3191 \reimp
3192*/
3193void QFusionStyle::unpolish(QApplication *app)
3194{
3195 QCommonStyle::unpolish(application: app);
3196}
3197
3198/*!
3199 \reimp
3200*/
3201QRect QFusionStyle::subControlRect(ComplexControl control, const QStyleOptionComplex *option,
3202 SubControl subControl, const QWidget *widget) const
3203{
3204 QRect rect = QCommonStyle::subControlRect(cc: control, opt: option, sc: subControl, w: widget);
3205
3206 switch (control) {
3207#if QT_CONFIG(slider)
3208 case CC_Slider:
3209 if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(opt: option)) {
3210 int tickSize = proxy()->pixelMetric(metric: PM_SliderTickmarkOffset, option, widget);
3211 switch (subControl) {
3212 case SC_SliderHandle: {
3213 const bool bothTicks = (slider->tickPosition & QSlider::TicksBothSides) == QSlider::TicksBothSides;
3214 if (slider->orientation == Qt::Horizontal) {
3215 rect.setHeight(proxy()->pixelMetric(metric: PM_SliderThickness, option, widget));
3216 rect.setWidth(proxy()->pixelMetric(metric: PM_SliderLength, option, widget));
3217 int centerY = slider->rect.center().y() - rect.height() / 2;
3218 if (!bothTicks) {
3219 if (slider->tickPosition & QSlider::TicksAbove)
3220 centerY += tickSize;
3221 if (slider->tickPosition & QSlider::TicksBelow)
3222 centerY -= tickSize - 1;
3223 }
3224 rect.moveTop(pos: centerY);
3225 } else {
3226 rect.setWidth(proxy()->pixelMetric(metric: PM_SliderThickness, option, widget));
3227 rect.setHeight(proxy()->pixelMetric(metric: PM_SliderLength, option, widget));
3228 int centerX = slider->rect.center().x() - rect.width() / 2;
3229 if (!bothTicks) {
3230 if (slider->tickPosition & QSlider::TicksAbove)
3231 centerX += tickSize;
3232 if (slider->tickPosition & QSlider::TicksBelow)
3233 centerX -= tickSize - 1;
3234 }
3235 rect.moveLeft(pos: centerX);
3236 }
3237 }
3238 break;
3239 case SC_SliderGroove: {
3240 QPoint grooveCenter = slider->rect.center();
3241 const int grooveThickness = QStyleHelper::dpiScaled(value: 7, option);
3242 const bool bothTicks = (slider->tickPosition & QSlider::TicksBothSides) == QSlider::TicksBothSides;
3243 if (slider->orientation == Qt::Horizontal) {
3244 rect.setHeight(grooveThickness);
3245 if (!bothTicks) {
3246 if (slider->tickPosition & QSlider::TicksAbove)
3247 grooveCenter.ry() += tickSize;
3248 if (slider->tickPosition & QSlider::TicksBelow)
3249 grooveCenter.ry() -= tickSize - 1;
3250 }
3251 } else {
3252 rect.setWidth(grooveThickness);
3253 if (!bothTicks) {
3254 if (slider->tickPosition & QSlider::TicksAbove)
3255 grooveCenter.rx() += tickSize;
3256 if (slider->tickPosition & QSlider::TicksBelow)
3257 grooveCenter.rx() -= tickSize - 1;
3258 }
3259 }
3260 rect.moveCenter(p: grooveCenter);
3261 break;
3262 }
3263 default:
3264 break;
3265 }
3266 }
3267 break;
3268#endif // QT_CONFIG(slider)
3269#if QT_CONFIG(spinbox)
3270 case CC_SpinBox:
3271 if (const QStyleOptionSpinBox *spinbox = qstyleoption_cast<const QStyleOptionSpinBox *>(opt: option)) {
3272 int center = spinbox->rect.height() / 2;
3273 int fw = spinbox->frame ? 3 : 0; // Is drawn with 3 pixels width in drawComplexControl, independently from PM_SpinBoxFrameWidth
3274 int y = fw;
3275 const int buttonWidth = QStyleHelper::dpiScaled(value: 14, option);
3276 int x, lx, rx;
3277 x = spinbox->rect.width() - y - buttonWidth + 2;
3278 lx = fw;
3279 rx = x - fw;
3280 switch (subControl) {
3281 case SC_SpinBoxUp:
3282 if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons)
3283 return QRect();
3284 rect = QRect(x, fw, buttonWidth, center - fw);
3285 break;
3286 case SC_SpinBoxDown:
3287 if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons)
3288 return QRect();
3289
3290 rect = QRect(x, center, buttonWidth, spinbox->rect.bottom() - center - fw + 1);
3291 break;
3292 case SC_SpinBoxEditField:
3293 if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons) {
3294 rect = QRect(lx, fw, spinbox->rect.width() - 2*fw, spinbox->rect.height() - 2*fw);
3295 } else {
3296 rect = QRect(lx, fw, rx - qMax(a: fw - 1, b: 0), spinbox->rect.height() - 2*fw);
3297 }
3298 break;
3299 case SC_SpinBoxFrame:
3300 rect = spinbox->rect;
3301 break;
3302 default:
3303 break;
3304 }
3305 rect = visualRect(direction: spinbox->direction, boundingRect: spinbox->rect, logicalRect: rect);
3306 }
3307 break;
3308#endif // QT_CONFIG(spinbox)
3309 case CC_GroupBox:
3310 if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast<const QStyleOptionGroupBox *>(opt: option)) {
3311 const int groupBoxTextAlignment = groupBox->textAlignment;
3312 const bool hasVerticalAlignment = (groupBoxTextAlignment & Qt::AlignVertical_Mask) == Qt::AlignVCenter;
3313 const int fontMetricsHeight = groupBox->text.isEmpty() ? 0 : groupBox->fontMetrics.height();
3314
3315 if (subControl == SC_GroupBoxFrame)
3316 return rect;
3317 else if (subControl == SC_GroupBoxContents) {
3318 QRect frameRect = option->rect.adjusted(xp1: 0, yp1: 0, xp2: 0, yp2: -groupBoxBottomMargin);
3319 int margin = 3;
3320 int leftMarginExtension = 0;
3321 const int indicatorHeight = option->subControls.testFlag(flag: SC_GroupBoxCheckBox) ?
3322 pixelMetric(metric: PM_IndicatorHeight, option, widget) : 0;
3323 const int topMargin = qMax(a: indicatorHeight, b: fontMetricsHeight) +
3324 groupBoxTopMargin;
3325 return frameRect.adjusted(xp1: leftMarginExtension + margin, yp1: margin + topMargin, xp2: -margin, yp2: -margin - groupBoxBottomMargin);
3326 }
3327
3328 QSize textSize = option->fontMetrics.boundingRect(text: groupBox->text).size() + QSize(2, 2);
3329 int indicatorWidth = proxy()->pixelMetric(metric: PM_IndicatorWidth, option, widget);
3330 int indicatorHeight = proxy()->pixelMetric(metric: PM_IndicatorHeight, option, widget);
3331
3332 const int width = textSize.width()
3333 + (option->subControls & QStyle::SC_GroupBoxCheckBox ? indicatorWidth + 5 : 0);
3334
3335 rect = QRect();
3336
3337 if (option->rect.width() > width) {
3338 switch (groupBoxTextAlignment & Qt::AlignHorizontal_Mask) {
3339 case Qt::AlignHCenter:
3340 rect.moveLeft(pos: (option->rect.width() - width) / 2);
3341 break;
3342 case Qt::AlignRight:
3343 rect.moveLeft(pos: option->rect.width() - width
3344 - (hasVerticalAlignment ? proxy()->pixelMetric(metric: PM_LayoutRightMargin, option: groupBox, widget) : 0));
3345 break;
3346 case Qt::AlignLeft:
3347 if (hasVerticalAlignment)
3348 rect.moveLeft(pos: proxy()->pixelMetric(metric: PM_LayoutLeftMargin, option, widget));
3349 break;
3350 }
3351 }
3352
3353 if (subControl == SC_GroupBoxCheckBox) {
3354 rect.setWidth(indicatorWidth);
3355 rect.setHeight(indicatorHeight);
3356 rect.moveTop(pos: textSize.height() > indicatorHeight ? (textSize.height() - indicatorHeight) / 2 : 0);
3357 rect.translate(dx: 1, dy: 0);
3358 } else if (subControl == SC_GroupBoxLabel) {
3359 rect.setSize(textSize);
3360 rect.moveTop(pos: 1);
3361 if (option->subControls & QStyle::SC_GroupBoxCheckBox)
3362 rect.translate(dx: indicatorWidth + 5, dy: 0);
3363 }
3364 return visualRect(direction: option->direction, boundingRect: option->rect, logicalRect: rect);
3365 }
3366
3367 return rect;
3368
3369 case CC_ComboBox:
3370 switch (subControl) {
3371 case SC_ComboBoxArrow: {
3372 const qreal dpi = QStyleHelper::dpi(option);
3373 rect = visualRect(direction: option->direction, boundingRect: option->rect, logicalRect: rect);
3374 rect.setRect(ax: rect.right() - int(QStyleHelper::dpiScaled(value: 18, dpi)), ay: rect.top() - 2,
3375 aw: int(QStyleHelper::dpiScaled(value: 19, dpi)), ah: rect.height() + 4);
3376 rect = visualRect(direction: option->direction, boundingRect: option->rect, logicalRect: rect);
3377 }
3378 break;
3379 case SC_ComboBoxEditField: {
3380 int frameWidth = 2;
3381 rect = visualRect(direction: option->direction, boundingRect: option->rect, logicalRect: rect);
3382 rect.setRect(ax: option->rect.left() + frameWidth, ay: option->rect.top() + frameWidth,
3383 aw: option->rect.width() - int(QStyleHelper::dpiScaled(value: 19, option)) - 2 * frameWidth,
3384 ah: option->rect.height() - 2 * frameWidth);
3385 if (const QStyleOptionComboBox *box = qstyleoption_cast<const QStyleOptionComboBox *>(opt: option)) {
3386 if (!box->editable) {
3387 rect.adjust(dx1: 2, dy1: 0, dx2: 0, dy2: 0);
3388 if (box->state & (State_Sunken | State_On))
3389 rect.translate(dx: 1, dy: 1);
3390 }
3391 }
3392 rect = visualRect(direction: option->direction, boundingRect: option->rect, logicalRect: rect);
3393 break;
3394 }
3395 default:
3396 break;
3397 }
3398 break;
3399 case CC_TitleBar:
3400 if (const QStyleOptionTitleBar *tb = qstyleoption_cast<const QStyleOptionTitleBar *>(opt: option)) {
3401 SubControl sc = subControl;
3402 QRect &ret = rect;
3403 const int indent = 3;
3404 const int controlTopMargin = 3;
3405 const int controlBottomMargin = 3;
3406 const int controlWidthMargin = 2;
3407 const int controlHeight = tb->rect.height() - controlTopMargin - controlBottomMargin ;
3408 const int delta = controlHeight + controlWidthMargin;
3409 int offset = 0;
3410
3411 bool isMinimized = tb->titleBarState & Qt::WindowMinimized;
3412 bool isMaximized = tb->titleBarState & Qt::WindowMaximized;
3413
3414 switch (sc) {
3415 case SC_TitleBarLabel:
3416 if (tb->titleBarFlags & (Qt::WindowTitleHint | Qt::WindowSystemMenuHint)) {
3417 ret = tb->rect;
3418 if (tb->titleBarFlags & Qt::WindowSystemMenuHint)
3419 ret.adjust(dx1: delta, dy1: 0, dx2: -delta, dy2: 0);
3420 if (tb->titleBarFlags & Qt::WindowMinimizeButtonHint)
3421 ret.adjust(dx1: 0, dy1: 0, dx2: -delta, dy2: 0);
3422 if (tb->titleBarFlags & Qt::WindowMaximizeButtonHint)
3423 ret.adjust(dx1: 0, dy1: 0, dx2: -delta, dy2: 0);
3424 if (tb->titleBarFlags & Qt::WindowShadeButtonHint)
3425 ret.adjust(dx1: 0, dy1: 0, dx2: -delta, dy2: 0);
3426 if (tb->titleBarFlags & Qt::WindowContextHelpButtonHint)
3427 ret.adjust(dx1: 0, dy1: 0, dx2: -delta, dy2: 0);
3428 }
3429 break;
3430 case SC_TitleBarContextHelpButton:
3431 if (tb->titleBarFlags & Qt::WindowContextHelpButtonHint)
3432 offset += delta;
3433 Q_FALLTHROUGH();
3434 case SC_TitleBarMinButton:
3435 if (!isMinimized && (tb->titleBarFlags & Qt::WindowMinimizeButtonHint))
3436 offset += delta;
3437 else if (sc == SC_TitleBarMinButton)
3438 break;
3439 Q_FALLTHROUGH();
3440 case SC_TitleBarNormalButton:
3441 if (isMinimized && (tb->titleBarFlags & Qt::WindowMinimizeButtonHint))
3442 offset += delta;
3443 else if (isMaximized && (tb->titleBarFlags & Qt::WindowMaximizeButtonHint))
3444 offset += delta;
3445 else if (sc == SC_TitleBarNormalButton)
3446 break;
3447 Q_FALLTHROUGH();
3448 case SC_TitleBarMaxButton:
3449 if (!isMaximized && (tb->titleBarFlags & Qt::WindowMaximizeButtonHint))
3450 offset += delta;
3451 else if (sc == SC_TitleBarMaxButton)
3452 break;
3453 Q_FALLTHROUGH();
3454 case SC_TitleBarShadeButton:
3455 if (!isMinimized && (tb->titleBarFlags & Qt::WindowShadeButtonHint))
3456 offset += delta;
3457 else if (sc == SC_TitleBarShadeButton)
3458 break;
3459 Q_FALLTHROUGH();
3460 case SC_TitleBarUnshadeButton:
3461 if (isMinimized && (tb->titleBarFlags & Qt::WindowShadeButtonHint))
3462 offset += delta;
3463 else if (sc == SC_TitleBarUnshadeButton)
3464 break;
3465 Q_FALLTHROUGH();
3466 case SC_TitleBarCloseButton:
3467 if (tb->titleBarFlags & Qt::WindowSystemMenuHint)
3468 offset += delta;
3469 else if (sc == SC_TitleBarCloseButton)
3470 break;
3471 ret.setRect(ax: tb->rect.right() - indent - offset, ay: tb->rect.top() + controlTopMargin,
3472 aw: controlHeight, ah: controlHeight);
3473 break;
3474 case SC_TitleBarSysMenu:
3475 if (tb->titleBarFlags & Qt::WindowSystemMenuHint) {
3476 ret.setRect(ax: tb->rect.left() + controlWidthMargin + indent, ay: tb->rect.top() + controlTopMargin,
3477 aw: controlHeight, ah: controlHeight);
3478 }
3479 break;
3480 default:
3481 break;
3482 }
3483 ret = visualRect(direction: tb->direction, boundingRect: tb->rect, logicalRect: ret);
3484 }
3485 break;
3486 default:
3487 break;
3488 }
3489
3490 return rect;
3491}
3492
3493
3494/*!
3495 \reimp
3496*/
3497QRect QFusionStyle::itemPixmapRect(const QRect &r, int flags, const QPixmap &pixmap) const
3498{
3499 return QCommonStyle::itemPixmapRect(r, flags, pixmap);
3500}
3501
3502/*!
3503 \reimp
3504*/
3505void QFusionStyle::drawItemPixmap(QPainter *painter, const QRect &rect,
3506 int alignment, const QPixmap &pixmap) const
3507{
3508 QCommonStyle::drawItemPixmap(painter, rect, alignment, pixmap);
3509}
3510
3511/*!
3512 \reimp
3513*/
3514QStyle::SubControl QFusionStyle::hitTestComplexControl(ComplexControl cc, const QStyleOptionComplex *opt,
3515 const QPoint &pt, const QWidget *w) const
3516{
3517 return QCommonStyle::hitTestComplexControl(cc, opt, pt, w);
3518}
3519
3520/*!
3521 \reimp
3522*/
3523QPixmap QFusionStyle::generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap,
3524 const QStyleOption *opt) const
3525{
3526 return QCommonStyle::generatedIconPixmap(iconMode, pixmap, opt);
3527}
3528
3529/*!
3530 \reimp
3531*/
3532int QFusionStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget,
3533 QStyleHintReturn *returnData) const
3534{
3535 switch (hint) {
3536 case SH_Slider_SnapToValue:
3537 case SH_PrintDialog_RightAlignButtons:
3538 case SH_FontDialog_SelectAssociatedText:
3539 case SH_MenuBar_AltKeyNavigation:
3540 case SH_ComboBox_ListMouseTracking:
3541 case SH_Slider_StopMouseOverSlider:
3542 case SH_ScrollBar_MiddleClickAbsolutePosition:
3543 case SH_EtchDisabledText:
3544 case SH_TitleBar_AutoRaise:
3545 case SH_TitleBar_NoBorder:
3546 case SH_ItemView_ShowDecorationSelected:
3547 case SH_ItemView_ArrowKeysNavigateIntoChildren:
3548 case SH_ItemView_ChangeHighlightOnFocus:
3549 case SH_MenuBar_MouseTracking:
3550 case SH_Menu_MouseTracking:
3551 case SH_Menu_SupportsSections:
3552 return 1;
3553
3554#if defined(QT_PLATFORM_UIKIT)
3555 case SH_ComboBox_UseNativePopup:
3556 return 1;
3557#endif
3558
3559 case SH_ToolBox_SelectedPageTitleBold:
3560 case SH_ScrollView_FrameOnlyAroundContents:
3561 case SH_Menu_AllowActiveAndDisabled:
3562 case SH_MainWindow_SpaceBelowMenuBar:
3563 case SH_MessageBox_CenterButtons:
3564 case SH_RubberBand_Mask:
3565 return 0;
3566
3567 case SH_ComboBox_Popup:
3568 if (const QStyleOptionComboBox *cmb = qstyleoption_cast<const QStyleOptionComboBox *>(opt: option))
3569 return !cmb->editable;
3570 return 0;
3571
3572 case SH_Table_GridLineColor:
3573 return option ? option->palette.window().color().darker(f: 120).rgba() : 0;
3574
3575 case SH_MessageBox_TextInteractionFlags:
3576 return Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse;
3577#if QT_CONFIG(wizard)
3578 case SH_WizardStyle:
3579 return QWizard::ClassicStyle;
3580#endif
3581 case SH_Menu_SubMenuPopupDelay:
3582 return 225; // default from GtkMenu
3583
3584 case SH_WindowFrame_Mask:
3585 if (QStyleHintReturnMask *mask = qstyleoption_cast<QStyleHintReturnMask *>(hint: returnData)) {
3586 //left rounded corner
3587 mask->region = option->rect;
3588 mask->region -= QRect(option->rect.left(), option->rect.top(), 5, 1);
3589 mask->region -= QRect(option->rect.left(), option->rect.top() + 1, 3, 1);
3590 mask->region -= QRect(option->rect.left(), option->rect.top() + 2, 2, 1);
3591 mask->region -= QRect(option->rect.left(), option->rect.top() + 3, 1, 2);
3592
3593 //right rounded corner
3594 mask->region -= QRect(option->rect.right() - 4, option->rect.top(), 5, 1);
3595 mask->region -= QRect(option->rect.right() - 2, option->rect.top() + 1, 3, 1);
3596 mask->region -= QRect(option->rect.right() - 1, option->rect.top() + 2, 2, 1);
3597 mask->region -= QRect(option->rect.right() , option->rect.top() + 3, 1, 2);
3598 return 1;
3599 }
3600 break;
3601 case SH_GroupBox_TextLabelVerticalAlignment: {
3602 if (const auto *groupBox = qstyleoption_cast<const QStyleOptionGroupBox *>(opt: option)) {
3603 if (groupBox) {
3604 const auto vAlign = groupBox->textAlignment & Qt::AlignVertical_Mask;
3605 // default fusion style is AlignTop
3606 return vAlign == 0 ? Qt::AlignTop : vAlign;
3607 }
3608 }
3609 break;
3610 }
3611 default:
3612 break;
3613 }
3614 return QCommonStyle::styleHint(sh: hint, opt: option, w: widget, shret: returnData);
3615}
3616
3617/*! \reimp */
3618QRect QFusionStyle::subElementRect(SubElement sr, const QStyleOption *opt, const QWidget *w) const
3619{
3620 QRect r = QCommonStyle::subElementRect(r: sr, opt, widget: w);
3621 switch (sr) {
3622 case SE_ProgressBarLabel:
3623 case SE_ProgressBarContents:
3624 case SE_ProgressBarGroove:
3625 return opt->rect;
3626 case SE_PushButtonFocusRect:
3627 r.adjust(dx1: 0, dy1: 1, dx2: 0, dy2: -1);
3628 break;
3629 case SE_DockWidgetTitleBarText: {
3630 if (const QStyleOptionDockWidget *titlebar = qstyleoption_cast<const QStyleOptionDockWidget*>(opt)) {
3631 bool verticalTitleBar = titlebar->verticalTitleBar;
3632 if (verticalTitleBar) {
3633 r.adjust(dx1: 0, dy1: 0, dx2: 0, dy2: -4);
3634 } else {
3635 if (opt->direction == Qt::LeftToRight)
3636 r.adjust(dx1: 4, dy1: 0, dx2: 0, dy2: 0);
3637 else
3638 r.adjust(dx1: 0, dy1: 0, dx2: -4, dy2: 0);
3639 }
3640 }
3641
3642 break;
3643 }
3644 default:
3645 break;
3646 }
3647 return r;
3648}
3649
3650/*!
3651 \internal
3652*/
3653QIcon QFusionStyle::iconFromTheme(StandardPixmap standardIcon) const
3654{
3655 QIcon icon;
3656#if QT_CONFIG(imageformat_png)
3657 auto addIconFiles = [](QStringView prefix, QIcon &icon)
3658 {
3659 const auto fullPrefix = QStringLiteral(":/qt-project.org/styles/fusionstyle/images/") + prefix;
3660 static constexpr auto dockTitleIconSizes = {10, 16, 20, 32, 48, 64};
3661 for (int size : dockTitleIconSizes)
3662 icon.addFile(fileName: fullPrefix + QString::number(size) + QStringLiteral(".png"),
3663 size: QSize(size, size));
3664 };
3665 switch (standardIcon) {
3666 case SP_TitleBarNormalButton:
3667 addIconFiles(u"fusion_normalizedockup-", icon);
3668 break;
3669 case SP_TitleBarMinButton:
3670 addIconFiles(u"fusion_titlebar-min-", icon);
3671 break;
3672 case SP_TitleBarCloseButton:
3673 case SP_DockWidgetCloseButton:
3674 addIconFiles(u"fusion_closedock-", icon);
3675 break;
3676 default:
3677 break;
3678 }
3679#else // imageformat_png
3680 Q_UNUSED(standardIcon);
3681#endif // imageformat_png
3682 return icon;
3683}
3684
3685/*!
3686 \reimp
3687*/
3688QIcon QFusionStyle::standardIcon(StandardPixmap standardIcon, const QStyleOption *option,
3689 const QWidget *widget) const
3690{
3691 const auto icon = iconFromTheme(standardIcon);
3692 if (!icon.availableSizes().isEmpty())
3693 return icon;
3694 return QCommonStyle::standardIcon(standardIcon, opt: option, widget);
3695}
3696
3697/*!
3698 \reimp
3699 */
3700QPixmap QFusionStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt,
3701 const QWidget *widget) const
3702{
3703 auto getDevicePixelRatio = [](const QWidget *widget)
3704 {
3705 return widget ? widget->devicePixelRatio() : qApp->devicePixelRatio();
3706 };
3707 const auto icon = iconFromTheme(standardIcon: standardPixmap);
3708 if (!icon.availableSizes().isEmpty())
3709 return icon.pixmap(size: QSize(16, 16), devicePixelRatio: getDevicePixelRatio(widget));
3710 return QCommonStyle::standardPixmap(sp: standardPixmap, opt, widget);
3711}
3712
3713QT_END_NAMESPACE
3714
3715#include "moc_qfusionstyle_p.cpp"
3716
3717#endif // style_fusion|| QT_PLUGIN
3718

Provided by KDAB

Privacy Policy
Learn Advanced QML with KDAB
Find out more

source code of qtbase/src/widgets/styles/qfusionstyle.cpp