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

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