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

Provided by KDAB

Privacy Policy
Start learning QML with our Intro Training
Find out more

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