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 
94 QT_BEGIN_NAMESPACE
95 
96 using namespace QStyleHelper;
97 
98 enum Direction {
99     TopDown,
100     FromLeft,
101     BottomUp,
102     FromRight
103 };
104 
105 // from windows style
106 static const int windowsItemFrame        =  2; // menu item frame width
107 static const int windowsItemHMargin      =  3; // menu item hor text margin
108 static const int windowsItemVMargin      =  8; // menu item ver text margin
109 static const int windowsRightBorder      = 15; // right border on windows
110 
111 static const int groupBoxBottomMargin    =  0;  // space below the groupbox
112 static const int groupBoxTopMargin       =  3;
113 
114 #if QT_CONFIG(imageformat_xpm)
115 /* XPM */
116 static 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 
139 static 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 
162 static 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 
186 static 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 
mergedColors(const QColor & colorA,const QColor & colorB,int factor=50)203 static 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
qt_fusion_gradient(const QRect & rect,const QBrush & baseColor,Direction direction=TopDown)214 static 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(124);
238         QColor gradientStopColor = baseColor.color().lighter(102);
239         gradient.setColorAt(0, gradientStartColor);
240         gradient.setColorAt(1, 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 
qt_fusion_draw_arrow(Qt::ArrowType type,QPainter * painter,const QStyleOption * option,const QRect & rect,const QColor & color)250 static 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(14, dpi));
257     const int arrowHeight = int(QStyleHelper::dpiScaled(8, dpi));
258 
259     const int arrowMax = qMin(arrowHeight, arrowWidth);
260     const int rectMax = qMin(rect.height(), rect.width());
261     const int size = qMin(arrowMax, rectMax);
262 
263     QPixmap cachePixmap;
264     QString cacheKey = QStyleHelper::uniqueName(QLatin1String("fusion-arrow"), option, rect.size())
265             % HexString<uint>(type)
266             % HexString<uint>(color.rgba());
267     if (!QPixmapCache::find(cacheKey, &cachePixmap)) {
268         cachePixmap = styleCachePixmap(rect.size());
269         cachePixmap.fill(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((rect.width() - arrowRect.width()) / 2.0,
278                          (rect.height() - arrowRect.height()) / 2.0);
279 
280         QPolygonF triangle;
281         triangle.reserve(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(QPainter::Antialiasing);
300         cachePainter.drawPolygon(triangle);
301 
302         QPixmapCache::insert(cacheKey, cachePixmap);
303     }
304 
305     painter->drawPixmap(rect, cachePixmap);
306 }
307 
qt_fusion_draw_mdibutton(QPainter * painter,const QStyleOptionTitleBar * option,const QRect & tmp,bool hover,bool sunken)308 static void qt_fusion_draw_mdibutton(QPainter *painter, const QStyleOptionTitleBar *option, const QRect &tmp, bool hover, bool sunken)
309 {
310     QColor dark;
311     dark.setHsv(option->palette.button().color().hue(),
312                 qMin(255, (int)(option->palette.button().color().saturation())),
313                 qMin(255, (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(1, 1, -1, -1), option->palette.highlight().color().darker(120));
322     else if (hover)
323         painter->fillRect(tmp.adjusted(1, 1, -1, -1), 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(130);
333 
334     QLinearGradient gradient(tmp.center().x(), tmp.top(), tmp.center().x(), tmp.bottom());
335     gradient.setColorAt(0, mdiButtonGradientStartColor);
336     gradient.setColorAt(1, mdiButtonGradientStopColor);
337     QColor mdiButtonBorderColor(active ? option->palette.highlight().color().darker(180): dark.darker(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, 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, 4);
354 
355     painter->setPen(titleBarHighlight);
356     painter->drawLine(tmp.left() + 2, tmp.top() + 1, tmp.right() - 2, tmp.top() + 1);
357     painter->drawLine(tmp.left() + 1, tmp.top() + 2, tmp.left() + 1, tmp.bottom() - 2);
358 
359     painter->setPen(QPen(gradient, 1));
360     painter->drawLine(tmp.right() + 1, tmp.top() + 2, tmp.right() + 1, tmp.bottom() - 2);
361     painter->drawPoint(tmp.right() , tmp.top() + 1);
362 
363     painter->drawLine(tmp.left() + 2, tmp.bottom() + 1, tmp.right() - 2, tmp.bottom() + 1);
364     painter->drawPoint(tmp.left() + 1, tmp.bottom());
365     painter->drawPoint(tmp.right() - 1, tmp.bottom());
366     painter->drawPoint(tmp.right() , tmp.bottom() - 1);
367 }
368 
qt_getWindow(const QWidget * widget)369 static QWindow *qt_getWindow(const QWidget *widget)
370 {
371     return widget ? QWidgetPrivate::get(widget)->windowHandle(QWidgetPrivate::WindowHandleMode::Closest) : nullptr;
372 }
373 
374 /*
375     \internal
376 */
QFusionStylePrivate()377 QFusionStylePrivate::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 */
QFusionStyle()398 QFusionStyle::QFusionStyle() : QCommonStyle(*new QFusionStylePrivate)
399 {
400     setObjectName(QLatin1String("Fusion"));
401 }
402 
403 /*!
404     \internal
405 
406     Constructs a QFusionStyle object.
407 */
QFusionStyle(QFusionStylePrivate & dd)408 QFusionStyle::QFusionStyle(QFusionStylePrivate &dd) : QCommonStyle(dd)
409 {
410 }
411 
412 /*!
413     Destroys the QFusionStyle object.
414 */
~QFusionStyle()415 QFusionStyle::~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 */
drawItemText(QPainter * painter,const QRect & rect,int alignment,const QPalette & pal,bool enabled,const QString & text,QPalette::ColorRole textRole) const437 void 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(textRole), savedPen.widthF()));
446     }
447     if (!enabled) {
448         QPen pen = painter->pen();
449         painter->setPen(pen);
450     }
451     painter->drawText(rect, alignment, text);
452     painter->setPen(savedPen);
453 }
454 
455 
456 /*!
457     \reimp
458 */
drawPrimitive(PrimitiveElement elem,const QStyleOption * option,QPainter * painter,const QWidget * widget) const459 void 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(option->palette);
470     QColor highlightedOutline = d->highlightedOutline(option->palette);
471 
472     QColor tabFrameColor = d->tabFrameColor(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 *>(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(pixelMetric(PM_ExclusiveIndicatorHeight), option->fontMetrics.height()) + groupBoxTopMargin;
488         }
489         QRect frame = option->rect.adjusted(0, topMargin, 0, 0);
490         qDrawBorderPixmap(painter, frame, 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(PE_IndicatorArrowDown, option, painter, widget);
499         else {
500             const bool reverse = (option->direction == Qt::RightToLeft);
501             drawPrimitive(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 *>(option)) {
509             painter->save();
510             painter->setPen(QPen(outline.lighter(110)));
511             switch (tbb->shape) {
512             case QTabBar::RoundedNorth: {
513                 QRegion region(tbb->rect);
514                 region -= tbb->selectedTabRect;
515                 painter->drawLine(tbb->rect.topLeft(), tbb->rect.topRight());
516                 painter->setClipRegion(region);
517                 painter->setPen(option->palette.light().color());
518                 painter->drawLine(tbb->rect.topLeft() + QPoint(0, 1), tbb->rect.topRight() + QPoint(0, 1));
519             }
520                 break;
521             case QTabBar::RoundedWest:
522                 painter->drawLine(tbb->rect.left(), tbb->rect.top(), tbb->rect.left(), tbb->rect.bottom());
523                 break;
524             case QTabBar::RoundedSouth:
525                 painter->drawLine(tbb->rect.left(), tbb->rect.bottom(),
526                                   tbb->rect.right(), tbb->rect.bottom());
527                 break;
528             case QTabBar::RoundedEast:
529                 painter->drawLine(tbb->rect.topRight(), 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(elem, option, painter, 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(QPalette::Window));
549         painter->drawRect(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(arrow, painter, option, option->rect, arrowColor);
576     }
577         break;
578     case PE_IndicatorItemViewItemCheck:
579     {
580         QStyleOptionButton button;
581         button.QStyleOption::operator=(*option);
582         button.state &= ~State_MouseOver;
583         proxy()->drawPrimitive(PE_IndicatorCheckBox, &button, painter, widget);
584     }
585         return;
586     case PE_IndicatorHeaderArrow:
587         if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(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(Qt::UpArrow, painter, option, r.translated(offset), arrowColor);
596             } else if (header->sortIndicator & QStyleOptionHeader::SortDown) {
597                 qt_fusion_draw_arrow(Qt::DownArrow, painter, option, r.translated(offset), 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_PanelButtonCommand, option, painter, 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(110)));
619             painter->drawLine(rect.bottomLeft().x() + offset,
620                               rect.bottomLeft().y() - margin,
621                               rect.topLeft().x() + offset,
622                               rect.topLeft().y() + margin);
623             painter->setPen(QPen(option->palette.window().color().lighter(110)));
624             painter->drawLine(rect.bottomLeft().x() + offset + 1,
625                               rect.bottomLeft().y() - margin,
626                               rect.topLeft().x() + offset + 1,
627                               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(110)));
631             painter->drawLine(rect.topLeft().x() + margin ,
632                               rect.topLeft().y() + offset,
633                               rect.topRight().x() - margin,
634                               rect.topRight().y() + offset);
635             painter->setPen(QPen(option->palette.window().color().lighter(110)));
636             painter->drawLine(rect.topLeft().x() + margin ,
637                               rect.topLeft().y() + offset + 1,
638                               rect.topRight().x() - margin,
639                               rect.topRight().y() + offset + 1);
640         }
641     }
642         break;
643     case PE_Frame: {
644         if (widget && widget->inherits("QComboBoxPrivateContainer")){
645             QStyleOption copy = *option;
646             copy.state |= State_Raised;
647             proxy()->drawPrimitive(PE_PanelMenu, &copy, painter, widget);
648             break;
649         }
650         painter->save();
651         QPen thePen(outline.lighter(108));
652         thePen.setCosmetic(false);
653         painter->setPen(thePen);
654         painter->drawRect(option->rect.adjusted(0, 0, -1, -1));
655         painter->restore(); }
656         break;
657     case PE_FrameMenu:
658         painter->save();
659     {
660         painter->setPen(QPen(outline));
661         painter->drawRect(option->rect.adjusted(0, 0, -1, -1));
662         QColor frameLight = option->palette.window().color().lighter(160);
663         QColor frameShadow = option->palette.window().color().darker(110);
664 
665         //paint beveleffect
666         QRect frame = option->rect.adjusted(1, 1, -1, -1);
667         painter->setPen(frameLight);
668         painter->drawLine(frame.topLeft(), frame.bottomLeft());
669         painter->drawLine(frame.topLeft(), frame.topRight());
670 
671         painter->setPen(frameShadow);
672         painter->drawLine(frame.topRight(), frame.bottomRight());
673         painter->drawLine(frame.bottomLeft(), 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(120);
682 
683         QRect rect= option->rect;
684         painter->setPen(softshadow);
685         painter->drawRect(option->rect.adjusted(0, 0, -1, -1));
686         painter->setPen(QPen(option->palette.light(), 1));
687         painter->drawLine(QPoint(rect.left() + 1, rect.top() + 1), QPoint(rect.left() + 1, rect.bottom() - 1));
688         painter->setPen(QPen(option->palette.window().color().darker(120)));
689         painter->drawLine(QPoint(rect.left() + 1, rect.bottom() - 1), QPoint(rect.right() - 2, rect.bottom() - 1));
690         painter->drawLine(QPoint(rect.right() - 1, rect.top() + 1), 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("QDockWidgetTitleButton")) {
699                 if (option->state & State_MouseOver)
700                     proxy()->drawPrimitive(PE_PanelButtonCommand, option, painter, widget);
701             } else {
702                 proxy()->drawPrimitive(PE_PanelButtonCommand, option, painter, 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(State_Horizontal, !horizontal);
712         proxy()->drawControl(CE_Splitter, &dockWidgetHandle, painter, widget);
713     }
714         break;
715     case PE_FrameWindow:
716         painter->save();
717     {
718         QRect rect= option->rect;
719         painter->setPen(QPen(outline.darker(150)));
720         painter->drawRect(option->rect.adjusted(0, 0, -1, -1));
721         painter->setPen(QPen(option->palette.light(), 1));
722         painter->drawLine(QPoint(rect.left() + 1, rect.top() + 1),
723                           QPoint(rect.left() + 1, rect.bottom() - 1));
724         painter->setPen(QPen(option->palette.window().color().darker(120)));
725         painter->drawLine(QPoint(rect.left() + 1, rect.bottom() - 1),
726                           QPoint(rect.right() - 2, rect.bottom() - 1));
727         painter->drawLine(QPoint(rect.right() - 1, rect.top() + 1),
728                           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(QPainter::Antialiasing, true);
740         //  ### highdpi painter bug.
741         painter->translate(0.5, 0.5);
742 
743         // Draw Outline
744         painter->setPen( QPen(hasFocus ? highlightedOutline : outline));
745         painter->drawRoundedRect(r.adjusted(0, 0, -1, -1), 2, 2);
746 
747         if (hasFocus) {
748             QColor softHighlight = highlightedOutline;
749             softHighlight.setAlpha(40);
750             painter->setPen(softHighlight);
751             painter->drawRoundedRect(r.adjusted(1, 1, -2, -2), 1.7, 1.7);
752         }
753         // Draw inner shadow
754         painter->setPen(d->topShadow());
755         painter->drawLine(QPoint(r.left() + 2, r.top() + 1), 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*>(option)) {
764             painter->setRenderHint(QPainter::Antialiasing, true);
765             painter->translate(0.5, 0.5);
766             rect = rect.adjusted(0, 0, -1, -1);
767 
768             QColor pressedColor = mergedColors(option->palette.base().color(), option->palette.windowText().color(), 85);
769             painter->setBrush(Qt::NoBrush);
770 
771             // Gradient fill
772             QLinearGradient gradient(rect.topLeft(), rect.bottomLeft());
773             gradient.setColorAt(0, (state & State_Sunken) ? pressedColor : option->palette.base().color().darker(115));
774             gradient.setColorAt(0.15, (state & State_Sunken) ? pressedColor : option->palette.base().color());
775             gradient.setColorAt(1, (state & State_Sunken) ? pressedColor : option->palette.base().color());
776 
777             painter->setBrush((state & State_Sunken) ? QBrush(pressedColor) : gradient);
778             painter->setPen(QPen(outline.lighter(110)));
779 
780             if (option->state & State_HasFocus && option->state & State_KeyboardFocusChange)
781                 painter->setPen(QPen(highlightedOutline));
782             painter->drawRect(rect);
783 
784             QColor checkMarkColor = option->palette.text().color().darker(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(0, checkMarkColor);
791                 checkMarkColor.setAlpha(140);
792                 gradient.setColorAt(1, checkMarkColor);
793                 checkMarkColor.setAlpha(180);
794                 painter->setPen(QPen(checkMarkColor, 1));
795                 painter->setBrush(gradient);
796                 painter->drawRect(rect.adjusted(checkMarkPadding, checkMarkPadding, -checkMarkPadding, -checkMarkPadding));
797 
798             } else if (checkbox->state & State_On) {
799                 const qreal dpi = QStyleHelper::dpi(option);
800                 qreal penWidth = QStyleHelper::dpiScaled(1.5, dpi);
801                 penWidth = qMax<qreal>(penWidth, 0.13 * rect.height());
802                 penWidth = qMin<qreal>(penWidth, 0.20 * rect.height());
803                 QPen checkPen = QPen(checkMarkColor, penWidth);
804                 checkMarkColor.setAlpha(210);
805                 painter->translate(dpiScaled(-0.8, dpi), dpiScaled(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(checkMarkPadding + rectHeight * 0.11, rectHeight * 0.47);
813                 path.lineTo(rectHeight * 0.5, rectHeight - checkMarkPadding);
814                 path.lineTo(rectHeight - checkMarkPadding, checkMarkPadding);
815                 painter->drawPath(path.translated(rect.topLeft()));
816             }
817         }
818         painter->restore();
819         break;
820     case PE_IndicatorRadioButton:
821         painter->save();
822     {
823         QColor pressedColor = mergedColors(option->palette.base().color(), option->palette.windowText().color(), 85);
824         painter->setBrush((state & State_Sunken) ? pressedColor : option->palette.base().color());
825         painter->setRenderHint(QPainter::Antialiasing, 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(circleCenter, outlineRadius, outlineRadius);
830         painter->setPen(QPen(option->palette.window().color().darker(150)));
831         if (option->state & State_HasFocus && option->state & State_KeyboardFocusChange)
832             painter->setPen(QPen(highlightedOutline));
833         painter->drawPath(circle);
834 
835         if (state & (State_On )) {
836             circle = QPainterPath();
837             const qreal checkmarkRadius = outlineRadius / 2.32;
838             circle.addEllipse(circleCenter, checkmarkRadius, checkmarkRadius);
839             QColor checkMarkColor = option->palette.text().color().darker(120);
840             checkMarkColor.setAlpha(200);
841             painter->setPen(checkMarkColor);
842             checkMarkColor.setAlpha(180);
843             painter->setBrush(checkMarkColor);
844             painter->drawPath(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(rect.center().x() + i, rect.center().y() + j, 2, 2, d->lightShade());
856                     painter->fillRect(rect.center().x() + i, rect.center().y() + j, 1, 1, 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(rect.center().x() + i, rect.center().y() + j, 2, 2, d->lightShade());
863                     painter->fillRect(rect.center().x() + i, rect.center().y() + j, 1, 1, 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 *>(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(QPainter::Antialiasing, true);
880             painter->translate(0.5, 0.5);
881             QColor fillcolor = highlightedOutline;
882             fillcolor.setAlpha(80);
883             painter->setPen(fillcolor.darker(120));
884             fillcolor.setAlpha(30);
885             QLinearGradient gradient(rect.topLeft(), rect.bottomLeft());
886             gradient.setColorAt(0, fillcolor.lighter(160));
887             gradient.setColorAt(1, fillcolor);
888             painter->setBrush(gradient);
889             painter->drawRoundedRect(option->rect.adjusted(0, 0, -1, -1), 1, 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*>(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(0, 1, 0, -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, 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, 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(option->palette);
935 
936         QColor darkOutline = outline;
937         if (hasFocus | isDefault) {
938             darkOutline = highlightedOutline;
939         }
940 
941         if (isDefault)
942             buttonColor = mergedColors(buttonColor, highlightedOutline.lighter(130), 90);
943 
944         BEGIN_STYLE_PIXMAPCACHE(QStringLiteral("pushbutton-") + buttonColor.name(QColor::HexArgb))
945         r = rect.adjusted(0, 1, -1, 0);
946 
947         p->setRenderHint(QPainter::Antialiasing, true);
948         p->translate(0.5, -0.5);
949 
950         QLinearGradient gradient = qt_fusion_gradient(rect, (isEnabled && option->state & State_MouseOver ) ? buttonColor : buttonColor.darker(104));
951         p->setPen(Qt::transparent);
952         p->setBrush(isDown ? QBrush(buttonColor.darker(110)) : gradient);
953         p->drawRoundedRect(r, 2.0, 2.0);
954         p->setBrush(Qt::NoBrush);
955 
956         // Outline
957         p->setPen(!isEnabled ? QPen(darkOutline.lighter(115)) : QPen(darkOutline));
958         p->drawRoundedRect(r, 2.0, 2.0);
959 
960         p->setPen(d->innerContrastLine());
961         p->drawRoundedRect(r.adjusted(1, 1, -1, -1), 2.0, 2.0);
962 
963         END_STYLE_PIXMAPCACHE
964         }
965         break;
966     case PE_FrameTabWidget:
967         painter->save();
968         painter->fillRect(option->rect.adjusted(0, 0, -1, -1), tabFrameColor);
969 #if QT_CONFIG(tabwidget)
970         if (const QStyleOptionTabWidgetFrame *twf = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(option)) {
971             QColor borderColor = outline.lighter(110);
972             QRect rect = option->rect.adjusted(0, 0, -1, -1);
973 
974             // Shadow outline
975             if (twf->shape != QTabBar::RoundedSouth) {
976                 rect.adjust(0, 0, 0, -1);
977                 QColor alphaShadow(Qt::black);
978                 alphaShadow.setAlpha(15);
979                 painter->setPen(alphaShadow);
980                 painter->drawLine(option->rect.bottomLeft(), option->rect.bottomRight());            painter->setPen(borderColor);
981             }
982 
983             // outline
984             painter->setPen(outline);
985             painter->drawRect(rect);
986 
987             // Inner frame highlight
988             painter->setPen(d->innerContrastLine());
989             painter->drawRect(rect.adjusted(1, 1, -1, -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(SP_DialogCloseButton, option, widget);
1003         if ((option->state & State_Enabled) && (option->state & State_MouseOver))
1004             proxy()->drawPrimitive(PE_PanelButtonCommand, option, painter, widget);
1005         QPixmap pixmap = d->tabBarcloseButtonIcon.pixmap(qt_getWindow(widget), QSize(16, 16), QIcon::Normal, QIcon::On);
1006         proxy()->drawItemPixmap(painter, option->rect, Qt::AlignCenter, pixmap);
1007     }
1008         break;
1009     case PE_PanelMenu: {
1010         painter->save();
1011         const QBrush menuBackground = option->palette.base().color().lighter(108);
1012         QColor borderColor = option->palette.window().color().darker(160);
1013         qDrawPlainRect(painter, option->rect, borderColor, 1, &menuBackground);
1014         painter->restore();
1015     }
1016         break;
1017 
1018     default:
1019         QCommonStyle::drawPrimitive(elem, option, painter, widget);
1020         break;
1021     }
1022 }
1023 
1024 /*!
1025   \reimp
1026 */
drawControl(ControlElement element,const QStyleOption * option,QPainter * painter,const QWidget * widget) const1027 void 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(option->palette);
1033     QColor highlightedOutline = d->highlightedOutline(option->palette);
1034     QColor shadow = d->darkShade();
1035 
1036     switch (element) {
1037     case CE_ComboBoxLabel:
1038         if (const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
1039             QRect editRect = proxy()->subControlRect(CC_ComboBox, cb, 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(qt_getWindow(widget), cb->iconSize, mode);
1046                 QRect iconRect(editRect);
1047                 iconRect.setWidth(cb->iconSize.width() + 4);
1048                 iconRect = alignedRect(cb->direction,
1049                                        Qt::AlignLeft | Qt::AlignVCenter,
1050                                        iconRect.size(), editRect);
1051                 if (cb->editable)
1052                     painter->fillRect(iconRect, cb->palette.brush(QPalette::Base));
1053                 proxy()->drawItemPixmap(painter, iconRect, Qt::AlignCenter, pixmap);
1054 
1055                 if (cb->direction == Qt::RightToLeft)
1056                     editRect.translate(-4 - cb->iconSize.width(), 0);
1057                 else
1058                     editRect.translate(cb->iconSize.width() + 4, 0);
1059             }
1060             if (!cb->currentText.isEmpty() && !cb->editable) {
1061                 proxy()->drawItemText(painter, editRect.adjusted(1, 0, -1, 0),
1062                                       visualAlignment(cb->direction, Qt::AlignLeft | Qt::AlignVCenter),
1063                                       cb->palette, cb->state & State_Enabled, cb->currentText,
1064                                       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(rect.center().x() + 1, rect.center().y() + j, 2, 2, d->lightShade());
1077                     painter->fillRect(rect.center().x() + 1, rect.center().y() + j, 1, 1, d->darkShade());
1078                 }
1079             } else {
1080                 for (int i = -6; i< 12 ; i += 3) {
1081                     painter->fillRect(rect.center().x() + i, rect.center().y(), 2, 2, d->lightShade());
1082                     painter->fillRect(rect.center().x() + i, rect.center().y(), 1, 1, d->darkShade());
1083                 }
1084             }
1085         }
1086         break;
1087     }
1088 #if QT_CONFIG(rubberband)
1089     case CE_RubberBand:
1090         if (qstyleoption_cast<const QStyleOptionRubberBand *>(option)) {
1091             QColor highlight = option->palette.color(QPalette::Active, QPalette::Highlight);
1092             painter->save();
1093             QColor penColor = highlight.darker(120);
1094             penColor.setAlpha(180);
1095             painter->setPen(penColor);
1096             QColor dimHighlight(qMin(highlight.red()/2 + 110, 255),
1097                                 qMin(highlight.green()/2 + 110, 255),
1098                                 qMin(highlight.blue()/2 + 110, 255));
1099             dimHighlight.setAlpha(widget && widget->isTopLevel() ? 255 : 80);
1100             QLinearGradient gradient(rect.topLeft(), QPoint(rect.bottomLeft().x(), rect.bottomLeft().y()));
1101             gradient.setColorAt(0, dimHighlight.lighter(120));
1102             gradient.setColorAt(1, dimHighlight);
1103             painter->setRenderHint(QPainter::Antialiasing, true);
1104             painter->translate(0.5, 0.5);
1105             painter->setBrush(dimHighlight);
1106             painter->drawRoundedRect(option->rect.adjusted(0, 0, -1, -1), 1, 1);
1107             QColor innerLine = Qt::white;
1108             innerLine.setAlpha(40);
1109             painter->setPen(innerLine);
1110             painter->drawRoundedRect(option->rect.adjusted(1, 1, -2, -2), 1, 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(rect.center().x() + i, rect.center().y() + j, 2, 2, d->lightShade());
1123                     painter->fillRect(rect.center().x() + i, rect.center().y() + j, 1, 1, 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 *>(option)) {
1133             // Reserve the beveled appearance only for mainwindow toolbars
1134             if (widget && !(qobject_cast<const QMainWindow*> (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(0, option->palette.window().color().lighter(104));
1144             gradient.setColorAt(1, 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(option->rect.bottomLeft(), option->rect.bottomRight());
1159                     painter->setPen(shadow);
1160                     painter->drawLine(option->rect.left(), option->rect.bottom() - 1,
1161                                       option->rect.right(), option->rect.bottom() - 1);
1162                 } else {
1163                     // All others draw a single dark line at the bottom.
1164                     painter->setPen(shadow);
1165                     painter->drawLine(option->rect.bottomLeft(), option->rect.bottomRight());
1166                 }
1167                 // All top toolbar lines draw a light line at the top.
1168                 painter->setPen(light);
1169                 painter->drawLine(option->rect.topLeft(), 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(option->rect.bottomLeft(), 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(option->rect.left(), option->rect.bottom() - 1,
1188                                       option->rect.right(), option->rect.bottom() - 1);
1189                     painter->setPen(light);
1190                     painter->drawLine(option->rect.bottomLeft(), option->rect.bottomRight());
1191                 }
1192                 if (toolBar->positionOfLine == QStyleOptionToolBar::End) {
1193                     painter->setPen(shadow);
1194                     painter->drawLine(option->rect.topLeft(), option->rect.topRight());
1195                     painter->setPen(light);
1196                     painter->drawLine(option->rect.left(), option->rect.top() + 1,
1197                                       option->rect.right(), 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(option->rect.topLeft(), 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(option->rect.topLeft(), 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(option->rect.right() - 1, option->rect.top(),
1217                                       option->rect.right() - 1, option->rect.bottom());
1218                     painter->setPen(light);
1219                     painter->drawLine(option->rect.topRight(), 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(option->rect.topRight(), 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(option->rect.topRight(), 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(option->rect.topLeft(), option->rect.bottomLeft());
1238                     // And a light line next to it
1239                     painter->setPen(light);
1240                     painter->drawLine(option->rect.left() + 1, option->rect.top(),
1241                                       option->rect.left() + 1, option->rect.bottom());
1242                 } else {
1243                     // Other right toolbars draw a light line on its left edge
1244                     painter->setPen(light);
1245                     painter->drawLine(option->rect.topLeft(), 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 *>(option)) {
1255             bool verticalTitleBar = dwOpt->verticalTitleBar;
1256 
1257             QRect titleRect = subElementRect(SE_DockWidgetTitleBarText, 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(r.left(), r.top() + r.width());
1267                 painter->rotate(-90);
1268                 painter->translate(-r.left(), -r.top());
1269             }
1270 
1271             if (!dwOpt->title.isEmpty()) {
1272                 QString titleText
1273                         = painter->fontMetrics().elidedText(dwOpt->title,
1274                                                             Qt::ElideRight, titleRect.width());
1275                 proxy()->drawItemText(painter,
1276                                       titleRect,
1277                                       Qt::AlignLeft | Qt::AlignVCenter, dwOpt->palette,
1278                                       dwOpt->state & State_Enabled, titleText,
1279                                       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 *>(option)) {
1288             QString pixmapName = QStyleHelper::uniqueName(QLatin1String("headersection"), option, 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(pixmapName, &cache)) {
1294                 cache = styleCachePixmap(rect.size());
1295                 cache.fill(Qt::transparent);
1296                 QRect pixmapRect(0, 0, rect.width(), rect.height());
1297                 QPainter cachePainter(&cache);
1298                 QColor buttonColor = d->buttonColor(option->palette);
1299                 QColor gradientStopColor;
1300                 QColor gradientStartColor = buttonColor.lighter(104);
1301                 gradientStopColor = buttonColor.darker(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(gradientStartColor, gradientStopColor, 60);
1308                     QColor midColor2 = mergedColors(gradientStartColor, gradientStopColor, 40);
1309                     gradient.setColorAt(0, gradientStartColor);
1310                     gradient.setColorAt(0.5, midColor1);
1311                     gradient.setColorAt(0.501, midColor2);
1312                     gradient.setColorAt(0.92, gradientStopColor);
1313                     gradient.setColorAt(1, gradientStopColor.darker(104));
1314                 }
1315                 cachePainter.fillRect(pixmapRect, gradient);
1316                 cachePainter.setPen(d->innerContrastLine());
1317                 cachePainter.setBrush(Qt::NoBrush);
1318                 cachePainter.drawLine(pixmapRect.topLeft(), pixmapRect.topRight());
1319                 cachePainter.setPen(d->outline(option->palette));
1320                 cachePainter.drawLine(pixmapRect.bottomLeft(), 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(pixmapRect.topRight(), pixmapRect.bottomRight() + QPoint(0, -1));
1327                     cachePainter.setPen(d->innerContrastLine());
1328                     cachePainter.drawLine(pixmapRect.topRight() + QPoint(-1, 0), pixmapRect.bottomRight() + QPoint(-1, -1));
1329                 } else if (header->orientation == Qt::Vertical) {
1330                     cachePainter.setPen(d->outline(option->palette));
1331                     cachePainter.drawLine(pixmapRect.topRight(), pixmapRect.bottomRight());
1332                 }
1333                 cachePainter.end();
1334                 QPixmapCache::insert(pixmapName, cache);
1335             }
1336             painter->drawPixmap(rect.topLeft(), cache);
1337         }
1338         painter->restore();
1339         break;
1340     case CE_ProgressBarGroove:
1341         painter->save();
1342     {
1343         painter->setRenderHint(QPainter::Antialiasing, true);
1344         painter->translate(0.5, 0.5);
1345 
1346         QColor shadowAlpha = Qt::black;
1347         shadowAlpha.setAlpha(16);
1348         painter->setPen(shadowAlpha);
1349         painter->drawLine(rect.topLeft() - QPoint(0, 1), rect.topRight() - QPoint(0, 1));
1350 
1351         painter->setBrush(option->palette.base());
1352         painter->setPen(QPen(outline));
1353         painter->drawRoundedRect(rect.adjusted(0, 0, -1, -1), 2, 2);
1354 
1355         // Inner shadow
1356         painter->setPen(d->topShadow());
1357         painter->drawLine(QPoint(rect.left() + 1, rect.top() + 1),
1358                           QPoint(rect.right() - 1, rect.top() + 1));
1359     }
1360         painter->restore();
1361         break;
1362     case CE_ProgressBarContents:
1363         painter->save();
1364         painter->setRenderHint(QPainter::Antialiasing, true);
1365         painter->translate(0.5, 0.5);
1366         if (const QStyleOptionProgressBar *bar = qstyleoption_cast<const QStyleOptionProgressBar *>(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(rect.height()-1, -1.0);
1382                 m.rotate(90.0);
1383                 painter->setTransform(m, true);
1384             }
1385 
1386             int maxWidth = rect.width();
1387             const auto progress = qMax(bar->progress, bar->minimum); // workaround for bug in QProgressBar
1388             const auto totalSteps = qMax(Q_INT64_C(1), 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(option->palette);
1400             QColor highlightedoutline = highlight.darker(140);
1401             if (qGray(outline.rgb()) > qGray(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(rect.left(), rect.top(), width - 1, rect.height() - 1);
1410                     if (!complete) {
1411                         painter->drawLine(progressBar.topRight() + QPoint(2, 1), progressBar.bottomRight() + QPoint(2, 0));
1412                         painter->setPen(QPen(highlight.darker(140)));
1413                         painter->drawLine(progressBar.topRight() + QPoint(1, 1), progressBar.bottomRight() + QPoint(1, 0));
1414                     }
1415                 } else {
1416                     progressBar.setRect(rect.right() - width - 1, rect.top(), width + 2, rect.height() - 1);
1417                     if (!complete) {
1418                         painter->drawLine(progressBar.topLeft() + QPoint(-2, 1), progressBar.bottomLeft() + QPoint(-2, 0));
1419                         painter->setPen(QPen(highlight.darker(140)));
1420                         painter->drawLine(progressBar.topLeft() + QPoint(-1, 1), progressBar.bottomLeft() + QPoint(-1, 0));
1421                     }
1422                 }
1423             } else {
1424                 progressBar.setRect(rect.left(), rect.top(), rect.width() - 1, rect.height() - 1);
1425             }
1426 
1427             if (indeterminate || bar->progress > bar->minimum) {
1428 
1429                 painter->setPen(QPen(outline));
1430 
1431                 QColor highlightedGradientStartColor = highlight.lighter(120);
1432                 QColor highlightedGradientStopColor  = highlight;
1433                 QLinearGradient gradient(rect.topLeft(), QPoint(rect.bottomLeft().x(), rect.bottomLeft().y()));
1434                 gradient.setColorAt(0, highlightedGradientStartColor);
1435                 gradient.setColorAt(1, highlightedGradientStopColor);
1436 
1437                 painter->setBrush(gradient);
1438 
1439                 painter->save();
1440                 if (!complete && !indeterminate)
1441                     painter->setClipRect(progressBar.adjusted(-1, -1, -1, 1));
1442                 QRect fillRect = progressBar.adjusted( !indeterminate && !complete && reverse ? -2 : 0, 0,
1443                                                        indeterminate || complete || reverse ? 0 : 2, 0);
1444                 painter->drawRoundedRect(fillRect, 2, 2);
1445                 painter->restore();
1446 
1447                 painter->setBrush(Qt::NoBrush);
1448                 painter->setPen(QColor(255, 255, 255, 50));
1449                 painter->drawRoundedRect(progressBar.adjusted(1, 1, -1, -1), 1, 1);
1450 
1451                 if (!indeterminate) {
1452 #if QT_CONFIG(animation)
1453                     (const_cast<QFusionStylePrivate*>(d))->stopAnimation(option->styleObject);
1454 #endif
1455                 } else {
1456                     highlightedGradientStartColor.setAlpha(120);
1457                     painter->setPen(QPen(highlightedGradientStartColor, 9.0));
1458                     painter->setClipRect(progressBar.adjusted(1, 1, -1, -1));
1459 #if QT_CONFIG(animation)
1460                 if (QProgressStyleAnimation *animation = qobject_cast<QProgressStyleAnimation*>(d->animation(option->styleObject)))
1461                     step = animation->animationStep() % 22;
1462                 else
1463                     (const_cast<QFusionStylePrivate*>(d))->startAnimation(new QProgressStyleAnimation(d->animationFps, option->styleObject));
1464 #endif
1465                 for (int x = progressBar.left() - rect.height(); x < rect.right() ; x += 22)
1466                     painter->drawLine(x + step, progressBar.bottom() + 1,
1467                                       x + rect.height() + step, progressBar.top() - 2);
1468                 }
1469             }
1470         }
1471         painter->restore();
1472         break;
1473     case CE_ProgressBarLabel:
1474         if (const QStyleOptionProgressBar *bar = qstyleoption_cast<const QStyleOptionProgressBar *>(option)) {
1475             QRect leftRect;
1476             QRect rect = bar->rect;
1477             QColor textColor = option->palette.text().color();
1478             QColor alternateTextColor = d->highlightedText(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), 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(rect.width() - progressIndicatorPos, 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(leftRect);
1499             painter->setClipRegion(rightRect);
1500             painter->setPen(flip ? alternateTextColor : textColor);
1501             painter->drawText(rect, bar->text, QTextOption(Qt::AlignAbsolute | Qt::AlignHCenter | Qt::AlignVCenter));
1502             if (!leftRect.isNull()) {
1503                 painter->setPen(flip ? textColor : alternateTextColor);
1504                 painter->setClipRect(leftRect);
1505                 painter->drawText(rect, bar->text, 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 *>(option))
1513         {
1514             QStyleOptionMenuItem item = *mbi;
1515             item.rect = mbi->rect.adjusted(0, 1, 0, -3);
1516             QColor highlightOutline = option->palette.highlight().color().darker(125);
1517             painter->fillRect(rect, option->palette.window());
1518 
1519             QCommonStyle::drawControl(element, &item, painter, 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.adjusted(0, 0, -1, -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(SH_UnderlineShortcut, mbi, widget))
1536                     alignment |= Qt::TextHideMnemonic;
1537                 proxy()->drawItemText(painter, item.rect, alignment, mbi->palette, mbi->state & State_Enabled, mbi->text, textRole);
1538             } else {
1539 
1540                 QColor shadow = mergedColors(option->palette.window().color().darker(120),
1541                                              outline.lighter(140), 60);
1542                 painter->setPen(QPen(shadow));
1543                 painter->drawLine(option->rect.bottomLeft(), 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 *>(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(5, option));
1557                 if (!menuItem->text.isEmpty()) {
1558                     painter->setFont(menuItem->font);
1559                     proxy()->drawItemText(painter, menuItem->rect.adjusted(margin, 0, -margin, 0), Qt::AlignLeft | Qt::AlignVCenter,
1560                                           menuItem->palette, menuItem->state & State_Enabled, menuItem->text,
1561                                           QPalette::Text);
1562                     w = menuItem->fontMetrics.horizontalAdvance(menuItem->text) + margin;
1563                 }
1564                 painter->setPen(shadow.lighter(106));
1565                 bool reverse = menuItem->direction == Qt::RightToLeft;
1566                 painter->drawLine(menuItem->rect.left() + margin + (reverse ? 0 : w), menuItem->rect.center().y(),
1567                                   menuItem->rect.right() - margin - (reverse ? w : 0), 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, highlight);
1575                 painter->setPen(QPen(highlightOutline));
1576                 painter->drawRect(QRectF(r).adjusted(0.5, 0.5, -0.5, -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>(menuItem->rect.height() * 0.79,
1586                                      qMax<int>(menuItem->maxIconWidth, dpiScaled(21, option))); // icon checkbox's highlight column width
1587             if (
1588 #if QT_CONFIG(combobox)
1589                 qobject_cast<const QComboBox*>(widget) ||
1590 #endif
1591                 (option->styleObject && option->styleObject->property("_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(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(menuItem->direction, menuItem->rect, checkRect);
1602                 if (checkable) {
1603                     if (menuItem->checkType & QStyleOptionMenuItem::Exclusive) {
1604                         // Radio button
1605                         if (menuItem->state & State_On || checked || sunken) {
1606                             painter->setRenderHint(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( option->palette.currentColorGroup(), textRole));
1612                             const int adjustment = checkRect.height() * 0.3;
1613                             painter->drawEllipse(checkRect.adjusted(adjustment, adjustment, -adjustment, -adjustment));
1614                         }
1615                     } else {
1616                         // Check box
1617                         if (menuItem->icon.isNull()) {
1618                             QStyleOptionButton box;
1619                             box.QStyleOption::operator=(*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_IndicatorCheckBox, &box, painter, 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(opt->direction, menuitem->rect,
1644                                           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(PM_SmallIconSize, option, widget);
1653                 QSize iconSize(smallIconSize, smallIconSize);
1654 #if QT_CONFIG(combobox)
1655                 if (const QComboBox *combo = qobject_cast<const QComboBox*>(widget))
1656                     iconSize = combo->iconSize();
1657 #endif
1658                 if (checked)
1659                     pixmap = menuItem->icon.pixmap(qt_getWindow(widget), iconSize, mode, QIcon::On);
1660                 else
1661                     pixmap = menuItem->icon.pixmap(qt_getWindow(widget), 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(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(option->palette.window().color(),
1673                                                           option->palette.highlight().color());
1674                         opt.palette.setBrush(QPalette::Button, activeColor);
1675                     }
1676                     opt.state |= State_Sunken;
1677                     opt.rect = vCheckRect;
1678                     proxy()->drawPrimitive(PE_PanelButtonCommand, &opt, painter, widget);
1679                 }
1680                 painter->drawPixmap(pmr.topLeft(), 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(&x, &y, &w, &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(opt->direction, menuitem->rect, textRect);
1700             QStringRef s(&menuitem->text);
1701             if (!s.isEmpty()) {                     // draw text
1702                 p->save();
1703                 int t = s.indexOf(QLatin1Char('\t'));
1704                 int text_flags = Qt::AlignVCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine;
1705                 if (!proxy()->styleHint(SH_UnderlineShortcut, menuitem, widget))
1706                     text_flags |= Qt::TextHideMnemonic;
1707                 text_flags |= Qt::AlignLeft;
1708                 if (t >= 0) {
1709                     QRect vShortcutRect = visualRect(opt->direction, menuitem->rect,
1710                                                      QRect(textRect.topRight(), QPoint(menuitem->rect.right(), textRect.bottom())));
1711                     const QString textToDraw = s.mid(t + 1).toString();
1712                     if (dis && !act && proxy()->styleHint(SH_EtchDisabledText, option, widget)) {
1713                         p->setPen(menuitem->palette.light().color());
1714                         p->drawText(vShortcutRect.adjusted(1, 1, 1, 1), text_flags, textToDraw);
1715                         p->setPen(discol);
1716                     }
1717                     p->drawText(vShortcutRect, text_flags, textToDraw);
1718                     s = s.left(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                 const QString textToDraw = s.left(t).toString();
1733                 if (dis && !act && proxy()->styleHint(SH_EtchDisabledText, option, widget)) {
1734                     p->setPen(menuitem->palette.light().color());
1735                     p->drawText(vTextRect.adjusted(1, 1, 1, 1), text_flags, textToDraw);
1736                     p->setPen(discol);
1737                 }
1738                 p->drawText(vTextRect, text_flags, textToDraw);
1739                 p->restore();
1740             }
1741 
1742             // Arrow
1743             if (menuItem->menuItemType == QStyleOptionMenuItem::SubMenu) {// draw sub menu arrow
1744                 int dim = (menuItem->rect.height() - 4) / 2;
1745                 PrimitiveElement arrow;
1746                 arrow = option->direction == Qt::RightToLeft ? PE_IndicatorArrowLeft : PE_IndicatorArrowRight;
1747                 int xpos = menuItem->rect.left() + menuItem->rect.width() - 3 - dim;
1748                 QRect  vSubMenuRect = visualRect(option->direction, menuItem->rect,
1749                                                  QRect(xpos, menuItem->rect.top() + menuItem->rect.height() / 2 - dim / 2, dim, dim));
1750                 QStyleOptionMenuItem newMI = *menuItem;
1751                 newMI.rect = vSubMenuRect;
1752                 newMI.state = !enabled ? State_None : State_Enabled;
1753                 if (selected)
1754                     newMI.palette.setColor(QPalette::WindowText,
1755                                            newMI.palette.highlightedText().color());
1756                 proxy()->drawPrimitive(arrow, &newMI, painter, widget);
1757             }
1758         }
1759         painter->restore();
1760         break;
1761     case CE_MenuHMargin:
1762     case CE_MenuVMargin:
1763         break;
1764     case CE_MenuEmptyArea:
1765         break;
1766     case CE_PushButton:
1767         if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) {
1768             proxy()->drawControl(CE_PushButtonBevel, btn, painter, widget);
1769             QStyleOptionButton subopt = *btn;
1770             subopt.rect = subElementRect(SE_PushButtonContents, btn, widget);
1771             proxy()->drawControl(CE_PushButtonLabel, &subopt, painter, widget);
1772         }
1773         break;
1774     case CE_PushButtonLabel:
1775         if (const QStyleOptionButton *button = qstyleoption_cast<const QStyleOptionButton *>(option)) {
1776             QStyleOptionButton b(*button);
1777             // no PM_ButtonShiftHorizontal and PM_ButtonShiftVertical for fusion style
1778             b.state &= ~(State_On | State_Sunken);
1779             QCommonStyle::drawControl(element, &b, painter, widget);
1780         }
1781         break;
1782     case CE_MenuBarEmptyArea:
1783         painter->save();
1784     {
1785         painter->fillRect(rect, option->palette.window());
1786         QColor shadow = mergedColors(option->palette.window().color().darker(120),
1787                                      outline.lighter(140), 60);
1788         painter->setPen(QPen(shadow));
1789         painter->drawLine(option->rect.bottomLeft(), option->rect.bottomRight());
1790     }
1791         painter->restore();
1792         break;
1793 #if QT_CONFIG(tabbar)
1794     case CE_TabBarTabShape:
1795         painter->save();
1796         if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(option)) {
1797 
1798             bool rtlHorTabs = (tab->direction == Qt::RightToLeft
1799                                && (tab->shape == QTabBar::RoundedNorth
1800                                    || tab->shape == QTabBar::RoundedSouth));
1801             bool selected = tab->state & State_Selected;
1802             bool lastTab = ((!rtlHorTabs && tab->position == QStyleOptionTab::End)
1803                             || (rtlHorTabs
1804                                 && tab->position == QStyleOptionTab::Beginning));
1805             bool onlyOne = tab->position == QStyleOptionTab::OnlyOneTab;
1806             int tabOverlap = pixelMetric(PM_TabBarTabOverlap, option, widget);
1807             rect = option->rect.adjusted(0, 0, (onlyOne || lastTab) ? 0 : tabOverlap, 0);
1808 
1809             QRect r2(rect);
1810             int x1 = r2.left();
1811             int x2 = r2.right();
1812             int y1 = r2.top();
1813             int y2 = r2.bottom();
1814 
1815             painter->setPen(d->innerContrastLine());
1816 
1817             QTransform rotMatrix;
1818             bool flip = false;
1819             painter->setPen(shadow);
1820 
1821             switch (tab->shape) {
1822             case QTabBar::RoundedNorth:
1823                 break;
1824             case QTabBar::RoundedSouth:
1825                 rotMatrix.rotate(180);
1826                 rotMatrix.translate(0, -rect.height() + 1);
1827                 rotMatrix.scale(-1, 1);
1828                 painter->setTransform(rotMatrix, true);
1829                 break;
1830             case QTabBar::RoundedWest:
1831                 rotMatrix.rotate(180 + 90);
1832                 rotMatrix.scale(-1, 1);
1833                 flip = true;
1834                 painter->setTransform(rotMatrix, true);
1835                 break;
1836             case QTabBar::RoundedEast:
1837                 rotMatrix.rotate(90);
1838                 rotMatrix.translate(0, - rect.width() + 1);
1839                 flip = true;
1840                 painter->setTransform(rotMatrix, true);
1841                 break;
1842             default:
1843                 painter->restore();
1844                 QCommonStyle::drawControl(element, tab, painter, widget);
1845                 return;
1846             }
1847 
1848             if (flip) {
1849                 QRect tmp = rect;
1850                 rect = QRect(tmp.y(), tmp.x(), tmp.height(), tmp.width());
1851                 int temp = x1;
1852                 x1 = y1;
1853                 y1 = temp;
1854                 temp = x2;
1855                 x2 = y2;
1856                 y2 = temp;
1857             }
1858 
1859             painter->setRenderHint(QPainter::Antialiasing, true);
1860             painter->translate(0.5, 0.5);
1861 
1862             QColor tabFrameColor = tab->features & QStyleOptionTab::HasFrame ?
1863                         d->tabFrameColor(option->palette) :
1864                         option->palette.window().color();
1865 
1866             QLinearGradient fillGradient(rect.topLeft(), rect.bottomLeft());
1867             QLinearGradient outlineGradient(rect.topLeft(), rect.bottomLeft());
1868             QPen outlinePen = outline.lighter(110);
1869             if (selected) {
1870                 fillGradient.setColorAt(0, tabFrameColor.lighter(104));
1871                 //                QColor highlight = option->palette.highlight().color();
1872                 //                if (option->state & State_HasFocus && option->state & State_KeyboardFocusChange) {
1873                 //                    fillGradient.setColorAt(0, highlight.lighter(130));
1874                 //                    outlineGradient.setColorAt(0, highlight.darker(130));
1875                 //                    fillGradient.setColorAt(0.14, highlight);
1876                 //                    outlineGradient.setColorAt(0.14, highlight.darker(130));
1877                 //                    fillGradient.setColorAt(0.1401, tabFrameColor);
1878                 //                    outlineGradient.setColorAt(0.1401, highlight.darker(130));
1879                 //                }
1880                 fillGradient.setColorAt(1, tabFrameColor);
1881                 outlineGradient.setColorAt(1, outline);
1882                 outlinePen = QPen(outlineGradient, 1);
1883             } else {
1884                 fillGradient.setColorAt(0, tabFrameColor.darker(108));
1885                 fillGradient.setColorAt(0.85, tabFrameColor.darker(108));
1886                 fillGradient.setColorAt(1, tabFrameColor.darker(116));
1887             }
1888 
1889             QRect drawRect = rect.adjusted(0, selected ? 0 : 2, 0, 3);
1890             painter->setPen(outlinePen);
1891             painter->save();
1892             painter->setClipRect(rect.adjusted(-1, -1, 1, selected ? -2 : -3));
1893             painter->setBrush(fillGradient);
1894             painter->drawRoundedRect(drawRect.adjusted(0, 0, -1, -1), 2.0, 2.0);
1895             painter->setBrush(Qt::NoBrush);
1896             painter->setPen(d->innerContrastLine());
1897             painter->drawRoundedRect(drawRect.adjusted(1, 1, -2, -1), 2.0, 2.0);
1898             painter->restore();
1899 
1900             if (selected) {
1901                 painter->fillRect(rect.left() + 1, rect.bottom() - 1, rect.width() - 2, rect.bottom() - 1, tabFrameColor);
1902                 painter->fillRect(QRect(rect.bottomRight() + QPoint(-2, -1), QSize(1, 1)), d->innerContrastLine());
1903                 painter->fillRect(QRect(rect.bottomLeft() + QPoint(0, -1), QSize(1, 1)), d->innerContrastLine());
1904                 painter->fillRect(QRect(rect.bottomRight() + QPoint(-1, -1), QSize(1, 1)), d->innerContrastLine());
1905             }
1906         }
1907         painter->restore();
1908         break;
1909 #endif //QT_CONFIG(tabbar)
1910     default:
1911         QCommonStyle::drawControl(element,option,painter,widget);
1912         break;
1913     }
1914 }
1915 
1916 extern QPalette qt_fusionPalette();
1917 
1918 /*!
1919   \reimp
1920 */
standardPalette() const1921 QPalette QFusionStyle::standardPalette () const
1922 {
1923     return qt_fusionPalette();
1924 }
1925 
1926 /*!
1927   \reimp
1928 */
drawComplexControl(ComplexControl control,const QStyleOptionComplex * option,QPainter * painter,const QWidget * widget) const1929 void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOptionComplex *option,
1930                                       QPainter *painter, const QWidget *widget) const
1931 {
1932 
1933     Q_D (const QFusionStyle);
1934 
1935 #if QT_CONFIG(spinbox) || QT_CONFIG(slider)
1936     QColor buttonColor = d->buttonColor(option->palette);
1937     QColor gradientStopColor = buttonColor;
1938 #endif
1939 #if QT_CONFIG(slider)
1940     QColor gradientStartColor = buttonColor.lighter(118);
1941 #endif
1942     QColor outline = d->outline(option->palette);
1943 
1944     QColor alphaCornerColor;
1945     if (widget) {
1946         // ### backgroundrole/foregroundrole should be part of the style option
1947         alphaCornerColor = mergedColors(option->palette.color(widget->backgroundRole()), outline);
1948     } else {
1949         alphaCornerColor = mergedColors(option->palette.window().color(), outline);
1950     }
1951 
1952     switch (control) {
1953     case CC_GroupBox:
1954         painter->save();
1955         if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast<const QStyleOptionGroupBox *>(option)) {
1956             // Draw frame
1957             QRect textRect = proxy()->subControlRect(CC_GroupBox, option, SC_GroupBoxLabel, widget);
1958             QRect checkBoxRect = proxy()->subControlRect(CC_GroupBox, option, SC_GroupBoxCheckBox, widget);
1959 
1960             if (groupBox->subControls & QStyle::SC_GroupBoxFrame) {
1961                 QStyleOptionFrame frame;
1962                 frame.QStyleOption::operator=(*groupBox);
1963                 frame.features = groupBox->features;
1964                 frame.lineWidth = groupBox->lineWidth;
1965                 frame.midLineWidth = groupBox->midLineWidth;
1966                 frame.rect = proxy()->subControlRect(CC_GroupBox, option, SC_GroupBoxFrame, widget);
1967                 proxy()->drawPrimitive(PE_FrameGroupBox, &frame, painter, widget);
1968             }
1969 
1970             // Draw title
1971             if ((groupBox->subControls & QStyle::SC_GroupBoxLabel) && !groupBox->text.isEmpty()) {
1972                 // groupBox->textColor gets the incorrect palette here
1973                 painter->setPen(QPen(option->palette.windowText(), 1));
1974                 int alignment = int(groupBox->textAlignment);
1975                 if (!proxy()->styleHint(QStyle::SH_UnderlineShortcut, option, widget))
1976                     alignment |= Qt::TextHideMnemonic;
1977 
1978                 proxy()->drawItemText(painter, textRect,  Qt::TextShowMnemonic | Qt::AlignLeft | alignment,
1979                                       groupBox->palette, groupBox->state & State_Enabled, groupBox->text, QPalette::NoRole);
1980 
1981                 if (groupBox->state & State_HasFocus) {
1982                     QStyleOptionFocusRect fropt;
1983                     fropt.QStyleOption::operator=(*groupBox);
1984                     fropt.rect = textRect.adjusted(-2, -1, 2, 1);
1985                     proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget);
1986                 }
1987             }
1988 
1989             // Draw checkbox
1990             if (groupBox->subControls & SC_GroupBoxCheckBox) {
1991                 QStyleOptionButton box;
1992                 box.QStyleOption::operator=(*groupBox);
1993                 box.rect = checkBoxRect;
1994                 proxy()->drawPrimitive(PE_IndicatorCheckBox, &box, painter, widget);
1995             }
1996         }
1997         painter->restore();
1998         break;
1999 #if QT_CONFIG(spinbox)
2000     case CC_SpinBox:
2001         if (const QStyleOptionSpinBox *spinBox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) {
2002             QPixmap cache;
2003             QString pixmapName = QStyleHelper::uniqueName(QLatin1String("spinbox"), spinBox, spinBox->rect.size());
2004             if (!QPixmapCache::find(pixmapName, &cache)) {
2005 
2006                 cache = styleCachePixmap(spinBox->rect.size());
2007                 cache.fill(Qt::transparent);
2008 
2009                 QRect pixmapRect(0, 0, spinBox->rect.width(), spinBox->rect.height());
2010                 QRect rect = pixmapRect;
2011                 QRect r = rect.adjusted(0, 1, 0, -1);
2012                 QPainter cachePainter(&cache);
2013                 QColor arrowColor = spinBox->palette.windowText().color();
2014                 arrowColor.setAlpha(160);
2015 
2016                 bool isEnabled = (spinBox->state & State_Enabled);
2017                 bool hover = isEnabled && (spinBox->state & State_MouseOver);
2018                 bool sunken = (spinBox->state & State_Sunken);
2019                 bool upIsActive = (spinBox->activeSubControls == SC_SpinBoxUp);
2020                 bool downIsActive = (spinBox->activeSubControls == SC_SpinBoxDown);
2021                 bool hasFocus = (option->state & State_HasFocus);
2022 
2023                 QStyleOptionSpinBox spinBoxCopy = *spinBox;
2024                 spinBoxCopy.rect = pixmapRect;
2025                 QRect upRect = proxy()->subControlRect(CC_SpinBox, &spinBoxCopy, SC_SpinBoxUp, widget);
2026                 QRect downRect = proxy()->subControlRect(CC_SpinBox, &spinBoxCopy, SC_SpinBoxDown, widget);
2027 
2028                 if (spinBox->frame) {
2029                     cachePainter.save();
2030                     cachePainter.setRenderHint(QPainter::Antialiasing, true);
2031                     cachePainter.translate(0.5, 0.5);
2032 
2033                     // Fill background
2034                     cachePainter.setPen(Qt::NoPen);
2035                     cachePainter.setBrush(option->palette.base());
2036                     cachePainter.drawRoundedRect(r.adjusted(0, 0, -1, -1), 2, 2);
2037 
2038                     // Draw inner shadow
2039                     cachePainter.setPen(d->topShadow());
2040                     cachePainter.drawLine(QPoint(r.left() + 2, r.top() + 1), QPoint(r.right() - 2, r.top() + 1));
2041 
2042                     // Draw button gradient
2043                     QColor buttonColor = d->buttonColor(option->palette);
2044                     QRect updownRect = upRect.adjusted(0, -2, 0, downRect.height() + 2);
2045                     QLinearGradient gradient = qt_fusion_gradient(updownRect, (isEnabled && option->state & State_MouseOver ) ? buttonColor : buttonColor.darker(104));
2046 
2047                     // Draw button gradient
2048                     cachePainter.setPen(Qt::NoPen);
2049                     cachePainter.setBrush(gradient);
2050 
2051                     cachePainter.save();
2052                     cachePainter.setClipRect(updownRect);
2053                     cachePainter.drawRoundedRect(r.adjusted(0, 0, -1, -1), 2, 2);
2054                     cachePainter.setPen(QPen(d->innerContrastLine()));
2055                     cachePainter.setBrush(Qt::NoBrush);
2056                     cachePainter.drawRoundedRect(r.adjusted(1, 1, -2, -2), 2, 2);
2057                     cachePainter.restore();
2058 
2059                     if ((spinBox->stepEnabled & QAbstractSpinBox::StepUpEnabled) && upIsActive) {
2060                         if (sunken)
2061                             cachePainter.fillRect(upRect.adjusted(0, -1, 0, 0), gradientStopColor.darker(110));
2062                         else if (hover)
2063                             cachePainter.fillRect(upRect.adjusted(0, -1, 0, 0), d->innerContrastLine());
2064                     }
2065 
2066                     if ((spinBox->stepEnabled & QAbstractSpinBox::StepDownEnabled) && downIsActive) {
2067                         if (sunken)
2068                             cachePainter.fillRect(downRect.adjusted(0, 0, 0, 1), gradientStopColor.darker(110));
2069                         else if (hover)
2070                             cachePainter.fillRect(downRect.adjusted(0, 0, 0, 1), d->innerContrastLine());
2071                     }
2072 
2073                     cachePainter.setPen(hasFocus ? d->highlightedOutline(option->palette) : outline);
2074                     cachePainter.setBrush(Qt::NoBrush);
2075                     cachePainter.drawRoundedRect(r.adjusted(0, 0, -1, -1), 2, 2);
2076                     if (hasFocus) {
2077                         QColor softHighlight = option->palette.highlight().color();
2078                         softHighlight.setAlpha(40);
2079                         cachePainter.setPen(softHighlight);
2080                         cachePainter.drawRoundedRect(r.adjusted(1, 1, -2, -2), 1.7, 1.7);
2081                     }
2082                     cachePainter.restore();
2083                 }
2084 
2085                 // outline the up/down buttons
2086                 cachePainter.setPen(outline);
2087                 if (spinBox->direction == Qt::RightToLeft) {
2088                     cachePainter.drawLine(upRect.right(), upRect.top() - 1, upRect.right(), downRect.bottom() + 1);
2089                 } else {
2090                     cachePainter.drawLine(upRect.left(), upRect.top() - 1, upRect.left(), downRect.bottom() + 1);
2091                 }
2092 
2093                 if (upIsActive && sunken) {
2094                     cachePainter.setPen(gradientStopColor.darker(130));
2095                     cachePainter.drawLine(downRect.left() + 1, downRect.top(), downRect.right(), downRect.top());
2096                     cachePainter.drawLine(upRect.left() + 1, upRect.top(), upRect.left() + 1, upRect.bottom());
2097                     cachePainter.drawLine(upRect.left() + 1, upRect.top() - 1, upRect.right(), upRect.top() - 1);
2098                 }
2099 
2100                 if (downIsActive && sunken) {
2101                     cachePainter.setPen(gradientStopColor.darker(130));
2102                     cachePainter.drawLine(downRect.left() + 1, downRect.top(), downRect.left() + 1, downRect.bottom() + 1);
2103                     cachePainter.drawLine(downRect.left() + 1, downRect.top(), downRect.right(), downRect.top());
2104                     cachePainter.setPen(gradientStopColor.darker(110));
2105                     cachePainter.drawLine(downRect.left() + 1, downRect.bottom() + 1, downRect.right(), downRect.bottom() + 1);
2106                 }
2107 
2108                 QColor disabledColor = mergedColors(arrowColor, option->palette.button().color());
2109                 if (spinBox->buttonSymbols == QAbstractSpinBox::PlusMinus) {
2110                     int centerX = upRect.center().x();
2111                     int centerY = upRect.center().y();
2112 
2113                     // plus/minus
2114                     cachePainter.setPen((spinBox->stepEnabled & QAbstractSpinBox::StepUpEnabled) ? arrowColor : disabledColor);
2115                     cachePainter.drawLine(centerX - 1, centerY, centerX + 3, centerY);
2116                     cachePainter.drawLine(centerX + 1, centerY - 2, centerX + 1, centerY + 2);
2117 
2118                     centerX = downRect.center().x();
2119                     centerY = downRect.center().y();
2120                     cachePainter.setPen((spinBox->stepEnabled & QAbstractSpinBox::StepDownEnabled) ? arrowColor : disabledColor);
2121                     cachePainter.drawLine(centerX - 1, centerY, centerX + 3, centerY);
2122 
2123                 } else if (spinBox->buttonSymbols == QAbstractSpinBox::UpDownArrows){
2124                     // arrows
2125                     qt_fusion_draw_arrow(Qt::UpArrow, &cachePainter, option, upRect.adjusted(0, 0, 0, 1),
2126                                          (spinBox->stepEnabled & QAbstractSpinBox::StepUpEnabled) ? arrowColor : disabledColor);
2127                     qt_fusion_draw_arrow(Qt::DownArrow, &cachePainter, option, downRect,
2128                                          (spinBox->stepEnabled & QAbstractSpinBox::StepDownEnabled) ? arrowColor : disabledColor);
2129                 }
2130 
2131                 cachePainter.end();
2132                 QPixmapCache::insert(pixmapName, cache);
2133             }
2134             painter->drawPixmap(spinBox->rect.topLeft(), cache);
2135         }
2136         break;
2137 #endif // QT_CONFIG(spinbox)
2138     case CC_TitleBar:
2139         painter->save();
2140         if (const QStyleOptionTitleBar *titleBar = qstyleoption_cast<const QStyleOptionTitleBar *>(option)) {
2141             const int buttonMargin = 5;
2142             bool active = (titleBar->titleBarState & State_Active);
2143             QRect fullRect = titleBar->rect;
2144             QPalette palette = option->palette;
2145             QColor highlight = option->palette.highlight().color();
2146 
2147             QColor titleBarFrameBorder(active ? highlight.darker(180): outline.darker(110));
2148             QColor titleBarHighlight(active ? highlight.lighter(120): palette.window().color().lighter(120));
2149             QColor textColor(active ? 0xffffff : 0xff000000);
2150             QColor textAlphaColor(active ? 0xffffff : 0xff000000 );
2151 
2152             {
2153                 // Fill title bar gradient
2154                 QColor titlebarColor = QColor(active ? highlight: palette.window().color());
2155                 QLinearGradient gradient(option->rect.center().x(), option->rect.top(),
2156                                          option->rect.center().x(), option->rect.bottom());
2157 
2158                 gradient.setColorAt(0, titlebarColor.lighter(114));
2159                 gradient.setColorAt(0.5, titlebarColor.lighter(102));
2160                 gradient.setColorAt(0.51, titlebarColor.darker(104));
2161                 gradient.setColorAt(1, titlebarColor);
2162                 painter->fillRect(option->rect.adjusted(1, 1, -1, 0), gradient);
2163 
2164                 // Frame and rounded corners
2165                 painter->setPen(titleBarFrameBorder);
2166 
2167                 // top outline
2168                 painter->drawLine(fullRect.left() + 5, fullRect.top(), fullRect.right() - 5, fullRect.top());
2169                 painter->drawLine(fullRect.left(), fullRect.top() + 4, fullRect.left(), fullRect.bottom());
2170                 const QPoint points[5] = {
2171                     QPoint(fullRect.left() + 4, fullRect.top() + 1),
2172                     QPoint(fullRect.left() + 3, fullRect.top() + 1),
2173                     QPoint(fullRect.left() + 2, fullRect.top() + 2),
2174                     QPoint(fullRect.left() + 1, fullRect.top() + 3),
2175                     QPoint(fullRect.left() + 1, fullRect.top() + 4)
2176                 };
2177                 painter->drawPoints(points, 5);
2178 
2179                 painter->drawLine(fullRect.right(), fullRect.top() + 4, fullRect.right(), fullRect.bottom());
2180                 const QPoint points2[5] = {
2181                     QPoint(fullRect.right() - 3, fullRect.top() + 1),
2182                     QPoint(fullRect.right() - 4, fullRect.top() + 1),
2183                     QPoint(fullRect.right() - 2, fullRect.top() + 2),
2184                     QPoint(fullRect.right() - 1, fullRect.top() + 3),
2185                     QPoint(fullRect.right() - 1, fullRect.top() + 4)
2186                 };
2187                 painter->drawPoints(points2, 5);
2188 
2189                 // draw bottomline
2190                 painter->drawLine(fullRect.right(), fullRect.bottom(), fullRect.left(), fullRect.bottom());
2191 
2192                 // top highlight
2193                 painter->setPen(titleBarHighlight);
2194                 painter->drawLine(fullRect.left() + 6, fullRect.top() + 1, fullRect.right() - 6, fullRect.top() + 1);
2195             }
2196             // draw title
2197             QRect textRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarLabel, widget);
2198             painter->setPen(active? (titleBar->palette.text().color().lighter(120)) :
2199                                     titleBar->palette.text().color() );
2200             // Note workspace also does elliding but it does not use the correct font
2201             QString title = painter->fontMetrics().elidedText(titleBar->text, Qt::ElideRight, textRect.width() - 14);
2202             painter->drawText(textRect.adjusted(1, 1, 1, 1), title, QTextOption(Qt::AlignHCenter | Qt::AlignVCenter));
2203             painter->setPen(Qt::white);
2204             if (active)
2205                 painter->drawText(textRect, title, QTextOption(Qt::AlignHCenter | Qt::AlignVCenter));
2206             // min button
2207             if ((titleBar->subControls & SC_TitleBarMinButton) && (titleBar->titleBarFlags & Qt::WindowMinimizeButtonHint) &&
2208                     !(titleBar->titleBarState& Qt::WindowMinimized)) {
2209                 QRect minButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarMinButton, widget);
2210                 if (minButtonRect.isValid()) {
2211                     bool hover = (titleBar->activeSubControls & SC_TitleBarMinButton) && (titleBar->state & State_MouseOver);
2212                     bool sunken = (titleBar->activeSubControls & SC_TitleBarMinButton) && (titleBar->state & State_Sunken);
2213                     qt_fusion_draw_mdibutton(painter, titleBar, minButtonRect, hover, sunken);
2214                     QRect minButtonIconRect = minButtonRect.adjusted(buttonMargin ,buttonMargin , -buttonMargin, -buttonMargin);
2215                     painter->setPen(textColor);
2216                     painter->drawLine(minButtonIconRect.center().x() - 2, minButtonIconRect.center().y() + 3,
2217                                       minButtonIconRect.center().x() + 3, minButtonIconRect.center().y() + 3);
2218                     painter->drawLine(minButtonIconRect.center().x() - 2, minButtonIconRect.center().y() + 4,
2219                                       minButtonIconRect.center().x() + 3, minButtonIconRect.center().y() + 4);
2220                     painter->setPen(textAlphaColor);
2221                     painter->drawLine(minButtonIconRect.center().x() - 3, minButtonIconRect.center().y() + 3,
2222                                       minButtonIconRect.center().x() - 3, minButtonIconRect.center().y() + 4);
2223                     painter->drawLine(minButtonIconRect.center().x() + 4, minButtonIconRect.center().y() + 3,
2224                                       minButtonIconRect.center().x() + 4, minButtonIconRect.center().y() + 4);
2225                 }
2226             }
2227             // max button
2228             if ((titleBar->subControls & SC_TitleBarMaxButton) && (titleBar->titleBarFlags & Qt::WindowMaximizeButtonHint) &&
2229                     !(titleBar->titleBarState & Qt::WindowMaximized)) {
2230                 QRect maxButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarMaxButton, widget);
2231                 if (maxButtonRect.isValid()) {
2232                     bool hover = (titleBar->activeSubControls & SC_TitleBarMaxButton) && (titleBar->state & State_MouseOver);
2233                     bool sunken = (titleBar->activeSubControls & SC_TitleBarMaxButton) && (titleBar->state & State_Sunken);
2234                     qt_fusion_draw_mdibutton(painter, titleBar, maxButtonRect, hover, sunken);
2235 
2236                     QRect maxButtonIconRect = maxButtonRect.adjusted(buttonMargin, buttonMargin, -buttonMargin, -buttonMargin);
2237 
2238                     painter->setPen(textColor);
2239                     painter->drawRect(maxButtonIconRect.adjusted(0, 0, -1, -1));
2240                     painter->drawLine(maxButtonIconRect.left() + 1, maxButtonIconRect.top() + 1,
2241                                       maxButtonIconRect.right() - 1, maxButtonIconRect.top() + 1);
2242                     painter->setPen(textAlphaColor);
2243                     const QPoint points[4] = {
2244                         maxButtonIconRect.topLeft(),
2245                         maxButtonIconRect.topRight(),
2246                         maxButtonIconRect.bottomLeft(),
2247                         maxButtonIconRect.bottomRight()
2248                     };
2249                     painter->drawPoints(points, 4);
2250                 }
2251             }
2252 
2253             // close button
2254             if ((titleBar->subControls & SC_TitleBarCloseButton) && (titleBar->titleBarFlags & Qt::WindowSystemMenuHint)) {
2255                 QRect closeButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarCloseButton, widget);
2256                 if (closeButtonRect.isValid()) {
2257                     bool hover = (titleBar->activeSubControls & SC_TitleBarCloseButton) && (titleBar->state & State_MouseOver);
2258                     bool sunken = (titleBar->activeSubControls & SC_TitleBarCloseButton) && (titleBar->state & State_Sunken);
2259                     qt_fusion_draw_mdibutton(painter, titleBar, closeButtonRect, hover, sunken);
2260                     QRect closeIconRect = closeButtonRect.adjusted(buttonMargin, buttonMargin, -buttonMargin, -buttonMargin);
2261                     painter->setPen(textAlphaColor);
2262                     const QLine lines[4] = {
2263                         QLine(closeIconRect.left() + 1, closeIconRect.top(),
2264                         closeIconRect.right(), closeIconRect.bottom() - 1),
2265                         QLine(closeIconRect.left(), closeIconRect.top() + 1,
2266                         closeIconRect.right() - 1, closeIconRect.bottom()),
2267                         QLine(closeIconRect.right() - 1, closeIconRect.top(),
2268                         closeIconRect.left(), closeIconRect.bottom() - 1),
2269                         QLine(closeIconRect.right(), closeIconRect.top() + 1,
2270                         closeIconRect.left() + 1, closeIconRect.bottom())
2271                     };
2272                     painter->drawLines(lines, 4);
2273                     const QPoint points[4] = {
2274                         closeIconRect.topLeft(),
2275                         closeIconRect.topRight(),
2276                         closeIconRect.bottomLeft(),
2277                         closeIconRect.bottomRight()
2278                     };
2279                     painter->drawPoints(points, 4);
2280 
2281                     painter->setPen(textColor);
2282                     painter->drawLine(closeIconRect.left() + 1, closeIconRect.top() + 1,
2283                                       closeIconRect.right() - 1, closeIconRect.bottom() - 1);
2284                     painter->drawLine(closeIconRect.left() + 1, closeIconRect.bottom() - 1,
2285                                       closeIconRect.right() - 1, closeIconRect.top() + 1);
2286                 }
2287             }
2288 
2289             // normalize button
2290             if ((titleBar->subControls & SC_TitleBarNormalButton) &&
2291                     (((titleBar->titleBarFlags & Qt::WindowMinimizeButtonHint) &&
2292                       (titleBar->titleBarState & Qt::WindowMinimized)) ||
2293                      ((titleBar->titleBarFlags & Qt::WindowMaximizeButtonHint) &&
2294                       (titleBar->titleBarState & Qt::WindowMaximized)))) {
2295                 QRect normalButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarNormalButton, widget);
2296                 if (normalButtonRect.isValid()) {
2297 
2298                     bool hover = (titleBar->activeSubControls & SC_TitleBarNormalButton) && (titleBar->state & State_MouseOver);
2299                     bool sunken = (titleBar->activeSubControls & SC_TitleBarNormalButton) && (titleBar->state & State_Sunken);
2300                     QRect normalButtonIconRect = normalButtonRect.adjusted(buttonMargin, buttonMargin, -buttonMargin, -buttonMargin);
2301                     qt_fusion_draw_mdibutton(painter, titleBar, normalButtonRect, hover, sunken);
2302 
2303                     QRect frontWindowRect = normalButtonIconRect.adjusted(0, 3, -3, 0);
2304                     painter->setPen(textColor);
2305                     painter->drawRect(frontWindowRect.adjusted(0, 0, -1, -1));
2306                     painter->drawLine(frontWindowRect.left() + 1, frontWindowRect.top() + 1,
2307                                       frontWindowRect.right() - 1, frontWindowRect.top() + 1);
2308                     painter->setPen(textAlphaColor);
2309                     const QPoint points[4] = {
2310                         frontWindowRect.topLeft(),
2311                         frontWindowRect.topRight(),
2312                         frontWindowRect.bottomLeft(),
2313                         frontWindowRect.bottomRight()
2314                     };
2315                     painter->drawPoints(points, 4);
2316 
2317                     QRect backWindowRect = normalButtonIconRect.adjusted(3, 0, 0, -3);
2318                     QRegion clipRegion = backWindowRect;
2319                     clipRegion -= frontWindowRect;
2320                     painter->save();
2321                     painter->setClipRegion(clipRegion);
2322                     painter->setPen(textColor);
2323                     painter->drawRect(backWindowRect.adjusted(0, 0, -1, -1));
2324                     painter->drawLine(backWindowRect.left() + 1, backWindowRect.top() + 1,
2325                                       backWindowRect.right() - 1, backWindowRect.top() + 1);
2326                     painter->setPen(textAlphaColor);
2327                     const QPoint points2[4] = {
2328                         backWindowRect.topLeft(),
2329                         backWindowRect.topRight(),
2330                         backWindowRect.bottomLeft(),
2331                         backWindowRect.bottomRight()
2332                     };
2333                     painter->drawPoints(points2, 4);
2334                     painter->restore();
2335                 }
2336             }
2337 
2338             // context help button
2339             if (titleBar->subControls & SC_TitleBarContextHelpButton
2340                     && (titleBar->titleBarFlags & Qt::WindowContextHelpButtonHint)) {
2341                 QRect contextHelpButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarContextHelpButton, widget);
2342                 if (contextHelpButtonRect.isValid()) {
2343                     bool hover = (titleBar->activeSubControls & SC_TitleBarContextHelpButton) && (titleBar->state & State_MouseOver);
2344                     bool sunken = (titleBar->activeSubControls & SC_TitleBarContextHelpButton) && (titleBar->state & State_Sunken);
2345                     qt_fusion_draw_mdibutton(painter, titleBar, contextHelpButtonRect, hover, sunken);
2346 #if QT_CONFIG(imageformat_xpm)
2347                     QImage image(qt_titlebar_context_help);
2348                     QColor alpha = textColor;
2349                     alpha.setAlpha(128);
2350                     image.setColor(1, textColor.rgba());
2351                     image.setColor(2, alpha.rgba());
2352                     painter->setRenderHint(QPainter::SmoothPixmapTransform);
2353                     painter->drawImage(contextHelpButtonRect.adjusted(4, 4, -4, -4), image);
2354 #endif
2355                 }
2356             }
2357 
2358             // shade button
2359             if (titleBar->subControls & SC_TitleBarShadeButton && (titleBar->titleBarFlags & Qt::WindowShadeButtonHint)) {
2360                 QRect shadeButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarShadeButton, widget);
2361                 if (shadeButtonRect.isValid()) {
2362                     bool hover = (titleBar->activeSubControls & SC_TitleBarShadeButton) && (titleBar->state & State_MouseOver);
2363                     bool sunken = (titleBar->activeSubControls & SC_TitleBarShadeButton) && (titleBar->state & State_Sunken);
2364                     qt_fusion_draw_mdibutton(painter, titleBar, shadeButtonRect, hover, sunken);
2365                     qt_fusion_draw_arrow(Qt::UpArrow, painter, option, shadeButtonRect.adjusted(5, 7, -5, -7), textColor);
2366                 }
2367             }
2368 
2369             // unshade button
2370             if (titleBar->subControls & SC_TitleBarUnshadeButton && (titleBar->titleBarFlags & Qt::WindowShadeButtonHint)) {
2371                 QRect unshadeButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarUnshadeButton, widget);
2372                 if (unshadeButtonRect.isValid()) {
2373                     bool hover = (titleBar->activeSubControls & SC_TitleBarUnshadeButton) && (titleBar->state & State_MouseOver);
2374                     bool sunken = (titleBar->activeSubControls & SC_TitleBarUnshadeButton) && (titleBar->state & State_Sunken);
2375                     qt_fusion_draw_mdibutton(painter, titleBar, unshadeButtonRect, hover, sunken);
2376                     qt_fusion_draw_arrow(Qt::DownArrow, painter, option, unshadeButtonRect.adjusted(5, 7, -5, -7), textColor);
2377                 }
2378             }
2379 
2380             if ((titleBar->subControls & SC_TitleBarSysMenu) && (titleBar->titleBarFlags & Qt::WindowSystemMenuHint)) {
2381                 QRect iconRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarSysMenu, widget);
2382                 if (iconRect.isValid()) {
2383                     if (!titleBar->icon.isNull()) {
2384                         titleBar->icon.paint(painter, iconRect);
2385                     } else {
2386                         QStyleOption tool = *titleBar;
2387                         QPixmap pm = proxy()->standardIcon(SP_TitleBarMenuButton, &tool, widget).pixmap(16, 16);
2388                         tool.rect = iconRect;
2389                         painter->save();
2390                         proxy()->drawItemPixmap(painter, iconRect, Qt::AlignCenter, pm);
2391                         painter->restore();
2392                     }
2393                 }
2394             }
2395         }
2396         painter->restore();
2397         break;
2398 #if QT_CONFIG(slider)
2399     case CC_ScrollBar:
2400         painter->save();
2401         if (const QStyleOptionSlider *scrollBar = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
2402             bool wasActive = false;
2403             qreal expandScale = 1.0;
2404             qreal expandOffset = -1.0;
2405             QObject *styleObject = option->styleObject;
2406             if (styleObject && proxy()->styleHint(SH_ScrollBar_Transient, option, widget)) {
2407 #if QT_CONFIG(animation)
2408                 qreal opacity = 0.0;
2409                 bool shouldExpand = false;
2410                 const qreal maxExpandScale = 13.0 / 9.0;
2411 #endif
2412 
2413                 int oldPos = styleObject->property("_q_stylepos").toInt();
2414                 int oldMin = styleObject->property("_q_stylemin").toInt();
2415                 int oldMax = styleObject->property("_q_stylemax").toInt();
2416                 QRect oldRect = styleObject->property("_q_stylerect").toRect();
2417                 QStyle::State oldState = static_cast<QStyle::State>(qvariant_cast<QStyle::State::Int>(styleObject->property("_q_stylestate")));
2418                 uint oldActiveControls = styleObject->property("_q_stylecontrols").toUInt();
2419 
2420                 // a scrollbar is transient when the scrollbar itself and
2421                 // its sibling are both inactive (ie. not pressed/hovered/moved)
2422                 bool transient = !option->activeSubControls && !(option->state & State_On);
2423 
2424                 if (!transient ||
2425                         oldPos != scrollBar->sliderPosition ||
2426                         oldMin != scrollBar->minimum ||
2427                         oldMax != scrollBar->maximum ||
2428                         oldRect != scrollBar->rect ||
2429                         oldState != scrollBar->state ||
2430                         oldActiveControls != scrollBar->activeSubControls) {
2431 
2432                     styleObject->setProperty("_q_stylepos", scrollBar->sliderPosition);
2433                     styleObject->setProperty("_q_stylemin", scrollBar->minimum);
2434                     styleObject->setProperty("_q_stylemax", scrollBar->maximum);
2435                     styleObject->setProperty("_q_stylerect", scrollBar->rect);
2436                     styleObject->setProperty("_q_stylestate", static_cast<QStyle::State::Int>(scrollBar->state));
2437                     styleObject->setProperty("_q_stylecontrols", static_cast<uint>(scrollBar->activeSubControls));
2438 
2439 #if QT_CONFIG(animation)
2440                     // if the scrollbar is transient or its attributes, geometry or
2441                     // state has changed, the opacity is reset back to 100% opaque
2442                     opacity = 1.0;
2443 
2444                     QScrollbarStyleAnimation *anim  = qobject_cast<QScrollbarStyleAnimation *>(d->animation(styleObject));
2445                     if (transient) {
2446                         if (!anim) {
2447                             anim = new QScrollbarStyleAnimation(QScrollbarStyleAnimation::Deactivating, styleObject);
2448                             d->startAnimation(anim);
2449                         } else if (anim->mode() == QScrollbarStyleAnimation::Deactivating) {
2450                             // the scrollbar was already fading out while the
2451                             // state changed -> restart the fade out animation
2452                             anim->setCurrentTime(0);
2453                         }
2454                     } else if (anim && anim->mode() == QScrollbarStyleAnimation::Deactivating) {
2455                         d->stopAnimation(styleObject);
2456                     }
2457 #endif // animation
2458                 }
2459 
2460 #if QT_CONFIG(animation)
2461                 QScrollbarStyleAnimation *anim = qobject_cast<QScrollbarStyleAnimation *>(d->animation(styleObject));
2462                 if (anim && anim->mode() == QScrollbarStyleAnimation::Deactivating) {
2463                     // once a scrollbar was active (hovered/pressed), it retains
2464                     // the active look even if it's no longer active while fading out
2465                     if (oldActiveControls)
2466                         anim->setActive(true);
2467 
2468                     wasActive = anim->wasActive();
2469                     opacity = anim->currentValue();
2470                 }
2471 
2472                 shouldExpand = (option->activeSubControls || wasActive);
2473                 if (shouldExpand) {
2474                     if (!anim && !oldActiveControls) {
2475                         // Start expand animation only once and when entering
2476                         anim = new QScrollbarStyleAnimation(QScrollbarStyleAnimation::Activating, styleObject);
2477                         d->startAnimation(anim);
2478                     }
2479                     if (anim && anim->mode() == QScrollbarStyleAnimation::Activating) {
2480                         expandScale = 1.0 + (maxExpandScale - 1.0) * anim->currentValue();
2481                         expandOffset = 5.5 * anim->currentValue() - 1;
2482                     } else {
2483                         // Keep expanded state after the animation ends, and when fading out
2484                         expandScale = maxExpandScale;
2485                         expandOffset = 4.5;
2486                     }
2487                 }
2488                 painter->setOpacity(opacity);
2489 #endif // animation
2490             }
2491 
2492             bool transient = proxy()->styleHint(SH_ScrollBar_Transient, option, widget);
2493             bool horizontal = scrollBar->orientation == Qt::Horizontal;
2494             bool sunken = scrollBar->state & State_Sunken;
2495 
2496             QRect scrollBarSubLine = proxy()->subControlRect(control, scrollBar, SC_ScrollBarSubLine, widget);
2497             QRect scrollBarAddLine = proxy()->subControlRect(control, scrollBar, SC_ScrollBarAddLine, widget);
2498             QRect scrollBarSlider = proxy()->subControlRect(control, scrollBar, SC_ScrollBarSlider, widget);
2499             QRect scrollBarGroove = proxy()->subControlRect(control, scrollBar, SC_ScrollBarGroove, widget);
2500 
2501             QRect rect = option->rect;
2502             QColor alphaOutline = outline;
2503             alphaOutline.setAlpha(180);
2504 
2505             QColor arrowColor = option->palette.windowText().color();
2506             arrowColor.setAlpha(160);
2507 
2508             const QColor bgColor = QStyleHelper::backgroundColor(option->palette, widget);
2509             const bool isDarkBg = bgColor.red() < 128 && bgColor.green() < 128 && bgColor.blue() < 128;
2510 
2511             if (transient) {
2512                 if (horizontal) {
2513                     rect.setY(rect.y() + 4.5 - expandOffset);
2514                     scrollBarSlider.setY(scrollBarSlider.y() + 4.5 - expandOffset);
2515                     scrollBarGroove.setY(scrollBarGroove.y() + 4.5 - expandOffset);
2516 
2517                     rect.setHeight(rect.height() * expandScale);
2518                     scrollBarGroove.setHeight(scrollBarGroove.height() * expandScale);
2519                 } else {
2520                     rect.setX(rect.x() + 4.5 - expandOffset);
2521                     scrollBarSlider.setX(scrollBarSlider.x() + 4.5 - expandOffset);
2522                     scrollBarGroove.setX(scrollBarGroove.x() + 4.5 - expandOffset);
2523 
2524                     rect.setWidth(rect.width() * expandScale);
2525                     scrollBarGroove.setWidth(scrollBarGroove.width() * expandScale);
2526                 }
2527             }
2528 
2529             // Paint groove
2530             if ((!transient || scrollBar->activeSubControls || wasActive) && scrollBar->subControls & SC_ScrollBarGroove) {
2531                 QLinearGradient gradient(rect.center().x(), rect.top(),
2532                                          rect.center().x(), rect.bottom());
2533                 if (!horizontal)
2534                     gradient = QLinearGradient(rect.left(), rect.center().y(),
2535                                                rect.right(), rect.center().y());
2536                 if (!transient || !isDarkBg) {
2537                     gradient.setColorAt(0, buttonColor.darker(107));
2538                     gradient.setColorAt(0.1, buttonColor.darker(105));
2539                     gradient.setColorAt(0.9, buttonColor.darker(105));
2540                     gradient.setColorAt(1, buttonColor.darker(107));
2541                 } else {
2542                     gradient.setColorAt(0, bgColor.lighter(157));
2543                     gradient.setColorAt(0.1, bgColor.lighter(155));
2544                     gradient.setColorAt(0.9, bgColor.lighter(155));
2545                     gradient.setColorAt(1, bgColor.lighter(157));
2546                 }
2547 
2548                 painter->save();
2549                 if (transient)
2550                     painter->setOpacity(0.8);
2551                 painter->fillRect(rect, gradient);
2552                 painter->setPen(Qt::NoPen);
2553                 if (transient)
2554                     painter->setOpacity(0.4);
2555                 painter->setPen(alphaOutline);
2556                 if (horizontal)
2557                     painter->drawLine(rect.topLeft(), rect.topRight());
2558                 else
2559                     painter->drawLine(rect.topLeft(), rect.bottomLeft());
2560 
2561                 QColor subtleEdge = alphaOutline;
2562                 subtleEdge.setAlpha(40);
2563                 painter->setPen(subtleEdge);
2564                 painter->setBrush(Qt::NoBrush);
2565                 painter->setClipRect(scrollBarGroove.adjusted(1, 0, -1, -3));
2566                 painter->drawRect(scrollBarGroove.adjusted(1, 0, -1, -1));
2567                 painter->restore();
2568             }
2569 
2570             QRect pixmapRect = scrollBarSlider;
2571             QLinearGradient gradient(pixmapRect.center().x(), pixmapRect.top(),
2572                                      pixmapRect.center().x(), pixmapRect.bottom());
2573             if (!horizontal)
2574                 gradient = QLinearGradient(pixmapRect.left(), pixmapRect.center().y(),
2575                                            pixmapRect.right(), pixmapRect.center().y());
2576 
2577             QLinearGradient highlightedGradient = gradient;
2578 
2579             QColor midColor2 = mergedColors(gradientStartColor, gradientStopColor, 40);
2580             gradient.setColorAt(0, d->buttonColor(option->palette).lighter(108));
2581             gradient.setColorAt(1, d->buttonColor(option->palette));
2582 
2583             highlightedGradient.setColorAt(0, gradientStartColor.darker(102));
2584             highlightedGradient.setColorAt(1, gradientStopColor.lighter(102));
2585 
2586             // Paint slider
2587             if (scrollBar->subControls & SC_ScrollBarSlider) {
2588                 if (transient) {
2589                     QRect rect = scrollBarSlider.adjusted(horizontal ? 1 : 2, horizontal ? 2 : 1, -1, -1);
2590                     painter->setPen(Qt::NoPen);
2591                     painter->setBrush(isDarkBg ? d->lightShade() : d->darkShade());
2592                     int r = qMin(rect.width(), rect.height()) / 2;
2593 
2594                     painter->save();
2595                     painter->setRenderHint(QPainter::Antialiasing, true);
2596                     painter->drawRoundedRect(rect, r, r);
2597                     painter->restore();
2598                 } else {
2599                     QRect pixmapRect = scrollBarSlider;
2600                     painter->setPen(QPen(alphaOutline));
2601                     if (option->state & State_Sunken && scrollBar->activeSubControls & SC_ScrollBarSlider)
2602                         painter->setBrush(midColor2);
2603                     else if (option->state & State_MouseOver && scrollBar->activeSubControls & SC_ScrollBarSlider)
2604                         painter->setBrush(highlightedGradient);
2605                     else
2606                         painter->setBrush(gradient);
2607 
2608                     painter->drawRect(pixmapRect.adjusted(horizontal ? -1 : 0, horizontal ? 0 : -1, horizontal ? 0 : 1, horizontal ? 1 : 0));
2609 
2610                     painter->setPen(d->innerContrastLine());
2611                     painter->drawRect(scrollBarSlider.adjusted(horizontal ? 0 : 1, horizontal ? 1 : 0, -1, -1));
2612 
2613                     // Outer shadow
2614                     //                  painter->setPen(subtleEdge);
2615                     //                  if (horizontal) {
2616                     ////                    painter->drawLine(scrollBarSlider.topLeft() + QPoint(-2, 0), scrollBarSlider.bottomLeft() + QPoint(2, 0));
2617                     ////                    painter->drawLine(scrollBarSlider.topRight() + QPoint(-2, 0), scrollBarSlider.bottomRight() + QPoint(2, 0));
2618                     //                  } else {
2619                     ////                    painter->drawLine(pixmapRect.topLeft() + QPoint(0, -2), pixmapRect.bottomLeft() + QPoint(0, -2));
2620                     ////                    painter->drawLine(pixmapRect.topRight() + QPoint(0, 2), pixmapRect.bottomRight() + QPoint(0, 2));
2621                     //                  }
2622                 }
2623             }
2624 
2625             // The SubLine (up/left) buttons
2626             if (!transient && scrollBar->subControls & SC_ScrollBarSubLine) {
2627                 if ((scrollBar->activeSubControls & SC_ScrollBarSubLine) && sunken)
2628                     painter->setBrush(gradientStopColor);
2629                 else if ((scrollBar->activeSubControls & SC_ScrollBarSubLine))
2630                     painter->setBrush(highlightedGradient);
2631                 else
2632                     painter->setBrush(gradient);
2633 
2634                 painter->setPen(Qt::NoPen);
2635                 painter->drawRect(scrollBarSubLine.adjusted(horizontal ? 0 : 1, horizontal ? 1 : 0, 0, 0));
2636                 painter->setPen(QPen(alphaOutline));
2637                 if (option->state & State_Horizontal) {
2638                     if (option->direction == Qt::RightToLeft) {
2639                         pixmapRect.setLeft(scrollBarSubLine.left());
2640                         painter->drawLine(pixmapRect.topLeft(), pixmapRect.bottomLeft());
2641                     } else {
2642                         pixmapRect.setRight(scrollBarSubLine.right());
2643                         painter->drawLine(pixmapRect.topRight(), pixmapRect.bottomRight());
2644                     }
2645                 } else {
2646                     pixmapRect.setBottom(scrollBarSubLine.bottom());
2647                     painter->drawLine(pixmapRect.bottomLeft(), pixmapRect.bottomRight());
2648                 }
2649 
2650                 QRect upRect = scrollBarSubLine.adjusted(horizontal ? 0 : 1, horizontal ? 1 : 0, horizontal ? -2 : -1, horizontal ? -1 : -2);
2651                 painter->setBrush(Qt::NoBrush);
2652                 painter->setPen(d->innerContrastLine());
2653                 painter->drawRect(upRect);
2654 
2655                 // Arrows
2656                 Qt::ArrowType arrowType = Qt::UpArrow;
2657                 if (option->state & State_Horizontal)
2658                     arrowType = option->direction == Qt::LeftToRight ? Qt::LeftArrow : Qt::RightArrow;
2659                 qt_fusion_draw_arrow(arrowType, painter, option, upRect, arrowColor);
2660             }
2661 
2662             // The AddLine (down/right) button
2663             if (!transient && scrollBar->subControls & SC_ScrollBarAddLine) {
2664                 if ((scrollBar->activeSubControls & SC_ScrollBarAddLine) && sunken)
2665                     painter->setBrush(gradientStopColor);
2666                 else if ((scrollBar->activeSubControls & SC_ScrollBarAddLine))
2667                     painter->setBrush(midColor2);
2668                 else
2669                     painter->setBrush(gradient);
2670 
2671                 painter->setPen(Qt::NoPen);
2672                 painter->drawRect(scrollBarAddLine.adjusted(horizontal ? 0 : 1, horizontal ? 1 : 0, 0, 0));
2673                 painter->setPen(QPen(alphaOutline, 1));
2674                 if (option->state & State_Horizontal) {
2675                     if (option->direction == Qt::LeftToRight) {
2676                         pixmapRect.setLeft(scrollBarAddLine.left());
2677                         painter->drawLine(pixmapRect.topLeft(), pixmapRect.bottomLeft());
2678                     } else {
2679                         pixmapRect.setRight(scrollBarAddLine.right());
2680                         painter->drawLine(pixmapRect.topRight(), pixmapRect.bottomRight());
2681                     }
2682                 } else {
2683                     pixmapRect.setTop(scrollBarAddLine.top());
2684                     painter->drawLine(pixmapRect.topLeft(), pixmapRect.topRight());
2685                 }
2686 
2687                 QRect downRect = scrollBarAddLine.adjusted(1, 1, -1, -1);
2688                 painter->setPen(d->innerContrastLine());
2689                 painter->setBrush(Qt::NoBrush);
2690                 painter->drawRect(downRect);
2691 
2692                 Qt::ArrowType arrowType = Qt::DownArrow;
2693                 if (option->state & State_Horizontal)
2694                     arrowType = option->direction == Qt::LeftToRight ? Qt::RightArrow : Qt::LeftArrow;
2695                 qt_fusion_draw_arrow(arrowType, painter, option, downRect, arrowColor);
2696             }
2697 
2698         }
2699         painter->restore();
2700         break;;
2701 #endif // QT_CONFIG(slider)
2702     case CC_ComboBox:
2703         painter->save();
2704         if (const QStyleOptionComboBox *comboBox = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
2705             bool hasFocus = option->state & State_HasFocus && option->state & State_KeyboardFocusChange;
2706             bool sunken = comboBox->state & State_On; // play dead, if combobox has no items
2707             bool isEnabled = (comboBox->state & State_Enabled);
2708             QPixmap cache;
2709             QString pixmapName = QStyleHelper::uniqueName(QLatin1String("combobox"), option, comboBox->rect.size());
2710             if (sunken)
2711                 pixmapName += QLatin1String("-sunken");
2712             if (comboBox->editable)
2713                 pixmapName += QLatin1String("-editable");
2714             if (isEnabled)
2715                 pixmapName += QLatin1String("-enabled");
2716             if (!comboBox->frame)
2717                 pixmapName += QLatin1String("-frameless");
2718 
2719             if (!QPixmapCache::find(pixmapName, &cache)) {
2720                 cache = styleCachePixmap(comboBox->rect.size());
2721                 cache.fill(Qt::transparent);
2722                 QPainter cachePainter(&cache);
2723                 QRect pixmapRect(0, 0, comboBox->rect.width(), comboBox->rect.height());
2724                 QStyleOptionComboBox comboBoxCopy = *comboBox;
2725                 comboBoxCopy.rect = pixmapRect;
2726 
2727                 QRect rect = pixmapRect;
2728                 QRect downArrowRect = proxy()->subControlRect(CC_ComboBox, &comboBoxCopy,
2729                                                               SC_ComboBoxArrow, widget);
2730                 // Draw a line edit
2731                 if (comboBox->editable) {
2732                     QStyleOptionFrame  buttonOption;
2733                     buttonOption.QStyleOption::operator=(*comboBox);
2734                     buttonOption.rect = rect;
2735                     buttonOption.state = (comboBox->state & (State_Enabled | State_MouseOver | State_HasFocus))
2736                             | State_KeyboardFocusChange; // Always show hig
2737 
2738                     if (sunken) {
2739                         buttonOption.state |= State_Sunken;
2740                         buttonOption.state &= ~State_MouseOver;
2741                     }
2742 
2743                     if (comboBox->frame) {
2744                         cachePainter.save();
2745                         cachePainter.setRenderHint(QPainter::Antialiasing, true);
2746                         cachePainter.translate(0.5, 0.5);
2747                         cachePainter.setPen(Qt::NoPen);
2748                         cachePainter.setBrush(buttonOption.palette.base());
2749                         cachePainter.drawRoundedRect(rect.adjusted(0, 0, -1, -1), 2, 2);
2750                         cachePainter.restore();
2751                         proxy()->drawPrimitive(PE_FrameLineEdit, &buttonOption, &cachePainter, widget);
2752                     }
2753 
2754                     // Draw button clipped
2755                     cachePainter.save();
2756                     cachePainter.setClipRect(downArrowRect.adjusted(0, 0, 1, 0));
2757                     buttonOption.rect.setLeft(comboBox->direction == Qt::LeftToRight ?
2758                                                   downArrowRect.left() - 6: downArrowRect.right() + 6);
2759                     proxy()->drawPrimitive(PE_PanelButtonCommand, &buttonOption, &cachePainter, widget);
2760                     cachePainter.restore();
2761                     cachePainter.setPen( QPen(hasFocus ? option->palette.highlight() : outline.lighter(110), 1));
2762 
2763                     if (!sunken) {
2764                         int borderSize = 1;
2765                         if (comboBox->direction == Qt::RightToLeft) {
2766                             cachePainter.drawLine(QPoint(downArrowRect.right() - 1, downArrowRect.top() + borderSize ),
2767                                                   QPoint(downArrowRect.right() - 1, downArrowRect.bottom() - borderSize));
2768                         } else {
2769                             cachePainter.drawLine(QPoint(downArrowRect.left() , downArrowRect.top() + borderSize),
2770                                                   QPoint(downArrowRect.left() , downArrowRect.bottom() - borderSize));
2771                         }
2772                     } else {
2773                         if (comboBox->direction == Qt::RightToLeft) {
2774                             cachePainter.drawLine(QPoint(downArrowRect.right(), downArrowRect.top() + 2),
2775                                                   QPoint(downArrowRect.right(), downArrowRect.bottom() - 2));
2776 
2777                         } else {
2778                             cachePainter.drawLine(QPoint(downArrowRect.left(), downArrowRect.top() + 2),
2779                                                   QPoint(downArrowRect.left(), downArrowRect.bottom() - 2));
2780                         }
2781                     }
2782                 } else {
2783                     QStyleOptionButton buttonOption;
2784                     buttonOption.QStyleOption::operator=(*comboBox);
2785                     buttonOption.rect = rect;
2786                     buttonOption.state = comboBox->state & (State_Enabled | State_MouseOver | State_HasFocus | State_KeyboardFocusChange);
2787                     if (sunken) {
2788                         buttonOption.state |= State_Sunken;
2789                         buttonOption.state &= ~State_MouseOver;
2790                     }
2791                     proxy()->drawPrimitive(PE_PanelButtonCommand, &buttonOption, &cachePainter, widget);
2792                 }
2793                 if (comboBox->subControls & SC_ComboBoxArrow) {
2794                     // Draw the up/down arrow
2795                     QColor arrowColor = option->palette.buttonText().color();
2796                     arrowColor.setAlpha(160);
2797                     qt_fusion_draw_arrow(Qt::DownArrow, &cachePainter, option, downArrowRect, arrowColor);
2798                 }
2799                 cachePainter.end();
2800                 QPixmapCache::insert(pixmapName, cache);
2801             }
2802             painter->drawPixmap(comboBox->rect.topLeft(), cache);
2803         }
2804         painter->restore();
2805         break;
2806 #if QT_CONFIG(slider)
2807     case CC_Slider:
2808         if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
2809             QRect groove = proxy()->subControlRect(CC_Slider, option, SC_SliderGroove, widget);
2810             QRect handle = proxy()->subControlRect(CC_Slider, option, SC_SliderHandle, widget);
2811 
2812             bool horizontal = slider->orientation == Qt::Horizontal;
2813             bool ticksAbove = slider->tickPosition & QSlider::TicksAbove;
2814             bool ticksBelow = slider->tickPosition & QSlider::TicksBelow;
2815             QColor activeHighlight = d->highlight(option->palette);
2816             QPixmap cache;
2817             QBrush oldBrush = painter->brush();
2818             QPen oldPen = painter->pen();
2819             QColor shadowAlpha(Qt::black);
2820             shadowAlpha.setAlpha(10);
2821             if (option->state & State_HasFocus && option->state & State_KeyboardFocusChange)
2822                 outline = d->highlightedOutline(option->palette);
2823 
2824 
2825             if ((option->subControls & SC_SliderGroove) && groove.isValid()) {
2826                 QColor grooveColor;
2827                 grooveColor.setHsv(buttonColor.hue(),
2828                                    qMin(255, (int)(buttonColor.saturation())),
2829                                    qMin(255, (int)(buttonColor.value()*0.9)));
2830                 QString groovePixmapName = QStyleHelper::uniqueName(QLatin1String("slider_groove"), option, groove.size());
2831                 QRect pixmapRect(0, 0, groove.width(), groove.height());
2832 
2833                 // draw background groove
2834                 if (!QPixmapCache::find(groovePixmapName, &cache)) {
2835                     cache = styleCachePixmap(pixmapRect.size());
2836                     cache.fill(Qt::transparent);
2837                     QPainter groovePainter(&cache);
2838                     groovePainter.setRenderHint(QPainter::Antialiasing, true);
2839                     groovePainter.translate(0.5, 0.5);
2840                     QLinearGradient gradient;
2841                     if (horizontal) {
2842                         gradient.setStart(pixmapRect.center().x(), pixmapRect.top());
2843                         gradient.setFinalStop(pixmapRect.center().x(), pixmapRect.bottom());
2844                     }
2845                     else {
2846                         gradient.setStart(pixmapRect.left(), pixmapRect.center().y());
2847                         gradient.setFinalStop(pixmapRect.right(), pixmapRect.center().y());
2848                     }
2849                     groovePainter.setPen(QPen(outline));
2850                     gradient.setColorAt(0, grooveColor.darker(110));
2851                     gradient.setColorAt(1, grooveColor.lighter(110));//palette.button().color().darker(115));
2852                     groovePainter.setBrush(gradient);
2853                     groovePainter.drawRoundedRect(pixmapRect.adjusted(1, 1, -2, -2), 1, 1);
2854                     groovePainter.end();
2855                     QPixmapCache::insert(groovePixmapName, cache);
2856                 }
2857                 painter->drawPixmap(groove.topLeft(), cache);
2858 
2859                 // draw blue groove highlight
2860                 QRect clipRect;
2861                 groovePixmapName += QLatin1String("_blue");
2862                 if (!QPixmapCache::find(groovePixmapName, &cache)) {
2863                     cache = styleCachePixmap(pixmapRect.size());
2864                     cache.fill(Qt::transparent);
2865                     QPainter groovePainter(&cache);
2866                     QLinearGradient gradient;
2867                     if (horizontal) {
2868                         gradient.setStart(pixmapRect.center().x(), pixmapRect.top());
2869                         gradient.setFinalStop(pixmapRect.center().x(), pixmapRect.bottom());
2870                     }
2871                     else {
2872                         gradient.setStart(pixmapRect.left(), pixmapRect.center().y());
2873                         gradient.setFinalStop(pixmapRect.right(), pixmapRect.center().y());
2874                     }
2875                     QColor highlight = d->highlight(option->palette);
2876                     QColor highlightedoutline = highlight.darker(140);
2877                     if (qGray(outline.rgb()) > qGray(highlightedoutline.rgb()))
2878                         outline = highlightedoutline;
2879 
2880 
2881                     groovePainter.setRenderHint(QPainter::Antialiasing, true);
2882                     groovePainter.translate(0.5, 0.5);
2883                     groovePainter.setPen(QPen(outline));
2884                     gradient.setColorAt(0, activeHighlight);
2885                     gradient.setColorAt(1, activeHighlight.lighter(130));
2886                     groovePainter.setBrush(gradient);
2887                     groovePainter.drawRoundedRect(pixmapRect.adjusted(1, 1, -2, -2), 1, 1);
2888                     groovePainter.setPen(d->innerContrastLine());
2889                     groovePainter.setBrush(Qt::NoBrush);
2890                     groovePainter.drawRoundedRect(pixmapRect.adjusted(2, 2, -3, -3), 1, 1);
2891                     groovePainter.end();
2892                     QPixmapCache::insert(groovePixmapName, cache);
2893                 }
2894                 if (horizontal) {
2895                     if (slider->upsideDown)
2896                         clipRect = QRect(handle.right(), groove.top(), groove.right() - handle.right(), groove.height());
2897                     else
2898                         clipRect = QRect(groove.left(), groove.top(), handle.left(), groove.height());
2899                 } else {
2900                     if (slider->upsideDown)
2901                         clipRect = QRect(groove.left(), handle.bottom(), groove.width(), groove.height() - handle.bottom());
2902                     else
2903                         clipRect = QRect(groove.left(), groove.top(), groove.width(), handle.top() - groove.top());
2904                 }
2905                 painter->save();
2906                 painter->setClipRect(clipRect.adjusted(0, 0, 1, 1), Qt::IntersectClip);
2907                 painter->drawPixmap(groove.topLeft(), cache);
2908                 painter->restore();
2909             }
2910 
2911             if (option->subControls & SC_SliderTickmarks) {
2912                 painter->setPen(outline);
2913                 int tickSize = proxy()->pixelMetric(PM_SliderTickmarkOffset, option, widget);
2914                 int available = proxy()->pixelMetric(PM_SliderSpaceAvailable, slider, widget);
2915                 int interval = slider->tickInterval;
2916                 if (interval <= 0) {
2917                     interval = slider->singleStep;
2918                     if (QStyle::sliderPositionFromValue(slider->minimum, slider->maximum, interval,
2919                                                         available)
2920                             - QStyle::sliderPositionFromValue(slider->minimum, slider->maximum,
2921                                                               0, available) < 3)
2922                         interval = slider->pageStep;
2923                 }
2924                 if (interval <= 0)
2925                     interval = 1;
2926 
2927                 int v = slider->minimum;
2928                 int len = proxy()->pixelMetric(PM_SliderLength, slider, widget);
2929                 while (v <= slider->maximum + 1) {
2930                     if (v == slider->maximum + 1 && interval == 1)
2931                         break;
2932                     const int v_ = qMin(v, slider->maximum);
2933                     int pos = sliderPositionFromValue(slider->minimum, slider->maximum,
2934                                                       v_, (horizontal
2935                                                            ? slider->rect.width()
2936                                                            : slider->rect.height()) - len,
2937                                                       slider->upsideDown) + len / 2;
2938                     int extra = 2 - ((v_ == slider->minimum || v_ == slider->maximum) ? 1 : 0);
2939 
2940                     if (horizontal) {
2941                         if (ticksAbove) {
2942                             painter->drawLine(pos, slider->rect.top() + extra,
2943                                               pos, slider->rect.top() + tickSize);
2944                         }
2945                         if (ticksBelow) {
2946                             painter->drawLine(pos, slider->rect.bottom() - extra,
2947                                               pos, slider->rect.bottom() - tickSize);
2948                         }
2949                     } else {
2950                         if (ticksAbove) {
2951                             painter->drawLine(slider->rect.left() + extra, pos,
2952                                               slider->rect.left() + tickSize, pos);
2953                         }
2954                         if (ticksBelow) {
2955                             painter->drawLine(slider->rect.right() - extra, pos,
2956                                               slider->rect.right() - tickSize, pos);
2957                         }
2958                     }
2959                     // in the case where maximum is max int
2960                     int nextInterval = v + interval;
2961                     if (nextInterval < v)
2962                         break;
2963                     v = nextInterval;
2964                 }
2965             }
2966             // draw handle
2967             if ((option->subControls & SC_SliderHandle) ) {
2968                 QString handlePixmapName = QStyleHelper::uniqueName(QLatin1String("slider_handle"), option, handle.size());
2969                 if (!QPixmapCache::find(handlePixmapName, &cache)) {
2970                     cache = styleCachePixmap(handle.size());
2971                     cache.fill(Qt::transparent);
2972                     QRect pixmapRect(0, 0, handle.width(), handle.height());
2973                     QPainter handlePainter(&cache);
2974                     QRect gradRect = pixmapRect.adjusted(2, 2, -2, -2);
2975 
2976                     // gradient fill
2977                     QRect r = pixmapRect.adjusted(1, 1, -2, -2);
2978                     QLinearGradient gradient = qt_fusion_gradient(gradRect, d->buttonColor(option->palette),horizontal ? TopDown : FromLeft);
2979 
2980                     handlePainter.setRenderHint(QPainter::Antialiasing, true);
2981                     handlePainter.translate(0.5, 0.5);
2982 
2983                     handlePainter.setPen(Qt::NoPen);
2984                     handlePainter.setBrush(QColor(0, 0, 0, 40));
2985                     handlePainter.drawRect(r.adjusted(-1, 2, 1, -2));
2986 
2987                     handlePainter.setPen(QPen(d->outline(option->palette)));
2988                     if (option->state & State_HasFocus && option->state & State_KeyboardFocusChange)
2989                         handlePainter.setPen(QPen(d->highlightedOutline(option->palette)));
2990 
2991                     handlePainter.setBrush(gradient);
2992                     handlePainter.drawRoundedRect(r, 2, 2);
2993                     handlePainter.setBrush(Qt::NoBrush);
2994                     handlePainter.setPen(d->innerContrastLine());
2995                     handlePainter.drawRoundedRect(r.adjusted(1, 1, -1, -1), 2, 2);
2996 
2997                     QColor cornerAlpha = outline.darker(120);
2998                     cornerAlpha.setAlpha(80);
2999 
3000                     //handle shadow
3001                     handlePainter.setPen(shadowAlpha);
3002                     handlePainter.drawLine(QPoint(r.left() + 2, r.bottom() + 1), QPoint(r.right() - 2, r.bottom() + 1));
3003                     handlePainter.drawLine(QPoint(r.right() + 1, r.bottom() - 3), QPoint(r.right() + 1, r.top() + 4));
3004                     handlePainter.drawLine(QPoint(r.right() - 1, r.bottom()), QPoint(r.right() + 1, r.bottom() - 2));
3005 
3006                     handlePainter.end();
3007                     QPixmapCache::insert(handlePixmapName, cache);
3008                 }
3009 
3010                 painter->drawPixmap(handle.topLeft(), cache);
3011 
3012             }
3013             painter->setBrush(oldBrush);
3014             painter->setPen(oldPen);
3015         }
3016         break;
3017 #endif // QT_CONFIG(slider)
3018 #if QT_CONFIG(dial)
3019     case CC_Dial:
3020         if (const QStyleOptionSlider *dial = qstyleoption_cast<const QStyleOptionSlider *>(option))
3021             QStyleHelper::drawDial(dial, painter);
3022         break;
3023 #endif
3024     default:
3025         QCommonStyle::drawComplexControl(control, option, painter, widget);
3026         break;
3027     }
3028 }
3029 
3030 /*!
3031   \reimp
3032 */
pixelMetric(PixelMetric metric,const QStyleOption * option,const QWidget * widget) const3033 int QFusionStyle::pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const
3034 {
3035     int val = -1;
3036     switch (metric) {
3037     case PM_SliderTickmarkOffset:
3038         val = 4;
3039         break;
3040     case PM_HeaderMargin:
3041     case PM_ToolTipLabelFrameWidth:
3042         val = 2;
3043         break;
3044     case PM_ButtonDefaultIndicator:
3045     case PM_ButtonShiftHorizontal:
3046     case PM_ButtonShiftVertical:
3047         val = 0;
3048         break;
3049     case PM_MessageBoxIconSize:
3050         val = 48;
3051         break;
3052     case PM_ListViewIconSize:
3053         val = 24;
3054         break;
3055     case PM_DialogButtonsSeparator:
3056     case PM_ScrollBarSliderMin:
3057         val = 26;
3058         break;
3059     case PM_TitleBarHeight:
3060         val = 24;
3061         break;
3062     case PM_ScrollBarExtent:
3063         val = 14;
3064         break;
3065     case PM_SliderThickness:
3066     case PM_SliderLength:
3067         val = 15;
3068         break;
3069     case PM_DockWidgetTitleMargin:
3070         val = 1;
3071         break;
3072     case PM_SpinBoxFrameWidth:
3073         val = 3;
3074         break;
3075     case PM_MenuVMargin:
3076     case PM_MenuHMargin:
3077     case PM_MenuPanelWidth:
3078         val = 0;
3079         break;
3080     case PM_MenuBarItemSpacing:
3081         val = 6;
3082         break;
3083     case PM_MenuBarVMargin:
3084     case PM_MenuBarHMargin:
3085     case PM_MenuBarPanelWidth:
3086         val = 0;
3087         break;
3088     case PM_ToolBarHandleExtent:
3089         val = 9;
3090         break;
3091     case PM_ToolBarItemSpacing:
3092         val = 1;
3093         break;
3094     case PM_ToolBarFrameWidth:
3095     case PM_ToolBarItemMargin:
3096         val = 2;
3097         break;
3098     case PM_SmallIconSize:
3099     case PM_ButtonIconSize:
3100         val = 16;
3101         break;
3102     case PM_DockWidgetTitleBarButtonMargin:
3103         val = 2;
3104         break;
3105     case PM_TitleBarButtonSize:
3106         val = 19;
3107         break;
3108     case PM_MaximumDragDistance:
3109         return -1; // Do not dpi-scale because the value is magic
3110     case PM_TabCloseIndicatorWidth:
3111     case PM_TabCloseIndicatorHeight:
3112         val = 20;
3113         break;
3114     case PM_TabBarTabVSpace:
3115         val = 12;
3116         break;
3117     case PM_TabBarTabOverlap:
3118         val = 1;
3119         break;
3120     case PM_TabBarBaseOverlap:
3121         val = 2;
3122         break;
3123     case PM_SubMenuOverlap:
3124         val = -1;
3125         break;
3126     case PM_DockWidgetHandleExtent:
3127     case PM_SplitterWidth:
3128         val = 4;
3129         break;
3130     case PM_IndicatorHeight:
3131     case PM_IndicatorWidth:
3132     case PM_ExclusiveIndicatorHeight:
3133     case PM_ExclusiveIndicatorWidth:
3134         val = 14;
3135         break;
3136     case PM_ScrollView_ScrollBarSpacing:
3137         val = 0;
3138         break;
3139     case PM_ScrollView_ScrollBarOverlap:
3140         if (proxy()->styleHint(SH_ScrollBar_Transient, option, widget))
3141             return proxy()->pixelMetric(PM_ScrollBarExtent, option, widget);
3142         val = 0;
3143         break;
3144     case PM_DefaultFrameWidth:
3145         return 1; // Do not dpi-scale because the drawn frame is always exactly 1 pixel thick
3146     default:
3147         return QCommonStyle::pixelMetric(metric, option, widget);
3148     }
3149     return QStyleHelper::dpiScaled(val, option);
3150 }
3151 
3152 /*!
3153   \reimp
3154 */
sizeFromContents(ContentsType type,const QStyleOption * option,const QSize & size,const QWidget * widget) const3155 QSize QFusionStyle::sizeFromContents(ContentsType type, const QStyleOption *option,
3156                                      const QSize &size, const QWidget *widget) const
3157 {
3158     QSize newSize = QCommonStyle::sizeFromContents(type, option, size, widget);
3159     switch (type) {
3160     case CT_PushButton:
3161         if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) {
3162             if (!btn->text.isEmpty() && newSize.width() < 80)
3163                 newSize.setWidth(80);
3164             if (!btn->icon.isNull() && btn->iconSize.height() > 16)
3165                 newSize -= QSize(0, 2);
3166         }
3167         break;
3168     case CT_GroupBox:
3169         if (option) {
3170             int topMargin = qMax(pixelMetric(PM_ExclusiveIndicatorHeight), option->fontMetrics.height()) + groupBoxTopMargin;
3171             newSize += QSize(10, topMargin); // Add some space below the groupbox
3172         }
3173         break;
3174     case CT_RadioButton:
3175     case CT_CheckBox:
3176         newSize += QSize(0, 1);
3177         break;
3178     case CT_ToolButton:
3179         newSize += QSize(2, 2);
3180         break;
3181     case CT_SpinBox:
3182         newSize += QSize(0, -3);
3183         break;
3184     case CT_ComboBox:
3185         newSize += QSize(2, 4);
3186         break;
3187     case CT_LineEdit:
3188         newSize += QSize(0, 4);
3189         break;
3190     case CT_MenuBarItem:
3191         newSize += QSize(8, 5);
3192         break;
3193     case CT_MenuItem:
3194         if (const QStyleOptionMenuItem *menuItem = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) {
3195             int w = newSize.width();
3196             int maxpmw = menuItem->maxIconWidth;
3197             int tabSpacing = 20;
3198             if (menuItem->text.contains(QLatin1Char('\t')))
3199                 w += tabSpacing;
3200             else if (menuItem->menuItemType == QStyleOptionMenuItem::SubMenu)
3201                 w += 2 * QStyleHelper::dpiScaled(QFusionStylePrivate::menuArrowHMargin, option);
3202             else if (menuItem->menuItemType == QStyleOptionMenuItem::DefaultItem) {
3203                 QFontMetrics fm(menuItem->font);
3204                 QFont fontBold = menuItem->font;
3205                 fontBold.setBold(true);
3206                 QFontMetrics fmBold(fontBold);
3207                 w += fmBold.horizontalAdvance(menuItem->text) - fm.horizontalAdvance(menuItem->text);
3208             }
3209             const qreal dpi = QStyleHelper::dpi(option);
3210             const int checkcol = qMax<int>(maxpmw, QStyleHelper::dpiScaled(QFusionStylePrivate::menuCheckMarkWidth, dpi)); // Windows always shows a check column
3211             w += checkcol;
3212             w += QStyleHelper::dpiScaled(int(QFusionStylePrivate::menuRightBorder) + 10, dpi);
3213             newSize.setWidth(w);
3214             if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) {
3215                 if (!menuItem->text.isEmpty()) {
3216                     newSize.setHeight(menuItem->fontMetrics.height());
3217                 }
3218             }
3219             else if (!menuItem->icon.isNull()) {
3220 #if QT_CONFIG(combobox)
3221                 if (const QComboBox *combo = qobject_cast<const QComboBox*>(widget)) {
3222                     newSize.setHeight(qMax(combo->iconSize().height() + 2, newSize.height()));
3223                 }
3224 #endif
3225             }
3226             newSize.setWidth(newSize.width() + int(QStyleHelper::dpiScaled(12, dpi)));
3227             newSize.setWidth(qMax<int>(newSize.width(), int(QStyleHelper::dpiScaled(120, dpi))));
3228         }
3229         break;
3230     case CT_SizeGrip:
3231         newSize += QSize(4, 4);
3232         break;
3233     case CT_MdiControls:
3234         newSize -= QSize(1, 0);
3235         break;
3236     default:
3237         break;
3238     }
3239     return newSize;
3240 }
3241 
3242 /*!
3243   \reimp
3244 */
polish(QApplication * app)3245 void QFusionStyle::polish(QApplication *app)
3246 {
3247     QCommonStyle::polish(app);
3248 }
3249 
3250 /*!
3251   \reimp
3252 */
polish(QWidget * widget)3253 void QFusionStyle::polish(QWidget *widget)
3254 {
3255     QCommonStyle::polish(widget);
3256     if (false
3257 #if QT_CONFIG(abstractbutton)
3258             || qobject_cast<QAbstractButton*>(widget)
3259 #endif
3260 #if QT_CONFIG(combobox)
3261             || qobject_cast<QComboBox *>(widget)
3262 #endif
3263 #if QT_CONFIG(progressbar)
3264             || qobject_cast<QProgressBar *>(widget)
3265 #endif
3266 #if QT_CONFIG(scrollbar)
3267             || qobject_cast<QScrollBar *>(widget)
3268 #endif
3269 #if QT_CONFIG(splitter)
3270             || qobject_cast<QSplitterHandle *>(widget)
3271 #endif
3272 #if QT_CONFIG(abstractslider)
3273             || qobject_cast<QAbstractSlider *>(widget)
3274 #endif
3275 #if QT_CONFIG(spinbox)
3276             || qobject_cast<QAbstractSpinBox *>(widget)
3277 #endif
3278             || (widget->inherits("QDockSeparator"))
3279             || (widget->inherits("QDockWidgetSeparator"))
3280             ) {
3281         widget->setAttribute(Qt::WA_Hover, true);
3282         widget->setAttribute(Qt::WA_OpaquePaintEvent, false);
3283     }
3284 }
3285 
3286 /*!
3287   \reimp
3288 */
polish(QPalette & pal)3289 void QFusionStyle::polish(QPalette &pal)
3290 {
3291     QCommonStyle::polish(pal);
3292 }
3293 
3294 /*!
3295   \reimp
3296 */
unpolish(QWidget * widget)3297 void QFusionStyle::unpolish(QWidget *widget)
3298 {
3299     QCommonStyle::unpolish(widget);
3300     if (false
3301 #if QT_CONFIG(abstractbutton)
3302             || qobject_cast<QAbstractButton*>(widget)
3303 #endif
3304 #if QT_CONFIG(combobox)
3305             || qobject_cast<QComboBox *>(widget)
3306 #endif
3307 #if QT_CONFIG(progressbar)
3308             || qobject_cast<QProgressBar *>(widget)
3309 #endif
3310 #if QT_CONFIG(scrollbar)
3311             || qobject_cast<QScrollBar *>(widget)
3312 #endif
3313 #if QT_CONFIG(splitter)
3314             || qobject_cast<QSplitterHandle *>(widget)
3315 #endif
3316 #if QT_CONFIG(abstractslider)
3317             || qobject_cast<QAbstractSlider *>(widget)
3318 #endif
3319 #if QT_CONFIG(spinbox)
3320             || qobject_cast<QAbstractSpinBox *>(widget)
3321 #endif
3322             || (widget->inherits("QDockSeparator"))
3323             || (widget->inherits("QDockWidgetSeparator"))
3324             ) {
3325         widget->setAttribute(Qt::WA_Hover, false);
3326     }
3327 }
3328 
3329 /*!
3330   \reimp
3331 */
unpolish(QApplication * app)3332 void QFusionStyle::unpolish(QApplication *app)
3333 {
3334     QCommonStyle::unpolish(app);
3335 }
3336 
3337 /*!
3338   \reimp
3339 */
subControlRect(ComplexControl control,const QStyleOptionComplex * option,SubControl subControl,const QWidget * widget) const3340 QRect QFusionStyle::subControlRect(ComplexControl control, const QStyleOptionComplex *option,
3341                                    SubControl subControl, const QWidget *widget) const
3342 {
3343     QRect rect = QCommonStyle::subControlRect(control, option, subControl, widget);
3344 
3345     switch (control) {
3346 #if QT_CONFIG(slider)
3347     case CC_Slider:
3348         if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
3349             int tickSize = proxy()->pixelMetric(PM_SliderTickmarkOffset, option, widget);
3350             switch (subControl) {
3351             case SC_SliderHandle: {
3352                 if (slider->orientation == Qt::Horizontal) {
3353                     rect.setHeight(proxy()->pixelMetric(PM_SliderThickness, option));
3354                     rect.setWidth(proxy()->pixelMetric(PM_SliderLength, option));
3355                     int centerY = slider->rect.center().y() - rect.height() / 2;
3356                     if (slider->tickPosition & QSlider::TicksAbove)
3357                         centerY += tickSize;
3358                     if (slider->tickPosition & QSlider::TicksBelow)
3359                         centerY -= tickSize;
3360                     rect.moveTop(centerY);
3361                 } else {
3362                     rect.setWidth(proxy()->pixelMetric(PM_SliderThickness, option));
3363                     rect.setHeight(proxy()->pixelMetric(PM_SliderLength, option));
3364                     int centerX = slider->rect.center().x() - rect.width() / 2;
3365                     if (slider->tickPosition & QSlider::TicksAbove)
3366                         centerX += tickSize;
3367                     if (slider->tickPosition & QSlider::TicksBelow)
3368                         centerX -= tickSize;
3369                     rect.moveLeft(centerX);
3370                 }
3371             }
3372                 break;
3373             case SC_SliderGroove: {
3374                 QPoint grooveCenter = slider->rect.center();
3375                 const int grooveThickness = QStyleHelper::dpiScaled(7, option);
3376                 if (slider->orientation == Qt::Horizontal) {
3377                     rect.setHeight(grooveThickness);
3378                     if (slider->tickPosition & QSlider::TicksAbove)
3379                         grooveCenter.ry() += tickSize;
3380                     if (slider->tickPosition & QSlider::TicksBelow)
3381                         grooveCenter.ry() -= tickSize;
3382                 } else {
3383                     rect.setWidth(grooveThickness);
3384                     if (slider->tickPosition & QSlider::TicksAbove)
3385                         grooveCenter.rx() += tickSize;
3386                     if (slider->tickPosition & QSlider::TicksBelow)
3387                         grooveCenter.rx() -= tickSize;
3388                 }
3389                 rect.moveCenter(grooveCenter);
3390                 break;
3391             }
3392             default:
3393                 break;
3394             }
3395         }
3396         break;
3397 #endif // QT_CONFIG(slider)
3398 #if QT_CONFIG(spinbox)
3399     case CC_SpinBox:
3400         if (const QStyleOptionSpinBox *spinbox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) {
3401             int center = spinbox->rect.height() / 2;
3402             int fw = spinbox->frame ? 3 : 0; // Is drawn with 3 pixels width in drawComplexControl, independently from PM_SpinBoxFrameWidth
3403             int y = fw;
3404             const int buttonWidth = QStyleHelper::dpiScaled(14, option);
3405             int x, lx, rx;
3406             x = spinbox->rect.width() - y - buttonWidth + 2;
3407             lx = fw;
3408             rx = x - fw;
3409             switch (subControl) {
3410             case SC_SpinBoxUp:
3411                 if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons)
3412                     return QRect();
3413                 rect = QRect(x, fw, buttonWidth, center - fw);
3414                 break;
3415             case SC_SpinBoxDown:
3416                 if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons)
3417                     return QRect();
3418 
3419                 rect = QRect(x, center, buttonWidth, spinbox->rect.bottom() - center - fw + 1);
3420                 break;
3421             case SC_SpinBoxEditField:
3422                 if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons) {
3423                     rect = QRect(lx, fw, spinbox->rect.width() - 2*fw, spinbox->rect.height() - 2*fw);
3424                 } else {
3425                     rect = QRect(lx, fw, rx - qMax(fw - 1, 0), spinbox->rect.height() - 2*fw);
3426                 }
3427                 break;
3428             case SC_SpinBoxFrame:
3429                 rect = spinbox->rect;
3430             default:
3431                 break;
3432             }
3433             rect = visualRect(spinbox->direction, spinbox->rect, rect);
3434         }
3435         break;
3436 #endif // QT_CONFIG(spinbox)
3437     case CC_GroupBox:
3438         if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast<const QStyleOptionGroupBox *>(option)) {
3439             rect = option->rect;
3440             if (subControl == SC_GroupBoxFrame)
3441                 return rect.adjusted(0, 0, 0, 0);
3442             else if (subControl == SC_GroupBoxContents) {
3443                 QRect frameRect = option->rect.adjusted(0, 0, 0, -groupBoxBottomMargin);
3444                 int margin = 3;
3445                 int leftMarginExtension = 0;
3446                 const int exclusiveIndicatorHeight = option->subControls.testFlag(SC_GroupBoxCheckBox) ?
3447                                                         pixelMetric(PM_ExclusiveIndicatorHeight) : 0;
3448                 const int fontMetricsHeight = groupBox->text.isEmpty() ? 0 :
3449                                                 groupBox->fontMetrics.height();
3450                 const int topMargin = qMax(exclusiveIndicatorHeight, fontMetricsHeight) +
3451                                         groupBoxTopMargin;
3452                 return frameRect.adjusted(leftMarginExtension + margin, margin + topMargin, -margin, -margin - groupBoxBottomMargin);
3453             }
3454 
3455             QSize textSize = option->fontMetrics.boundingRect(groupBox->text).size() + QSize(2, 2);
3456             int indicatorWidth = proxy()->pixelMetric(PM_IndicatorWidth, option, widget);
3457             int indicatorHeight = proxy()->pixelMetric(PM_IndicatorHeight, option, widget);
3458 
3459             const int width = textSize.width()
3460                 + (option->subControls & QStyle::SC_GroupBoxCheckBox ? indicatorWidth + 5 : 0);
3461 
3462             rect = QRect();
3463 
3464             if (option->rect.width() > width) {
3465                 switch (groupBox->textAlignment & Qt::AlignHorizontal_Mask) {
3466                 case Qt::AlignHCenter:
3467                     rect.moveLeft((option->rect.width() - width) / 2);
3468                     break;
3469                 case Qt::AlignRight:
3470                     rect.moveLeft(option->rect.width() - width);
3471                     break;
3472                 }
3473             }
3474 
3475             if (subControl == SC_GroupBoxCheckBox) {
3476                 rect.setWidth(indicatorWidth);
3477                 rect.setHeight(indicatorHeight);
3478                 rect.moveTop(textSize.height() > indicatorHeight ? (textSize.height() - indicatorHeight) / 2 : 0);
3479                 rect.translate(1, 0);
3480             } else if (subControl == SC_GroupBoxLabel) {
3481                 rect.setSize(textSize);
3482                 rect.moveTop(1);
3483                 if (option->subControls & QStyle::SC_GroupBoxCheckBox)
3484                     rect.translate(indicatorWidth + 5, 0);
3485             }
3486             return visualRect(option->direction, option->rect, rect);
3487         }
3488 
3489         return rect;
3490 
3491     case CC_ComboBox:
3492         switch (subControl) {
3493         case SC_ComboBoxArrow: {
3494             const qreal dpi = QStyleHelper::dpi(option);
3495             rect = visualRect(option->direction, option->rect, rect);
3496             rect.setRect(rect.right() - int(QStyleHelper::dpiScaled(18, dpi)), rect.top() - 2,
3497                          int(QStyleHelper::dpiScaled(19, dpi)), rect.height() + 4);
3498             rect = visualRect(option->direction, option->rect, rect);
3499         }
3500             break;
3501         case SC_ComboBoxEditField: {
3502             int frameWidth = 2;
3503             rect = visualRect(option->direction, option->rect, rect);
3504             rect.setRect(option->rect.left() + frameWidth, option->rect.top() + frameWidth,
3505                          option->rect.width() - int(QStyleHelper::dpiScaled(19, option)) - 2 * frameWidth,
3506                          option->rect.height() - 2 * frameWidth);
3507             if (const QStyleOptionComboBox *box = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
3508                 if (!box->editable) {
3509                     rect.adjust(2, 0, 0, 0);
3510                     if (box->state & (State_Sunken | State_On))
3511                         rect.translate(1, 1);
3512                 }
3513             }
3514             rect = visualRect(option->direction, option->rect, rect);
3515             break;
3516         }
3517         default:
3518             break;
3519         }
3520         break;
3521     case CC_TitleBar:
3522         if (const QStyleOptionTitleBar *tb = qstyleoption_cast<const QStyleOptionTitleBar *>(option)) {
3523             SubControl sc = subControl;
3524             QRect &ret = rect;
3525             const int indent = 3;
3526             const int controlTopMargin = 3;
3527             const int controlBottomMargin = 3;
3528             const int controlWidthMargin = 2;
3529             const int controlHeight = tb->rect.height() - controlTopMargin - controlBottomMargin ;
3530             const int delta = controlHeight + controlWidthMargin;
3531             int offset = 0;
3532 
3533             bool isMinimized = tb->titleBarState & Qt::WindowMinimized;
3534             bool isMaximized = tb->titleBarState & Qt::WindowMaximized;
3535 
3536             switch (sc) {
3537             case SC_TitleBarLabel:
3538                 if (tb->titleBarFlags & (Qt::WindowTitleHint | Qt::WindowSystemMenuHint)) {
3539                     ret = tb->rect;
3540                     if (tb->titleBarFlags & Qt::WindowSystemMenuHint)
3541                         ret.adjust(delta, 0, -delta, 0);
3542                     if (tb->titleBarFlags & Qt::WindowMinimizeButtonHint)
3543                         ret.adjust(0, 0, -delta, 0);
3544                     if (tb->titleBarFlags & Qt::WindowMaximizeButtonHint)
3545                         ret.adjust(0, 0, -delta, 0);
3546                     if (tb->titleBarFlags & Qt::WindowShadeButtonHint)
3547                         ret.adjust(0, 0, -delta, 0);
3548                     if (tb->titleBarFlags & Qt::WindowContextHelpButtonHint)
3549                         ret.adjust(0, 0, -delta, 0);
3550                 }
3551                 break;
3552             case SC_TitleBarContextHelpButton:
3553                 if (tb->titleBarFlags & Qt::WindowContextHelpButtonHint)
3554                     offset += delta;
3555                 Q_FALLTHROUGH();
3556             case SC_TitleBarMinButton:
3557                 if (!isMinimized && (tb->titleBarFlags & Qt::WindowMinimizeButtonHint))
3558                     offset += delta;
3559                 else if (sc == SC_TitleBarMinButton)
3560                     break;
3561                 Q_FALLTHROUGH();
3562             case SC_TitleBarNormalButton:
3563                 if (isMinimized && (tb->titleBarFlags & Qt::WindowMinimizeButtonHint))
3564                     offset += delta;
3565                 else if (isMaximized && (tb->titleBarFlags & Qt::WindowMaximizeButtonHint))
3566                     offset += delta;
3567                 else if (sc == SC_TitleBarNormalButton)
3568                     break;
3569                 Q_FALLTHROUGH();
3570             case SC_TitleBarMaxButton:
3571                 if (!isMaximized && (tb->titleBarFlags & Qt::WindowMaximizeButtonHint))
3572                     offset += delta;
3573                 else if (sc == SC_TitleBarMaxButton)
3574                     break;
3575                 Q_FALLTHROUGH();
3576             case SC_TitleBarShadeButton:
3577                 if (!isMinimized && (tb->titleBarFlags & Qt::WindowShadeButtonHint))
3578                     offset += delta;
3579                 else if (sc == SC_TitleBarShadeButton)
3580                     break;
3581                 Q_FALLTHROUGH();
3582             case SC_TitleBarUnshadeButton:
3583                 if (isMinimized && (tb->titleBarFlags & Qt::WindowShadeButtonHint))
3584                     offset += delta;
3585                 else if (sc == SC_TitleBarUnshadeButton)
3586                     break;
3587                 Q_FALLTHROUGH();
3588             case SC_TitleBarCloseButton:
3589                 if (tb->titleBarFlags & Qt::WindowSystemMenuHint)
3590                     offset += delta;
3591                 else if (sc == SC_TitleBarCloseButton)
3592                     break;
3593                 ret.setRect(tb->rect.right() - indent - offset, tb->rect.top() + controlTopMargin,
3594                             controlHeight, controlHeight);
3595                 break;
3596             case SC_TitleBarSysMenu:
3597                 if (tb->titleBarFlags & Qt::WindowSystemMenuHint) {
3598                     ret.setRect(tb->rect.left() + controlWidthMargin + indent, tb->rect.top() + controlTopMargin,
3599                                 controlHeight, controlHeight);
3600                 }
3601                 break;
3602             default:
3603                 break;
3604             }
3605             ret = visualRect(tb->direction, tb->rect, ret);
3606         }
3607         break;
3608     default:
3609         break;
3610     }
3611 
3612     return rect;
3613 }
3614 
3615 
3616 /*!
3617   \reimp
3618 */
itemPixmapRect(const QRect & r,int flags,const QPixmap & pixmap) const3619 QRect QFusionStyle::itemPixmapRect(const QRect &r, int flags, const QPixmap &pixmap) const
3620 {
3621     return QCommonStyle::itemPixmapRect(r, flags, pixmap);
3622 }
3623 
3624 /*!
3625   \reimp
3626 */
drawItemPixmap(QPainter * painter,const QRect & rect,int alignment,const QPixmap & pixmap) const3627 void QFusionStyle::drawItemPixmap(QPainter *painter, const QRect &rect,
3628                                   int alignment, const QPixmap &pixmap) const
3629 {
3630     QCommonStyle::drawItemPixmap(painter, rect, alignment, pixmap);
3631 }
3632 
3633 /*!
3634   \reimp
3635 */
hitTestComplexControl(ComplexControl cc,const QStyleOptionComplex * opt,const QPoint & pt,const QWidget * w) const3636 QStyle::SubControl QFusionStyle::hitTestComplexControl(ComplexControl cc, const QStyleOptionComplex *opt,
3637                                                        const QPoint &pt, const QWidget *w) const
3638 {
3639     return QCommonStyle::hitTestComplexControl(cc, opt, pt, w);
3640 }
3641 
3642 /*!
3643   \reimp
3644 */
generatedIconPixmap(QIcon::Mode iconMode,const QPixmap & pixmap,const QStyleOption * opt) const3645 QPixmap QFusionStyle::generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap,
3646                                           const QStyleOption *opt) const
3647 {
3648     return QCommonStyle::generatedIconPixmap(iconMode, pixmap, opt);
3649 }
3650 
3651 /*!
3652   \reimp
3653 */
styleHint(StyleHint hint,const QStyleOption * option,const QWidget * widget,QStyleHintReturn * returnData) const3654 int QFusionStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget,
3655                             QStyleHintReturn *returnData) const
3656 {
3657     switch (hint) {
3658     case SH_Slider_SnapToValue:
3659     case SH_PrintDialog_RightAlignButtons:
3660     case SH_FontDialog_SelectAssociatedText:
3661     case SH_MenuBar_AltKeyNavigation:
3662     case SH_ComboBox_ListMouseTracking:
3663     case SH_Slider_StopMouseOverSlider:
3664     case SH_ScrollBar_MiddleClickAbsolutePosition:
3665     case SH_EtchDisabledText:
3666     case SH_TitleBar_AutoRaise:
3667     case SH_TitleBar_NoBorder:
3668     case SH_ItemView_ShowDecorationSelected:
3669     case SH_ItemView_ArrowKeysNavigateIntoChildren:
3670     case SH_ItemView_ChangeHighlightOnFocus:
3671     case SH_MenuBar_MouseTracking:
3672     case SH_Menu_MouseTracking:
3673     case SH_Menu_SupportsSections:
3674         return 1;
3675 
3676 #if defined(QT_PLATFORM_UIKIT)
3677     case SH_ComboBox_UseNativePopup:
3678         return 1;
3679 #endif
3680 
3681     case SH_ToolBox_SelectedPageTitleBold:
3682     case SH_ScrollView_FrameOnlyAroundContents:
3683     case SH_Menu_AllowActiveAndDisabled:
3684     case SH_MainWindow_SpaceBelowMenuBar:
3685     case SH_MessageBox_CenterButtons:
3686     case SH_RubberBand_Mask:
3687         return 0;
3688 
3689     case SH_ComboBox_Popup:
3690         if (const QStyleOptionComboBox *cmb = qstyleoption_cast<const QStyleOptionComboBox *>(option))
3691             return !cmb->editable;
3692         return 0;
3693 
3694     case SH_Table_GridLineColor:
3695         return option ? option->palette.window().color().darker(120).rgba() : 0;
3696 
3697     case SH_MessageBox_TextInteractionFlags:
3698         return Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse;
3699 #if QT_CONFIG(wizard)
3700     case SH_WizardStyle:
3701         return QWizard::ClassicStyle;
3702 #endif
3703     case SH_Menu_SubMenuPopupDelay:
3704         return 225; // default from GtkMenu
3705 
3706     case SH_WindowFrame_Mask:
3707         if (QStyleHintReturnMask *mask = qstyleoption_cast<QStyleHintReturnMask *>(returnData)) {
3708             //left rounded corner
3709             mask->region = option->rect;
3710             mask->region -= QRect(option->rect.left(), option->rect.top(), 5, 1);
3711             mask->region -= QRect(option->rect.left(), option->rect.top() + 1, 3, 1);
3712             mask->region -= QRect(option->rect.left(), option->rect.top() + 2, 2, 1);
3713             mask->region -= QRect(option->rect.left(), option->rect.top() + 3, 1, 2);
3714 
3715             //right rounded corner
3716             mask->region -= QRect(option->rect.right() - 4, option->rect.top(), 5, 1);
3717             mask->region -= QRect(option->rect.right() - 2, option->rect.top() + 1, 3, 1);
3718             mask->region -= QRect(option->rect.right() - 1, option->rect.top() + 2, 2, 1);
3719             mask->region -= QRect(option->rect.right() , option->rect.top() + 3, 1, 2);
3720             return 1;
3721         }
3722     default:
3723         break;
3724     }
3725     return QCommonStyle::styleHint(hint, option, widget, returnData);
3726 }
3727 
3728 /*! \reimp */
subElementRect(SubElement sr,const QStyleOption * opt,const QWidget * w) const3729 QRect QFusionStyle::subElementRect(SubElement sr, const QStyleOption *opt, const QWidget *w) const
3730 {
3731     QRect r = QCommonStyle::subElementRect(sr, opt, w);
3732     switch (sr) {
3733     case SE_ProgressBarLabel:
3734     case SE_ProgressBarContents:
3735     case SE_ProgressBarGroove:
3736         return opt->rect;
3737     case SE_PushButtonFocusRect:
3738         r.adjust(0, 1, 0, -1);
3739         break;
3740     case SE_DockWidgetTitleBarText: {
3741         if (const QStyleOptionDockWidget *titlebar = qstyleoption_cast<const QStyleOptionDockWidget*>(opt)) {
3742             bool verticalTitleBar = titlebar->verticalTitleBar;
3743             if (verticalTitleBar) {
3744                 r.adjust(0, 0, 0, -4);
3745             } else {
3746                 if (opt->direction == Qt::LeftToRight)
3747                     r.adjust(4, 0, 0, 0);
3748                 else
3749                     r.adjust(0, 0, -4, 0);
3750             }
3751         }
3752 
3753         break;
3754     }
3755     default:
3756         break;
3757     }
3758     return r;
3759 }
3760 
3761 /*!
3762     \reimp
3763 */
standardIcon(StandardPixmap standardIcon,const QStyleOption * option,const QWidget * widget) const3764 QIcon QFusionStyle::standardIcon(StandardPixmap standardIcon, const QStyleOption *option,
3765                                  const QWidget *widget) const
3766 {
3767 #if QT_CONFIG(imageformat_xpm)
3768     switch (standardIcon) {
3769     case SP_TitleBarNormalButton:
3770         return QIcon(QPixmap(dock_widget_restore_xpm));
3771     case SP_TitleBarMinButton:
3772         return QIcon(QPixmap(workspace_minimize));
3773     case SP_TitleBarCloseButton:
3774     case SP_DockWidgetCloseButton:
3775         return QIcon(QPixmap(dock_widget_close_xpm));
3776     default:
3777         break;
3778     }
3779 #endif // imageformat_xpm
3780     return QCommonStyle::standardIcon(standardIcon, option, widget);
3781 }
3782 
3783 /*!
3784  \reimp
3785  */
standardPixmap(StandardPixmap standardPixmap,const QStyleOption * opt,const QWidget * widget) const3786 QPixmap QFusionStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt,
3787                                      const QWidget *widget) const
3788 {
3789 #ifndef QT_NO_IMAGEFORMAT_XPM
3790     switch (standardPixmap) {
3791     case SP_TitleBarNormalButton:
3792         return QPixmap(dock_widget_restore_xpm);
3793     case SP_TitleBarMinButton:
3794         return QPixmap(workspace_minimize);
3795     case SP_TitleBarCloseButton:
3796     case SP_DockWidgetCloseButton:
3797         return QPixmap(dock_widget_close_xpm);
3798 
3799     default:
3800         break;
3801     }
3802 #endif //QT_NO_IMAGEFORMAT_XPM
3803 
3804     return QCommonStyle::standardPixmap(standardPixmap, opt, widget);
3805 }
3806 
3807 QT_END_NAMESPACE
3808 
3809 #include "moc_qfusionstyle_p.cpp"
3810 
3811 #endif // style_fusion|| QT_PLUGIN
3812