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

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