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 "qcommonstyle.h"
41 #include "qcommonstyle_p.h"
42 
43 #include <qfile.h>
44 #if QT_CONFIG(itemviews)
45 #include <qabstractitemview.h>
46 #endif
47 #include <qapplication.h>
48 #include <private/qguiapplication_p.h>
49 #include <qpa/qplatformtheme.h>
50 #include <qbitmap.h>
51 #include <qcache.h>
52 #if QT_CONFIG(dockwidget)
53 #include <qdockwidget.h>
54 #endif
55 #include <qdrawutil.h>
56 #if QT_CONFIG(dialogbuttonbox)
57 #include <qdialogbuttonbox.h>
58 #endif
59 #if QT_CONFIG(formlayout)
60 #include <qformlayout.h>
61 #else
62 #include <qlayout.h>
63 #endif
64 #if QT_CONFIG(groupbox)
65 #include <qgroupbox.h>
66 #endif
67 #include <qmath.h>
68 #if QT_CONFIG(menu)
69 #include <qmenu.h>
70 #endif
71 #include <qpainter.h>
72 #include <qpaintengine.h>
73 #include <qpainterpath.h>
74 #if QT_CONFIG(slider)
75 #include <qslider.h>
76 #endif
77 #include <qstyleoption.h>
78 #if QT_CONFIG(tabbar)
79 #include <qtabbar.h>
80 #endif
81 #if QT_CONFIG(tabwidget)
82 #include <qtabwidget.h>
83 #endif
84 #if QT_CONFIG(toolbar)
85 #include <qtoolbar.h>
86 #endif
87 #if QT_CONFIG(toolbutton)
88 #include <qtoolbutton.h>
89 #endif
90 #if QT_CONFIG(rubberband)
91 #include <qrubberband.h>
92 #endif
93 #if QT_CONFIG(treeview)
94 #include "qtreeview.h"
95 #endif
96 #include <private/qcommonstylepixmaps_p.h>
97 #include <private/qmath_p.h>
98 #include <qdebug.h>
99 #include <qtextformat.h>
100 #if QT_CONFIG(wizard)
101 #include <qwizard.h>
102 #endif
103 #if QT_CONFIG(filedialog)
104 #include <qsidebar_p.h>
105 #endif
106 #include <qfileinfo.h>
107 #include <qdir.h>
108 #if QT_CONFIG(settings)
109 #include <qsettings.h>
110 #endif
111 #include <qvariant.h>
112 #include <qpixmapcache.h>
113 #if QT_CONFIG(animation)
114 #include <private/qstyleanimation_p.h>
115 #endif
116 
117 #include <limits.h>
118 
119 #include <private/qtextengine_p.h>
120 #include <private/qstylehelper_p.h>
121 
122 QT_BEGIN_NAMESPACE
123 
qt_getWindow(const QWidget * widget)124 static QWindow *qt_getWindow(const QWidget *widget)
125 {
126     return widget ? widget->window()->windowHandle() : nullptr;
127 }
128 
129 /*!
130     \class QCommonStyle
131     \brief The QCommonStyle class encapsulates the common Look and Feel of a GUI.
132 
133     \ingroup appearance
134     \inmodule QtWidgets
135 
136     This abstract class implements some of the widget's look and feel
137     that is common to all GUI styles provided and shipped as part of
138     Qt.
139 
140     Since QCommonStyle inherits QStyle, all of its functions are fully documented
141     in the QStyle documentation.
142     \omit
143     , although the
144     extra functions that QCommonStyle provides, e.g.
145     drawComplexControl(), drawControl(), drawPrimitive(),
146     hitTestComplexControl(), subControlRect(), sizeFromContents(), and
147     subElementRect() are documented here.
148     \endomit
149 
150     \sa QStyle, QProxyStyle
151 */
152 
153 /*!
154     Constructs a QCommonStyle.
155 */
QCommonStyle()156 QCommonStyle::QCommonStyle()
157     : QStyle(*new QCommonStylePrivate)
158 { }
159 
160 /*! \internal
161 */
QCommonStyle(QCommonStylePrivate & dd)162 QCommonStyle::QCommonStyle(QCommonStylePrivate &dd)
163     : QStyle(dd)
164 { }
165 
166 /*!
167     Destroys the style.
168 */
~QCommonStyle()169 QCommonStyle::~QCommonStyle()
170 { }
171 
172 
173 /*!
174     \reimp
175 */
drawPrimitive(PrimitiveElement pe,const QStyleOption * opt,QPainter * p,const QWidget * widget) const176 void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPainter *p,
177                                  const QWidget *widget) const
178 {
179     Q_D(const QCommonStyle);
180     switch (pe) {
181     case PE_FrameButtonBevel:
182     case PE_FrameButtonTool:
183         qDrawShadeRect(p, opt->rect, opt->palette,
184                        opt->state & (State_Sunken | State_On), 1, 0);
185         break;
186     case PE_PanelButtonCommand:
187     case PE_PanelButtonBevel:
188     case PE_PanelButtonTool:
189     case PE_IndicatorButtonDropDown:
190         qDrawShadePanel(p, opt->rect, opt->palette,
191                         opt->state & (State_Sunken | State_On), 1,
192                         &opt->palette.brush(QPalette::Button));
193         break;
194     case PE_IndicatorItemViewItemCheck:
195         proxy()->drawPrimitive(PE_IndicatorCheckBox, opt, p, widget);
196         break;
197     case PE_IndicatorCheckBox:
198         if (opt->state & State_NoChange) {
199             p->setPen(opt->palette.windowText().color());
200             p->fillRect(opt->rect, opt->palette.brush(QPalette::Button));
201             p->drawRect(opt->rect);
202             p->drawLine(opt->rect.topLeft(), opt->rect.bottomRight());
203         } else {
204             qDrawShadePanel(p, opt->rect.x(), opt->rect.y(), opt->rect.width(), opt->rect.height(),
205                             opt->palette, opt->state & (State_Sunken | State_On), 1,
206                             &opt->palette.brush(QPalette::Button));
207         }
208         break;
209     case PE_IndicatorRadioButton: {
210         QRect ir = opt->rect;
211         p->setPen(opt->palette.dark().color());
212         p->drawArc(opt->rect, 0, 5760);
213         if (opt->state & (State_Sunken | State_On)) {
214             ir.adjust(2, 2, -2, -2);
215             p->setBrush(opt->palette.windowText());
216             bool oldQt4CompatiblePainting = p->testRenderHint(QPainter::Qt4CompatiblePainting);
217             p->setRenderHint(QPainter::Qt4CompatiblePainting);
218             p->drawEllipse(ir);
219             p->setRenderHint(QPainter::Qt4CompatiblePainting, oldQt4CompatiblePainting);
220         }
221         break; }
222     case PE_FrameFocusRect:
223         if (const QStyleOptionFocusRect *fropt = qstyleoption_cast<const QStyleOptionFocusRect *>(opt)) {
224             QColor bg = fropt->backgroundColor;
225             QPen oldPen = p->pen();
226             if (bg.isValid()) {
227                 int h, s, v;
228                 bg.getHsv(&h, &s, &v);
229                 if (v >= 128)
230                     p->setPen(Qt::black);
231                 else
232                     p->setPen(Qt::white);
233             } else {
234                 p->setPen(opt->palette.windowText().color());
235             }
236             QRect focusRect = opt->rect.adjusted(1, 1, -1, -1);
237             p->drawRect(focusRect.adjusted(0, 0, -1, -1)); //draw pen inclusive
238             p->setPen(oldPen);
239         }
240         break;
241     case PE_IndicatorMenuCheckMark: {
242         const int markW = opt->rect.width() > 7 ? 7 : opt->rect.width();
243         const int markH = markW;
244         int posX = opt->rect.x() + (opt->rect.width() - markW)/2 + 1;
245         int posY = opt->rect.y() + (opt->rect.height() - markH)/2;
246 
247         QVector<QLineF> a;
248         a.reserve(markH);
249 
250         int i, xx, yy;
251         xx = posX;
252         yy = 3 + posY;
253         for (i = 0; i < markW/2; ++i) {
254             a << QLineF(xx, yy, xx, yy + 2);
255             ++xx;
256             ++yy;
257         }
258         yy -= 2;
259         for (; i < markH; ++i) {
260             a << QLineF(xx, yy, xx, yy + 2);
261             ++xx;
262             --yy;
263         }
264         if (!(opt->state & State_Enabled) && !(opt->state & State_On)) {
265             p->save();
266             p->translate(1, 1);
267             p->setPen(opt->palette.light().color());
268             p->drawLines(a);
269             p->restore();
270         }
271         p->setPen((opt->state & State_On) ? opt->palette.highlightedText().color() : opt->palette.text().color());
272         p->drawLines(a);
273         break; }
274     case PE_Frame:
275     case PE_FrameMenu:
276         if (const QStyleOptionFrame *frame = qstyleoption_cast<const QStyleOptionFrame *>(opt)) {
277             if (pe == PE_FrameMenu || (frame->state & State_Sunken) || (frame->state & State_Raised)) {
278                 qDrawShadePanel(p, frame->rect, frame->palette, frame->state & State_Sunken,
279                                 frame->lineWidth);
280             } else {
281                 qDrawPlainRect(p, frame->rect, frame->palette.windowText().color(), frame->lineWidth);
282             }
283         }
284         break;
285 #if QT_CONFIG(toolbar)
286     case PE_PanelMenuBar:
287         if (widget && qobject_cast<QToolBar *>(widget->parentWidget()))
288             break;
289         if (const QStyleOptionFrame *frame = qstyleoption_cast<const QStyleOptionFrame *>(opt)){
290             qDrawShadePanel(p, frame->rect, frame->palette, false, frame->lineWidth,
291                             &frame->palette.brush(QPalette::Button));
292 
293         }
294         else if (const QStyleOptionToolBar *frame = qstyleoption_cast<const QStyleOptionToolBar *>(opt)){
295             qDrawShadePanel(p, frame->rect, frame->palette, false, frame->lineWidth,
296                             &frame->palette.brush(QPalette::Button));
297         }
298 
299         break;
300    case PE_PanelMenu:
301         break;
302     case PE_PanelToolBar:
303        break;
304 #endif // QT_CONFIG(toolbar)
305 #if QT_CONFIG(progressbar)
306     case PE_IndicatorProgressChunk:
307         {
308             bool vertical = false;
309             if (const QStyleOptionProgressBar *pb = qstyleoption_cast<const QStyleOptionProgressBar *>(opt))
310                 vertical = pb->orientation == Qt::Vertical;
311             if (!vertical) {
312                 p->fillRect(opt->rect.x(), opt->rect.y() + 3, opt->rect.width() -2, opt->rect.height() - 6,
313                             opt->palette.brush(QPalette::Highlight));
314             } else {
315                 p->fillRect(opt->rect.x() + 2, opt->rect.y(), opt->rect.width() -6, opt->rect.height() - 2,
316                             opt->palette.brush(QPalette::Highlight));
317             }
318         }
319         break;
320 #endif // QT_CONFIG(progressbar)
321     case PE_IndicatorBranch: {
322         static const int decoration_size = 9;
323         int mid_h = opt->rect.x() + opt->rect.width() / 2;
324         int mid_v = opt->rect.y() + opt->rect.height() / 2;
325         int bef_h = mid_h;
326         int bef_v = mid_v;
327         int aft_h = mid_h;
328         int aft_v = mid_v;
329         if (opt->state & State_Children) {
330             int delta = decoration_size / 2;
331             bef_h -= delta;
332             bef_v -= delta;
333             aft_h += delta;
334             aft_v += delta;
335             p->drawLine(bef_h + 2, bef_v + 4, bef_h + 6, bef_v + 4);
336             if (!(opt->state & State_Open))
337                 p->drawLine(bef_h + 4, bef_v + 2, bef_h + 4, bef_v + 6);
338             QPen oldPen = p->pen();
339             p->setPen(opt->palette.dark().color());
340             p->drawRect(bef_h, bef_v, decoration_size - 1, decoration_size - 1);
341             p->setPen(oldPen);
342         }
343         QBrush brush(opt->palette.dark().color(), Qt::Dense4Pattern);
344         if (opt->state & State_Item) {
345             if (opt->direction == Qt::RightToLeft)
346                 p->fillRect(opt->rect.left(), mid_v, bef_h - opt->rect.left(), 1, brush);
347             else
348                 p->fillRect(aft_h, mid_v, opt->rect.right() - aft_h + 1, 1, brush);
349         }
350         if (opt->state & State_Sibling)
351             p->fillRect(mid_h, aft_v, 1, opt->rect.bottom() - aft_v + 1, brush);
352         if (opt->state & (State_Open | State_Children | State_Item | State_Sibling))
353             p->fillRect(mid_h, opt->rect.y(), 1, bef_v - opt->rect.y(), brush);
354         break; }
355     case PE_FrameStatusBarItem:
356         qDrawShadeRect(p, opt->rect, opt->palette, true, 1, 0, nullptr);
357         break;
358     case PE_IndicatorHeaderArrow:
359         if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(opt)) {
360             QPen oldPen = p->pen();
361             if (header->sortIndicator & QStyleOptionHeader::SortUp) {
362                 p->setPen(QPen(opt->palette.light(), 0));
363                 p->drawLine(opt->rect.x() + opt->rect.width(), opt->rect.y(),
364                             opt->rect.x() + opt->rect.width() / 2, opt->rect.y() + opt->rect.height());
365                 p->setPen(QPen(opt->palette.dark(), 0));
366                 const QPoint points[] = {
367                     QPoint(opt->rect.x() + opt->rect.width() / 2, opt->rect.y() + opt->rect.height()),
368                     QPoint(opt->rect.x(), opt->rect.y()),
369                     QPoint(opt->rect.x() + opt->rect.width(), opt->rect.y()),
370                 };
371                 p->drawPolyline(points, sizeof points / sizeof *points);
372             } else if (header->sortIndicator & QStyleOptionHeader::SortDown) {
373                 p->setPen(QPen(opt->palette.light(), 0));
374                 const QPoint points[] = {
375                     QPoint(opt->rect.x(), opt->rect.y() + opt->rect.height()),
376                     QPoint(opt->rect.x() + opt->rect.width(), opt->rect.y() + opt->rect.height()),
377                     QPoint(opt->rect.x() + opt->rect.width() / 2, opt->rect.y()),
378                 };
379                 p->drawPolyline(points, sizeof points / sizeof *points);
380                 p->setPen(QPen(opt->palette.dark(), 0));
381                 p->drawLine(opt->rect.x(), opt->rect.y() + opt->rect.height(),
382                             opt->rect.x() + opt->rect.width() / 2, opt->rect.y());
383             }
384             p->setPen(oldPen);
385         }
386         break;
387 #if QT_CONFIG(tabbar)
388     case PE_FrameTabBarBase:
389         if (const QStyleOptionTabBarBase *tbb
390                 = qstyleoption_cast<const QStyleOptionTabBarBase *>(opt)) {
391             p->save();
392             switch (tbb->shape) {
393             case QTabBar::RoundedNorth:
394             case QTabBar::TriangularNorth:
395                 p->setPen(QPen(tbb->palette.light(), 0));
396                 p->drawLine(tbb->rect.topLeft(), tbb->rect.topRight());
397                 break;
398             case QTabBar::RoundedWest:
399             case QTabBar::TriangularWest:
400                 p->setPen(QPen(tbb->palette.light(), 0));
401                 p->drawLine(tbb->rect.topLeft(), tbb->rect.bottomLeft());
402                 break;
403             case QTabBar::RoundedSouth:
404             case QTabBar::TriangularSouth:
405                 p->setPen(QPen(tbb->palette.shadow(), 0));
406                 p->drawLine(tbb->rect.left(), tbb->rect.bottom(),
407                             tbb->rect.right(), tbb->rect.bottom());
408                 p->setPen(QPen(tbb->palette.dark(), 0));
409                 p->drawLine(tbb->rect.left(), tbb->rect.bottom() - 1,
410                             tbb->rect.right() - 1, tbb->rect.bottom() - 1);
411                 break;
412             case QTabBar::RoundedEast:
413             case QTabBar::TriangularEast:
414                 p->setPen(QPen(tbb->palette.dark(), 0));
415                 p->drawLine(tbb->rect.topRight(), tbb->rect.bottomRight());
416                 break;
417             }
418             p->restore();
419         }
420         break;
421     case PE_IndicatorTabClose: {
422         if (d->tabBarcloseButtonIcon.isNull()) {
423             d->tabBarcloseButtonIcon.addPixmap(QPixmap(
424                         QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-closetab-16.png")),
425                         QIcon::Normal, QIcon::Off);
426             d->tabBarcloseButtonIcon.addPixmap(QPixmap(
427                         QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-closetab-down-16.png")),
428                         QIcon::Normal, QIcon::On);
429             d->tabBarcloseButtonIcon.addPixmap(QPixmap(
430                         QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-closetab-hover-16.png")),
431                         QIcon::Active, QIcon::Off);
432         }
433 
434         const int size = proxy()->pixelMetric(QStyle::PM_SmallIconSize, opt);
435         QIcon::Mode mode = opt->state & State_Enabled ?
436                             (opt->state & State_Raised ? QIcon::Active : QIcon::Normal)
437                             : QIcon::Disabled;
438         if (!(opt->state & State_Raised)
439             && !(opt->state & State_Sunken)
440             && !(opt->state & QStyle::State_Selected))
441             mode = QIcon::Disabled;
442 
443         QIcon::State state = opt->state & State_Sunken ? QIcon::On : QIcon::Off;
444         QPixmap pixmap = d->tabBarcloseButtonIcon.pixmap(qt_getWindow(widget), QSize(size, size), mode, state);
445         proxy()->drawItemPixmap(p, opt->rect, Qt::AlignCenter, pixmap);
446         break;
447     }
448 #else
449     Q_UNUSED(d);
450 #endif // QT_CONFIG(tabbar)
451     case PE_FrameTabWidget:
452     case PE_FrameWindow:
453         qDrawWinPanel(p, opt->rect, opt->palette, false, nullptr);
454         break;
455     case PE_FrameLineEdit:
456         proxy()->drawPrimitive(PE_Frame, opt, p, widget);
457         break;
458 #if QT_CONFIG(groupbox)
459     case PE_FrameGroupBox:
460         if (const QStyleOptionFrame *frame = qstyleoption_cast<const QStyleOptionFrame *>(opt)) {
461             if (frame->features & QStyleOptionFrame::Flat) {
462                 QRect fr = frame->rect;
463                 QPoint p1(fr.x(), fr.y() + 1);
464                 QPoint p2(fr.x() + fr.width(), p1.y());
465                 qDrawShadeLine(p, p1, p2, frame->palette, true,
466                                frame->lineWidth, frame->midLineWidth);
467             } else {
468                 qDrawShadeRect(p, frame->rect.x(), frame->rect.y(), frame->rect.width(),
469                                frame->rect.height(), frame->palette, true,
470                                frame->lineWidth, frame->midLineWidth);
471             }
472         }
473         break;
474 #endif // QT_CONFIG(groupbox)
475 #if QT_CONFIG(dockwidget)
476     case PE_FrameDockWidget:
477         if (const QStyleOptionFrame *frame = qstyleoption_cast<const QStyleOptionFrame *>(opt)) {
478             int lw = frame->lineWidth;
479             if (lw <= 0)
480                 lw = proxy()->pixelMetric(PM_DockWidgetFrameWidth, opt);
481 
482             qDrawShadePanel(p, frame->rect, frame->palette, false, lw);
483         }
484         break;
485 #endif // QT_CONFIG(dockwidget)
486 #if QT_CONFIG(toolbar)
487     case PE_IndicatorToolBarHandle:
488         p->save();
489         p->translate(opt->rect.x(), opt->rect.y());
490         if (opt->state & State_Horizontal) {
491             int x = opt->rect.width() / 3;
492             if (opt->direction == Qt::RightToLeft)
493                 x -= 2;
494             if (opt->rect.height() > 4) {
495                 qDrawShadePanel(p, x, 2, 3, opt->rect.height() - 4,
496                                 opt->palette, false, 1, nullptr);
497                 qDrawShadePanel(p, x+3, 2, 3, opt->rect.height() - 4,
498                                 opt->palette, false, 1, nullptr);
499             }
500         } else {
501             if (opt->rect.width() > 4) {
502                 int y = opt->rect.height() / 3;
503                 qDrawShadePanel(p, 2, y, opt->rect.width() - 4, 3,
504                                 opt->palette, false, 1, nullptr);
505                 qDrawShadePanel(p, 2, y+3, opt->rect.width() - 4, 3,
506                                 opt->palette, false, 1, nullptr);
507             }
508         }
509         p->restore();
510         break;
511     case PE_IndicatorToolBarSeparator:
512         {
513             QPoint p1, p2;
514             if (opt->state & State_Horizontal) {
515                 p1 = QPoint(opt->rect.width()/2, 0);
516                 p2 = QPoint(p1.x(), opt->rect.height());
517             } else {
518                 p1 = QPoint(0, opt->rect.height()/2);
519                 p2 = QPoint(opt->rect.width(), p1.y());
520             }
521             qDrawShadeLine(p, p1, p2, opt->palette, 1, 1, 0);
522             break;
523         }
524 #endif // QT_CONFIG(toolbar)
525 #if QT_CONFIG(spinbox)
526     case PE_IndicatorSpinPlus:
527     case PE_IndicatorSpinMinus: {
528         QRect r = opt->rect;
529         int fw = proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget);
530         QRect br = r.adjusted(fw, fw, -fw, -fw);
531 
532         int offset = (opt->state & State_Sunken) ? 1 : 0;
533         int step = (br.width() + 4) / 5;
534         p->fillRect(br.x() + offset, br.y() + offset +br.height() / 2 - step / 2,
535                     br.width(), step,
536                     opt->palette.buttonText());
537         if (pe == PE_IndicatorSpinPlus)
538             p->fillRect(br.x() + br.width() / 2 - step / 2 + offset, br.y() + offset,
539                         step, br.height(),
540                         opt->palette.buttonText());
541 
542         break; }
543     case PE_IndicatorSpinUp:
544     case PE_IndicatorSpinDown: {
545         QRect r = opt->rect;
546         int fw = proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget);
547         // QRect br = r.adjusted(fw, fw, -fw, -fw);
548         int x = r.x(), y = r.y(), w = r.width(), h = r.height();
549         int sw = w-4;
550         if (sw < 3)
551             break;
552         else if (!(sw & 1))
553             sw--;
554         sw -= (sw / 7) * 2;        // Empty border
555         int sh = sw/2 + 2;      // Must have empty row at foot of arrow
556 
557         int sx = x + w / 2 - sw / 2;
558         int sy = y + h / 2 - sh / 2;
559 
560         if (pe == PE_IndicatorSpinUp && fw)
561             --sy;
562 
563         int bsx = 0;
564         int bsy = 0;
565         if (opt->state & State_Sunken) {
566             bsx = proxy()->pixelMetric(PM_ButtonShiftHorizontal, opt);
567             bsy = proxy()->pixelMetric(PM_ButtonShiftVertical, opt);
568         }
569         p->save();
570         p->translate(sx + bsx, sy + bsy);
571         p->setPen(opt->palette.buttonText().color());
572         p->setBrush(opt->palette.buttonText());
573         p->setRenderHint(QPainter::Qt4CompatiblePainting);
574         if (pe == PE_IndicatorSpinDown) {
575             const QPoint points[] = { QPoint(0, 1), QPoint(sw-1, 1), QPoint(sh-2, sh-1) };
576             p->drawPolygon(points, sizeof points / sizeof *points);
577         } else {
578             const QPoint points[] = { QPoint(0, sh-1), QPoint(sw-1, sh-1), QPoint(sh-2, 1) };
579             p->drawPolygon(points, sizeof points / sizeof *points);
580         }
581         p->restore();
582         break; }
583 #endif // QT_CONFIG(spinbox)
584     case PE_PanelTipLabel: {
585         const QBrush brush(opt->palette.toolTipBase());
586         qDrawPlainRect(p, opt->rect, opt->palette.toolTipText().color(), 1, &brush);
587         break;
588     }
589 #if QT_CONFIG(tabbar)
590     case PE_IndicatorTabTear:
591         if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(opt)) {
592             bool rtl = tab->direction == Qt::RightToLeft;
593             const bool horizontal = tab->rect.height() > tab->rect.width();
594             const int margin = 4;
595             QPainterPath path;
596 
597             if (horizontal) {
598                 QRect rect = tab->rect.adjusted(rtl ? margin : 0, 0, rtl ? 1 : -margin, 0);
599                 rect.setTop(rect.top() + ((tab->state & State_Selected) ? 1 : 3));
600                 rect.setBottom(rect.bottom() - ((tab->state & State_Selected) ? 0 : 2));
601 
602                 path.moveTo(QPoint(rtl ? rect.right() : rect.left(), rect.top()));
603                 int count = 4;
604                 for (int jags = 1; jags <= count; ++jags, rtl = !rtl)
605                     path.lineTo(QPoint(rtl ? rect.left() : rect.right(), rect.top() + jags * rect.height()/count));
606             } else {
607                 QRect rect = tab->rect.adjusted(0, 0, 0, -margin);
608                 rect.setLeft(rect.left() + ((tab->state & State_Selected) ? 1 : 3));
609                 rect.setRight(rect.right() - ((tab->state & State_Selected) ? 0 : 2));
610 
611                 path.moveTo(QPoint(rect.left(), rect.top()));
612                 int count = 4;
613                 for (int jags = 1; jags <= count; ++jags, rtl = !rtl)
614                     path.lineTo(QPoint(rect.left() + jags * rect.width()/count, rtl ? rect.top() : rect.bottom()));
615             }
616 
617             p->setPen(QPen(tab->palette.dark(), qreal(.8)));
618             p->setBrush(tab->palette.window());
619             p->setRenderHint(QPainter::Antialiasing);
620             p->drawPath(path);
621         }
622         break;
623 #endif // QT_CONFIG(tabbar)
624 #if QT_CONFIG(lineedit)
625     case PE_PanelLineEdit:
626         if (const QStyleOptionFrame *panel = qstyleoption_cast<const QStyleOptionFrame *>(opt)) {
627             p->fillRect(panel->rect.adjusted(panel->lineWidth, panel->lineWidth, -panel->lineWidth, -panel->lineWidth),
628                         panel->palette.brush(QPalette::Base));
629 
630             if (panel->lineWidth > 0)
631                 proxy()->drawPrimitive(PE_FrameLineEdit, panel, p, widget);
632         }
633         break;
634 #endif // QT_CONFIG(lineedit)
635 #if QT_CONFIG(columnview)
636     case PE_IndicatorColumnViewArrow: {
637     if (const QStyleOptionViewItem *viewOpt = qstyleoption_cast<const QStyleOptionViewItem *>(opt)) {
638         bool reverse = (viewOpt->direction == Qt::RightToLeft);
639         p->save();
640         QPainterPath path;
641         int x = viewOpt->rect.x() + 1;
642         int offset = (viewOpt->rect.height() / 3);
643         int height = (viewOpt->rect.height()) - offset * 2;
644         if (height % 2 == 1)
645             --height;
646         int x2 = x + height - 1;
647         if (reverse) {
648             x = viewOpt->rect.x() + viewOpt->rect.width() - 1;
649             x2 = x - height + 1;
650         }
651         path.moveTo(x, viewOpt->rect.y() + offset);
652         path.lineTo(x, viewOpt->rect.y() + offset + height);
653         path.lineTo(x2, viewOpt->rect.y() + offset+height/2);
654         path.closeSubpath();
655         if (viewOpt->state & QStyle::State_Selected ) {
656             if (viewOpt->showDecorationSelected) {
657                 QColor color = viewOpt->palette.color(QPalette::Active, QPalette::HighlightedText);
658                 p->setPen(color);
659                 p->setBrush(color);
660             } else {
661                 QColor color = viewOpt->palette.color(QPalette::Active, QPalette::WindowText);
662                 p->setPen(color);
663                 p->setBrush(color);
664             }
665 
666         } else {
667             QColor color = viewOpt->palette.color(QPalette::Active, QPalette::Mid);
668             p->setPen(color);
669             p->setBrush(color);
670         }
671         p->drawPath(path);
672 
673         // draw the vertical and top triangle line
674         if (!(viewOpt->state & QStyle::State_Selected)) {
675             QPainterPath lines;
676             lines.moveTo(x, viewOpt->rect.y() + offset);
677             lines.lineTo(x, viewOpt->rect.y() + offset + height);
678             lines.moveTo(x, viewOpt->rect.y() + offset);
679             lines.lineTo(x2, viewOpt->rect.y() + offset+height/2);
680             QColor color = viewOpt->palette.color(QPalette::Active, QPalette::Dark);
681             p->setPen(color);
682             p->drawPath(lines);
683         }
684         p->restore();
685     }
686     break; }
687 #endif //QT_CONFIG(columnview)
688     case PE_IndicatorItemViewItemDrop: {
689         QRect rect = opt->rect;
690         if (opt->rect.height() == 0)
691             p->drawLine(rect.topLeft(), rect.topRight());
692         else
693             p->drawRect(rect);
694         break; }
695 #if QT_CONFIG(itemviews)
696     case PE_PanelItemViewRow:
697         if (const QStyleOptionViewItem *vopt = qstyleoption_cast<const QStyleOptionViewItem *>(opt)) {
698             QPalette::ColorGroup cg = (widget ? widget->isEnabled() : (vopt->state & QStyle::State_Enabled))
699                                       ? QPalette::Normal : QPalette::Disabled;
700             if (cg == QPalette::Normal && !(vopt->state & QStyle::State_Active))
701                 cg = QPalette::Inactive;
702 
703             if ((vopt->state & QStyle::State_Selected) &&  proxy()->styleHint(QStyle::SH_ItemView_ShowDecorationSelected, opt, widget))
704                 p->fillRect(vopt->rect, vopt->palette.brush(cg, QPalette::Highlight));
705             else if (vopt->features & QStyleOptionViewItem::Alternate)
706                 p->fillRect(vopt->rect, vopt->palette.brush(cg, QPalette::AlternateBase));
707         }
708         break;
709     case PE_PanelItemViewItem:
710         if (const QStyleOptionViewItem *vopt = qstyleoption_cast<const QStyleOptionViewItem *>(opt)) {
711             QPalette::ColorGroup cg = (widget ? widget->isEnabled() : (vopt->state & QStyle::State_Enabled))
712                                       ? QPalette::Normal : QPalette::Disabled;
713             if (cg == QPalette::Normal && !(vopt->state & QStyle::State_Active))
714                 cg = QPalette::Inactive;
715 
716             if (vopt->showDecorationSelected && (vopt->state & QStyle::State_Selected)) {
717                 p->fillRect(vopt->rect, vopt->palette.brush(cg, QPalette::Highlight));
718             } else {
719                 if (vopt->backgroundBrush.style() != Qt::NoBrush) {
720                     QPointF oldBO = p->brushOrigin();
721                     p->setBrushOrigin(vopt->rect.topLeft());
722                     p->fillRect(vopt->rect, vopt->backgroundBrush);
723                     p->setBrushOrigin(oldBO);
724                 }
725 
726                 if (vopt->state & QStyle::State_Selected) {
727                     QRect textRect = subElementRect(QStyle::SE_ItemViewItemText,  opt, widget);
728                     p->fillRect(textRect, vopt->palette.brush(cg, QPalette::Highlight));
729                 }
730             }
731         }
732         break;
733 #endif // QT_CONFIG(itemviews)
734     case PE_PanelScrollAreaCorner: {
735         const QBrush brush(opt->palette.brush(QPalette::Window));
736         p->fillRect(opt->rect, brush);
737         } break;
738     case PE_IndicatorArrowUp:
739     case PE_IndicatorArrowDown:
740     case PE_IndicatorArrowRight:
741     case PE_IndicatorArrowLeft:
742         {
743             if (opt->rect.width() <= 1 || opt->rect.height() <= 1)
744                 break;
745             QRect r = opt->rect;
746             int size = qMin(r.height(), r.width());
747             QPixmap pixmap;
748             QString pixmapName = QStyleHelper::uniqueName(QLatin1String("$qt_ia-")
749                                                           % QLatin1String(metaObject()->className()), opt, QSize(size, size))
750                                  % HexString<uint>(pe);
751             if (!QPixmapCache::find(pixmapName, &pixmap)) {
752                 qreal pixelRatio = p->device()->devicePixelRatioF();
753                 int border = qRound(pixelRatio*(size/5));
754                 int sqsize = qRound(pixelRatio*(2*(size/2)));
755                 QImage image(sqsize, sqsize, QImage::Format_ARGB32_Premultiplied);
756                 image.fill(0);
757                 QPainter imagePainter(&image);
758 
759                 QPolygon a;
760                 switch (pe) {
761                     case PE_IndicatorArrowUp:
762                         a.setPoints(3, border, sqsize/2,  sqsize/2, border,  sqsize - border, sqsize/2);
763                         break;
764                     case PE_IndicatorArrowDown:
765                         a.setPoints(3, border, sqsize/2,  sqsize/2, sqsize - border,  sqsize - border, sqsize/2);
766                         break;
767                     case PE_IndicatorArrowRight:
768                         a.setPoints(3, sqsize - border, sqsize/2,  sqsize/2, border,  sqsize/2, sqsize - border);
769                         break;
770                     case PE_IndicatorArrowLeft:
771                         a.setPoints(3, border, sqsize/2,  sqsize/2, border,  sqsize/2, sqsize - border);
772                         break;
773                     default:
774                         break;
775                 }
776 
777                 int bsx = 0;
778                 int bsy = 0;
779 
780                 if (opt->state & State_Sunken) {
781                     bsx = proxy()->pixelMetric(PM_ButtonShiftHorizontal, opt, widget);
782                     bsy = proxy()->pixelMetric(PM_ButtonShiftVertical, opt, widget);
783                 }
784 
785                 QRect bounds = a.boundingRect();
786                 int sx = sqsize / 2 - bounds.center().x() - 1;
787                 int sy = sqsize / 2 - bounds.center().y() - 1;
788                 imagePainter.translate(sx + bsx, sy + bsy);
789                 imagePainter.setPen(opt->palette.buttonText().color());
790                 imagePainter.setBrush(opt->palette.buttonText());
791                 imagePainter.setRenderHint(QPainter::Qt4CompatiblePainting);
792 
793                 if (!(opt->state & State_Enabled)) {
794                     imagePainter.translate(1, 1);
795                     imagePainter.setBrush(opt->palette.light().color());
796                     imagePainter.setPen(opt->palette.light().color());
797                     imagePainter.drawPolygon(a);
798                     imagePainter.translate(-1, -1);
799                     imagePainter.setBrush(opt->palette.mid().color());
800                     imagePainter.setPen(opt->palette.mid().color());
801                 }
802 
803                 imagePainter.drawPolygon(a);
804                 imagePainter.end();
805                 pixmap = QPixmap::fromImage(image);
806                 pixmap.setDevicePixelRatio(pixelRatio);
807                 QPixmapCache::insert(pixmapName, pixmap);
808             }
809             int xOffset = r.x() + (r.width() - size)/2;
810             int yOffset = r.y() + (r.height() - size)/2;
811             p->drawPixmap(xOffset, yOffset, pixmap);
812         }
813         break;
814     default:
815         break;
816     }
817 }
818 
819 #if QT_CONFIG(toolbutton)
drawArrow(const QStyle * style,const QStyleOptionToolButton * toolbutton,const QRect & rect,QPainter * painter,const QWidget * widget=nullptr)820 static void drawArrow(const QStyle *style, const QStyleOptionToolButton *toolbutton,
821                       const QRect &rect, QPainter *painter, const QWidget *widget = nullptr)
822 {
823     QStyle::PrimitiveElement pe;
824     switch (toolbutton->arrowType) {
825     case Qt::LeftArrow:
826         pe = QStyle::PE_IndicatorArrowLeft;
827         break;
828     case Qt::RightArrow:
829         pe = QStyle::PE_IndicatorArrowRight;
830         break;
831     case Qt::UpArrow:
832         pe = QStyle::PE_IndicatorArrowUp;
833         break;
834     case Qt::DownArrow:
835         pe = QStyle::PE_IndicatorArrowDown;
836         break;
837     default:
838         return;
839     }
840     QStyleOption arrowOpt = *toolbutton;
841     arrowOpt.rect = rect;
842     style->drawPrimitive(pe, &arrowOpt, painter, widget);
843 }
844 #endif // QT_CONFIG(toolbutton)
845 
viewItemTextLayout(QTextLayout & textLayout,int lineWidth,int maxHeight=-1,int * lastVisibleLine=nullptr)846 static QSizeF viewItemTextLayout(QTextLayout &textLayout, int lineWidth, int maxHeight = -1, int *lastVisibleLine = nullptr)
847 {
848     if (lastVisibleLine)
849         *lastVisibleLine = -1;
850     qreal height = 0;
851     qreal widthUsed = 0;
852     textLayout.beginLayout();
853     int i = 0;
854     while (true) {
855         QTextLine line = textLayout.createLine();
856         if (!line.isValid())
857             break;
858         line.setLineWidth(lineWidth);
859         line.setPosition(QPointF(0, height));
860         height += line.height();
861         widthUsed = qMax(widthUsed, line.naturalTextWidth());
862         // we assume that the height of the next line is the same as the current one
863         if (maxHeight > 0 && lastVisibleLine && height + line.height() > maxHeight) {
864             const QTextLine nextLine = textLayout.createLine();
865             *lastVisibleLine = nextLine.isValid() ? i : -1;
866             break;
867         }
868         ++i;
869     }
870     textLayout.endLayout();
871     return QSizeF(widthUsed, height);
872 }
873 
calculateElidedText(const QString & text,const QTextOption & textOption,const QFont & font,const QRect & textRect,const Qt::Alignment valign,Qt::TextElideMode textElideMode,int flags,bool lastVisibleLineShouldBeElided,QPointF * paintStartPosition) const874 QString QCommonStylePrivate::calculateElidedText(const QString &text, const QTextOption &textOption,
875                                                  const QFont &font, const QRect &textRect, const Qt::Alignment valign,
876                                                  Qt::TextElideMode textElideMode, int flags,
877                                                  bool lastVisibleLineShouldBeElided, QPointF *paintStartPosition) const
878 {
879     QTextLayout textLayout(text, font);
880     textLayout.setTextOption(textOption);
881 
882     // In AlignVCenter mode when more than one line is displayed and the height only allows
883     // some of the lines it makes no sense to display those. From a users perspective it makes
884     // more sense to see the start of the text instead something inbetween.
885     const bool vAlignmentOptimization = paintStartPosition && valign.testFlag(Qt::AlignVCenter);
886 
887     int lastVisibleLine = -1;
888     viewItemTextLayout(textLayout, textRect.width(), vAlignmentOptimization ? textRect.height() : -1, &lastVisibleLine);
889 
890     const QRectF boundingRect = textLayout.boundingRect();
891     // don't care about LTR/RTL here, only need the height
892     const QRect layoutRect = QStyle::alignedRect(Qt::LayoutDirectionAuto, valign,
893                                                  boundingRect.size().toSize(), textRect);
894 
895     if (paintStartPosition)
896         *paintStartPosition = QPointF(textRect.x(), layoutRect.top());
897 
898     QString ret;
899     qreal height = 0;
900     const int lineCount = textLayout.lineCount();
901     for (int i = 0; i < lineCount; ++i) {
902         const QTextLine line = textLayout.lineAt(i);
903         height += line.height();
904 
905         // above visible rect
906         if (height + layoutRect.top() <= textRect.top()) {
907             if (paintStartPosition)
908                 paintStartPosition->ry() += line.height();
909             continue;
910         }
911 
912         const int start = line.textStart();
913         const int length = line.textLength();
914         const bool drawElided = line.naturalTextWidth() > textRect.width();
915         bool elideLastVisibleLine = lastVisibleLine == i;
916         if (!drawElided && i + 1 < lineCount && lastVisibleLineShouldBeElided) {
917             const QTextLine nextLine = textLayout.lineAt(i + 1);
918             const int nextHeight = height + nextLine.height() / 2;
919             // elide when less than the next half line is visible
920             if (nextHeight + layoutRect.top() > textRect.height() + textRect.top())
921                 elideLastVisibleLine = true;
922         }
923 
924         QString text = textLayout.text().mid(start, length);
925         if (drawElided || elideLastVisibleLine) {
926             if (elideLastVisibleLine) {
927                 if (text.endsWith(QChar::LineSeparator))
928                     text.chop(1);
929                 text += QChar(0x2026);
930             }
931             const QStackTextEngine engine(text, font);
932             ret += engine.elidedText(textElideMode, textRect.width(), flags);
933 
934             // no newline for the last line (last visible or real)
935             // sometimes drawElided is true but no eliding is done so the text ends
936             // with QChar::LineSeparator - don't add another one. This happened with
937             // arabic text in the testcase for QTBUG-72805
938             if (i < lineCount - 1 &&
939                 !ret.endsWith(QChar::LineSeparator))
940                 ret += QChar::LineSeparator;
941         } else {
942             ret += text;
943         }
944 
945         // below visible text, can stop
946         if ((height + layoutRect.top() >= textRect.bottom()) ||
947                 (lastVisibleLine >= 0 && lastVisibleLine == i))
948             break;
949     }
950     return ret;
951 }
952 
953 #if QT_CONFIG(itemviews)
954 
viewItemSize(const QStyleOptionViewItem * option,int role) const955 QSize QCommonStylePrivate::viewItemSize(const QStyleOptionViewItem *option, int role) const
956 {
957     const QWidget *widget = option->widget;
958     switch (role) {
959     case Qt::CheckStateRole:
960         if (option->features & QStyleOptionViewItem::HasCheckIndicator)
961             return QSize(proxyStyle->pixelMetric(QStyle::PM_IndicatorWidth, option, widget),
962                          proxyStyle->pixelMetric(QStyle::PM_IndicatorHeight, option, widget));
963         break;
964     case Qt::DisplayRole:
965         if (option->features & QStyleOptionViewItem::HasDisplay) {
966             QTextOption textOption;
967             textOption.setWrapMode(QTextOption::WordWrap);
968             QTextLayout textLayout(option->text, option->font);
969             textLayout.setTextOption(textOption);
970             const bool wrapText = option->features & QStyleOptionViewItem::WrapText;
971             const int textMargin = proxyStyle->pixelMetric(QStyle::PM_FocusFrameHMargin, option, widget) + 1;
972             QRect bounds = option->rect;
973             switch (option->decorationPosition) {
974             case QStyleOptionViewItem::Left:
975             case QStyleOptionViewItem::Right: {
976                 if (wrapText && bounds.isValid()) {
977                     int width = bounds.width() - 2 * textMargin;
978                     if (option->features & QStyleOptionViewItem::HasDecoration)
979                         width -= option->decorationSize.width() + 2 * textMargin;
980                     bounds.setWidth(width);
981                 } else
982                     bounds.setWidth(QFIXED_MAX);
983                 break;
984             }
985             case QStyleOptionViewItem::Top:
986             case QStyleOptionViewItem::Bottom:
987                 if (wrapText)
988                     bounds.setWidth(bounds.isValid() ? bounds.width() - 2 * textMargin : option->decorationSize.width());
989                 else
990                     bounds.setWidth(QFIXED_MAX);
991                 break;
992             default:
993                 break;
994             }
995 
996             if (wrapText && option->features & QStyleOptionViewItem::HasCheckIndicator)
997                 bounds.setWidth(bounds.width() - proxyStyle->pixelMetric(QStyle::PM_IndicatorWidth, option) - 2 * textMargin);
998 
999             const int lineWidth = bounds.width();
1000             const QSizeF size = viewItemTextLayout(textLayout, lineWidth);
1001             return QSize(qCeil(size.width()) + 2 * textMargin, qCeil(size.height()));
1002         }
1003         break;
1004     case Qt::DecorationRole:
1005         if (option->features & QStyleOptionViewItem::HasDecoration) {
1006             return option->decorationSize;
1007         }
1008         break;
1009     default:
1010         break;
1011     }
1012 
1013     return QSize(0, 0);
1014 }
1015 
viewItemDrawText(QPainter * p,const QStyleOptionViewItem * option,const QRect & rect) const1016 void QCommonStylePrivate::viewItemDrawText(QPainter *p, const QStyleOptionViewItem *option, const QRect &rect) const
1017 {
1018     const QWidget *widget = option->widget;
1019     const int textMargin = proxyStyle->pixelMetric(QStyle::PM_FocusFrameHMargin, nullptr, widget) + 1;
1020 
1021     QRect textRect = rect.adjusted(textMargin, 0, -textMargin, 0); // remove width padding
1022     const bool wrapText = option->features & QStyleOptionViewItem::WrapText;
1023     QTextOption textOption;
1024     textOption.setWrapMode(wrapText ? QTextOption::WordWrap : QTextOption::ManualWrap);
1025     textOption.setTextDirection(option->direction);
1026     textOption.setAlignment(QStyle::visualAlignment(option->direction, option->displayAlignment));
1027 
1028     QPointF paintPosition;
1029     const QString newText = calculateElidedText(option->text, textOption,
1030                                                 option->font, textRect, option->displayAlignment,
1031                                                 option->textElideMode, 0,
1032                                                 true, &paintPosition);
1033 
1034     QTextLayout textLayout(newText, option->font);
1035     textLayout.setTextOption(textOption);
1036     viewItemTextLayout(textLayout, textRect.width());
1037     textLayout.draw(p, paintPosition);
1038 }
1039 
1040 /*! \internal
1041     compute the position for the different component of an item (pixmap, text, checkbox)
1042 
1043     Set sizehint to false to layout the elements inside opt->rect. Set sizehint to true to ignore
1044    opt->rect and return rectangles in infinite space
1045 
1046     Code duplicated in QItemDelegate::doLayout
1047 */
viewItemLayout(const QStyleOptionViewItem * opt,QRect * checkRect,QRect * pixmapRect,QRect * textRect,bool sizehint) const1048 void QCommonStylePrivate::viewItemLayout(const QStyleOptionViewItem *opt,  QRect *checkRect,
1049                                          QRect *pixmapRect, QRect *textRect, bool sizehint) const
1050 {
1051     Q_ASSERT(checkRect && pixmapRect && textRect);
1052     *pixmapRect = QRect(QPoint(0, 0), viewItemSize(opt, Qt::DecorationRole));
1053     *textRect = QRect(QPoint(0, 0), viewItemSize(opt, Qt::DisplayRole));
1054     *checkRect = QRect(QPoint(0, 0), viewItemSize(opt, Qt::CheckStateRole));
1055 
1056     const QWidget *widget = opt->widget;
1057     const bool hasCheck = checkRect->isValid();
1058     const bool hasPixmap = pixmapRect->isValid();
1059     const bool hasText = textRect->isValid();
1060     const bool hasMargin = (hasText | hasPixmap | hasCheck);
1061     const int frameHMargin = hasMargin ?
1062                 proxyStyle->pixelMetric(QStyle::PM_FocusFrameHMargin, opt, widget) + 1 : 0;
1063     const int textMargin = hasText ? frameHMargin : 0;
1064     const int pixmapMargin = hasPixmap ? frameHMargin : 0;
1065     const int checkMargin = hasCheck ? frameHMargin : 0;
1066     const int x = opt->rect.left();
1067     const int y = opt->rect.top();
1068     int w, h;
1069 
1070     if (textRect->height() == 0 && (!hasPixmap || !sizehint)) {
1071         //if there is no text, we still want to have a decent height for the item sizeHint and the editor size
1072         textRect->setHeight(opt->fontMetrics.height());
1073     }
1074 
1075     QSize pm(0, 0);
1076     if (hasPixmap) {
1077         pm = pixmapRect->size();
1078         pm.rwidth() += 2 * pixmapMargin;
1079     }
1080     if (sizehint) {
1081         h = qMax(checkRect->height(), qMax(textRect->height(), pm.height()));
1082         if (opt->decorationPosition == QStyleOptionViewItem::Left
1083             || opt->decorationPosition == QStyleOptionViewItem::Right) {
1084             w = textRect->width() + pm.width();
1085         } else {
1086             w = qMax(textRect->width(), pm.width());
1087         }
1088     } else {
1089         w = opt->rect.width();
1090         h = opt->rect.height();
1091     }
1092 
1093     int cw = 0;
1094     QRect check;
1095     if (hasCheck) {
1096         cw = checkRect->width() + 2 * checkMargin;
1097         if (sizehint) w += cw;
1098         if (opt->direction == Qt::RightToLeft) {
1099             check.setRect(x + w - cw, y, cw, h);
1100         } else {
1101             check.setRect(x, y, cw, h);
1102         }
1103     }
1104 
1105     QRect display;
1106     QRect decoration;
1107     switch (opt->decorationPosition) {
1108     case QStyleOptionViewItem::Top: {
1109         if (hasPixmap)
1110             pm.setHeight(pm.height() + pixmapMargin); // add space
1111         h = sizehint ? textRect->height() : h - pm.height();
1112 
1113         if (opt->direction == Qt::RightToLeft) {
1114             decoration.setRect(x, y, w - cw, pm.height());
1115             display.setRect(x, y + pm.height(), w - cw, h);
1116         } else {
1117             decoration.setRect(x + cw, y, w - cw, pm.height());
1118             display.setRect(x + cw, y + pm.height(), w - cw, h);
1119         }
1120         break; }
1121     case QStyleOptionViewItem::Bottom: {
1122         if (hasText)
1123             textRect->setHeight(textRect->height() + textMargin); // add space
1124         h = sizehint ? textRect->height() + pm.height() : h;
1125 
1126         if (opt->direction == Qt::RightToLeft) {
1127             display.setRect(x, y, w - cw, textRect->height());
1128             decoration.setRect(x, y + textRect->height(), w - cw, h - textRect->height());
1129         } else {
1130             display.setRect(x + cw, y, w - cw, textRect->height());
1131             decoration.setRect(x + cw, y + textRect->height(), w - cw, h - textRect->height());
1132         }
1133         break; }
1134     case QStyleOptionViewItem::Left: {
1135         if (opt->direction == Qt::LeftToRight) {
1136             decoration.setRect(x + cw, y, pm.width(), h);
1137             display.setRect(decoration.right() + 1, y, w - pm.width() - cw, h);
1138         } else {
1139             display.setRect(x, y, w - pm.width() - cw, h);
1140             decoration.setRect(display.right() + 1, y, pm.width(), h);
1141         }
1142         break; }
1143     case QStyleOptionViewItem::Right: {
1144         if (opt->direction == Qt::LeftToRight) {
1145             display.setRect(x + cw, y, w - pm.width() - cw, h);
1146             decoration.setRect(display.right() + 1, y, pm.width(), h);
1147         } else {
1148             decoration.setRect(x, y, pm.width(), h);
1149             display.setRect(decoration.right() + 1, y, w - pm.width() - cw, h);
1150         }
1151         break; }
1152     default:
1153         qWarning("doLayout: decoration position is invalid");
1154         decoration = *pixmapRect;
1155         break;
1156     }
1157 
1158     if (!sizehint) { // we only need to do the internal layout if we are going to paint
1159         *checkRect = QStyle::alignedRect(opt->direction, Qt::AlignCenter,
1160                                          checkRect->size(), check);
1161         *pixmapRect = QStyle::alignedRect(opt->direction, opt->decorationAlignment,
1162                                           pixmapRect->size(), decoration);
1163         // the text takes up all available space, unless the decoration is not shown as selected
1164         if (opt->showDecorationSelected)
1165             *textRect = display;
1166         else
1167             *textRect = QStyle::alignedRect(opt->direction, opt->displayAlignment,
1168                                             textRect->size().boundedTo(display.size()), display);
1169     } else {
1170         *checkRect = check;
1171         *pixmapRect = decoration;
1172         *textRect = display;
1173     }
1174 }
1175 #endif // QT_CONFIG(itemviews)
1176 
1177 #if QT_CONFIG(toolbutton)
toolButtonElideText(const QStyleOptionToolButton * option,const QRect & textRect,int flags) const1178 QString QCommonStylePrivate::toolButtonElideText(const QStyleOptionToolButton *option,
1179                                                  const QRect &textRect, int flags) const
1180 {
1181     if (option->fontMetrics.horizontalAdvance(option->text) <= textRect.width())
1182         return option->text;
1183 
1184     QString text = option->text;
1185     text.replace('\n', QChar::LineSeparator);
1186     QTextOption textOption;
1187     textOption.setWrapMode(QTextOption::ManualWrap);
1188     textOption.setTextDirection(option->direction);
1189 
1190     return calculateElidedText(text, textOption,
1191                                option->font, textRect, Qt::AlignTop,
1192                                Qt::ElideMiddle, flags,
1193                                false, nullptr);
1194 }
1195 #endif // QT_CONFIG(toolbutton)
1196 
1197 #if QT_CONFIG(tabbar)
1198 /*! \internal
1199     Compute the textRect and the pixmapRect from the opt rect
1200 
1201     Uses the same computation than in QTabBar::tabSizeHint
1202  */
tabLayout(const QStyleOptionTab * opt,const QWidget * widget,QRect * textRect,QRect * iconRect) const1203 void QCommonStylePrivate::tabLayout(const QStyleOptionTab *opt, const QWidget *widget, QRect *textRect, QRect *iconRect) const
1204 {
1205     Q_ASSERT(textRect);
1206     Q_ASSERT(iconRect);
1207     QRect tr = opt->rect;
1208     bool verticalTabs = opt->shape == QTabBar::RoundedEast
1209                         || opt->shape == QTabBar::RoundedWest
1210                         || opt->shape == QTabBar::TriangularEast
1211                         || opt->shape == QTabBar::TriangularWest;
1212     if (verticalTabs)
1213         tr.setRect(0, 0, tr.height(), tr.width()); // 0, 0 as we will have a translate transform
1214 
1215     int verticalShift = proxyStyle->pixelMetric(QStyle::PM_TabBarTabShiftVertical, opt, widget);
1216     int horizontalShift = proxyStyle->pixelMetric(QStyle::PM_TabBarTabShiftHorizontal, opt, widget);
1217     int hpadding = proxyStyle->pixelMetric(QStyle::PM_TabBarTabHSpace, opt, widget) / 2;
1218     int vpadding = proxyStyle->pixelMetric(QStyle::PM_TabBarTabVSpace, opt, widget) / 2;
1219     if (opt->shape == QTabBar::RoundedSouth || opt->shape == QTabBar::TriangularSouth)
1220         verticalShift = -verticalShift;
1221     tr.adjust(hpadding, verticalShift - vpadding, horizontalShift - hpadding, vpadding);
1222     bool selected = opt->state & QStyle::State_Selected;
1223     if (selected) {
1224         tr.setTop(tr.top() - verticalShift);
1225         tr.setRight(tr.right() - horizontalShift);
1226     }
1227 
1228     // left widget
1229     if (!opt->leftButtonSize.isEmpty()) {
1230         tr.setLeft(tr.left() + 4 +
1231             (verticalTabs ? opt->leftButtonSize.height() : opt->leftButtonSize.width()));
1232     }
1233     // right widget
1234     if (!opt->rightButtonSize.isEmpty()) {
1235         tr.setRight(tr.right() - 4 -
1236             (verticalTabs ? opt->rightButtonSize.height() : opt->rightButtonSize.width()));
1237     }
1238 
1239     // icon
1240     if (!opt->icon.isNull()) {
1241         QSize iconSize = opt->iconSize;
1242         if (!iconSize.isValid()) {
1243             int iconExtent = proxyStyle->pixelMetric(QStyle::PM_SmallIconSize, opt);
1244             iconSize = QSize(iconExtent, iconExtent);
1245         }
1246         QSize tabIconSize = opt->icon.actualSize(iconSize,
1247                         (opt->state & QStyle::State_Enabled) ? QIcon::Normal : QIcon::Disabled,
1248                         (opt->state & QStyle::State_Selected) ? QIcon::On : QIcon::Off);
1249         // High-dpi icons do not need adjustment; make sure tabIconSize is not larger than iconSize
1250         tabIconSize = QSize(qMin(tabIconSize.width(), iconSize.width()), qMin(tabIconSize.height(), iconSize.height()));
1251 
1252         const int offsetX = (iconSize.width() - tabIconSize.width()) / 2;
1253         *iconRect = QRect(tr.left() + offsetX, tr.center().y() - tabIconSize.height() / 2,
1254                           tabIconSize.width(), tabIconSize.height());
1255         if (!verticalTabs)
1256             *iconRect = QStyle::visualRect(opt->direction, opt->rect, *iconRect);
1257         tr.setLeft(tr.left() + tabIconSize.width() + 4);
1258     }
1259 
1260     if (!verticalTabs)
1261         tr = QStyle::visualRect(opt->direction, opt->rect, tr);
1262 
1263     *textRect = tr;
1264 }
1265 #endif // QT_CONFIG(tabbar)
1266 
1267 #if QT_CONFIG(animation)
1268 /*! \internal */
animationTargets() const1269 QList<const QObject*> QCommonStylePrivate::animationTargets() const
1270 {
1271     return animations.keys();
1272 }
1273 
1274 /*! \internal */
animation(const QObject * target) const1275 QStyleAnimation * QCommonStylePrivate::animation(const QObject *target) const
1276 {
1277     return animations.value(target);
1278 }
1279 
1280 /*! \internal */
startAnimation(QStyleAnimation * animation) const1281 void QCommonStylePrivate::startAnimation(QStyleAnimation *animation) const
1282 {
1283     Q_Q(const QCommonStyle);
1284     stopAnimation(animation->target());
1285     q->connect(animation, SIGNAL(destroyed()), SLOT(_q_removeAnimation()), Qt::UniqueConnection);
1286     animations.insert(animation->target(), animation);
1287     animation->start();
1288 }
1289 
1290 /*! \internal */
stopAnimation(const QObject * target) const1291 void QCommonStylePrivate::stopAnimation(const QObject *target) const
1292 {
1293     QStyleAnimation *animation = animations.take(target);
1294     if (animation) {
1295         animation->stop();
1296         delete animation;
1297     }
1298 }
1299 
1300 /*! \internal */
_q_removeAnimation()1301 void QCommonStylePrivate::_q_removeAnimation()
1302 {
1303     Q_Q(QCommonStyle);
1304     QObject *animation = q->sender();
1305     if (animation)
1306         animations.remove(animation->parent());
1307 }
1308 #endif
1309 
1310 /*!
1311   \reimp
1312 */
drawControl(ControlElement element,const QStyleOption * opt,QPainter * p,const QWidget * widget) const1313 void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
1314                                QPainter *p, const QWidget *widget) const
1315 {
1316     Q_D(const QCommonStyle);
1317     switch (element) {
1318 
1319     case CE_PushButton:
1320         if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
1321             proxy()->drawControl(CE_PushButtonBevel, btn, p, widget);
1322             QStyleOptionButton subopt = *btn;
1323             subopt.rect = subElementRect(SE_PushButtonContents, btn, widget);
1324             proxy()->drawControl(CE_PushButtonLabel, &subopt, p, widget);
1325             if (btn->state & State_HasFocus) {
1326                 QStyleOptionFocusRect fropt;
1327                 fropt.QStyleOption::operator=(*btn);
1328                 fropt.rect = subElementRect(SE_PushButtonFocusRect, btn, widget);
1329                 proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, p, widget);
1330             }
1331         }
1332         break;
1333     case CE_PushButtonBevel:
1334         if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
1335             QRect br = btn->rect;
1336             int dbi = proxy()->pixelMetric(PM_ButtonDefaultIndicator, btn, widget);
1337             if (btn->features & QStyleOptionButton::DefaultButton)
1338                 proxy()->drawPrimitive(PE_FrameDefaultButton, opt, p, widget);
1339             if (btn->features & QStyleOptionButton::AutoDefaultButton)
1340                 br.setCoords(br.left() + dbi, br.top() + dbi, br.right() - dbi, br.bottom() - dbi);
1341             if (!(btn->features & (QStyleOptionButton::Flat | QStyleOptionButton::CommandLinkButton))
1342                 || btn->state & (State_Sunken | State_On)
1343                 || (btn->features & QStyleOptionButton::CommandLinkButton && btn->state & State_MouseOver)) {
1344                 QStyleOptionButton tmpBtn = *btn;
1345                 tmpBtn.rect = br;
1346                 proxy()->drawPrimitive(PE_PanelButtonCommand, &tmpBtn, p, widget);
1347             }
1348             if (btn->features & QStyleOptionButton::HasMenu) {
1349                 int mbi = proxy()->pixelMetric(PM_MenuButtonIndicator, btn, widget);
1350                 QRect ir = btn->rect;
1351                 QStyleOptionButton newBtn = *btn;
1352                 newBtn.rect = QRect(ir.right() - mbi + 2, ir.height()/2 - mbi/2 + 3, mbi - 6, mbi - 6);
1353                 newBtn.rect = visualRect(btn->direction, br, newBtn.rect);
1354                 proxy()->drawPrimitive(PE_IndicatorArrowDown, &newBtn, p, widget);
1355             }
1356         }
1357         break;
1358  case CE_PushButtonLabel:
1359         if (const QStyleOptionButton *button = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
1360             QRect textRect = button->rect;
1361             uint tf = Qt::AlignVCenter | Qt::TextShowMnemonic;
1362             if (!proxy()->styleHint(SH_UnderlineShortcut, button, widget))
1363                 tf |= Qt::TextHideMnemonic;
1364 
1365             if (!button->icon.isNull()) {
1366                 //Center both icon and text
1367                 QIcon::Mode mode = button->state & State_Enabled ? QIcon::Normal : QIcon::Disabled;
1368                 if (mode == QIcon::Normal && button->state & State_HasFocus)
1369                     mode = QIcon::Active;
1370                 QIcon::State state = QIcon::Off;
1371                 if (button->state & State_On)
1372                     state = QIcon::On;
1373 
1374                 QPixmap pixmap = button->icon.pixmap(qt_getWindow(widget), button->iconSize, mode, state);
1375                 int pixmapWidth = pixmap.width() / pixmap.devicePixelRatio();
1376                 int pixmapHeight = pixmap.height() / pixmap.devicePixelRatio();
1377                 int labelWidth = pixmapWidth;
1378                 int labelHeight = pixmapHeight;
1379                 int iconSpacing = 4;//### 4 is currently hardcoded in QPushButton::sizeHint()
1380                 if (!button->text.isEmpty()) {
1381                     int textWidth = button->fontMetrics.boundingRect(opt->rect, tf, button->text).width();
1382                     labelWidth += (textWidth + iconSpacing);
1383                 }
1384 
1385                 QRect iconRect = QRect(textRect.x() + (textRect.width() - labelWidth) / 2,
1386                                        textRect.y() + (textRect.height() - labelHeight) / 2,
1387                                        pixmapWidth, pixmapHeight);
1388 
1389                 iconRect = visualRect(button->direction, textRect, iconRect);
1390 
1391                 if (button->direction == Qt::RightToLeft) {
1392                     tf |= Qt::AlignRight;
1393                     textRect.setRight(iconRect.left() - iconSpacing / 2);
1394                 } else {
1395                     tf |= Qt::AlignLeft; //left align, we adjust the text-rect instead
1396                     textRect.setLeft(iconRect.left() + iconRect.width() + iconSpacing / 2);
1397                 }
1398 
1399                 if (button->state & (State_On | State_Sunken))
1400                     iconRect.translate(proxy()->pixelMetric(PM_ButtonShiftHorizontal, opt, widget),
1401                                        proxy()->pixelMetric(PM_ButtonShiftVertical, opt, widget));
1402                 p->drawPixmap(iconRect, pixmap);
1403             } else {
1404                 tf |= Qt::AlignHCenter;
1405             }
1406             if (button->state & (State_On | State_Sunken))
1407                 textRect.translate(proxy()->pixelMetric(PM_ButtonShiftHorizontal, opt, widget),
1408                              proxy()->pixelMetric(PM_ButtonShiftVertical, opt, widget));
1409 
1410             if (button->features & QStyleOptionButton::HasMenu) {
1411                 int indicatorSize = proxy()->pixelMetric(PM_MenuButtonIndicator, button, widget);
1412                 if (button->direction == Qt::LeftToRight)
1413                     textRect = textRect.adjusted(0, 0, -indicatorSize, 0);
1414                 else
1415                     textRect = textRect.adjusted(indicatorSize, 0, 0, 0);
1416             }
1417             proxy()->drawItemText(p, textRect, tf, button->palette, (button->state & State_Enabled),
1418                          button->text, QPalette::ButtonText);
1419         }
1420         break;
1421     case CE_RadioButton:
1422     case CE_CheckBox:
1423         if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
1424             bool isRadio = (element == CE_RadioButton);
1425             QStyleOptionButton subopt = *btn;
1426             subopt.rect = subElementRect(isRadio ? SE_RadioButtonIndicator
1427                                                  : SE_CheckBoxIndicator, btn, widget);
1428             proxy()->drawPrimitive(isRadio ? PE_IndicatorRadioButton : PE_IndicatorCheckBox,
1429                           &subopt, p, widget);
1430             subopt.rect = subElementRect(isRadio ? SE_RadioButtonContents
1431                                                  : SE_CheckBoxContents, btn, widget);
1432             proxy()->drawControl(isRadio ? CE_RadioButtonLabel : CE_CheckBoxLabel, &subopt, p, widget);
1433             if (btn->state & State_HasFocus) {
1434                 QStyleOptionFocusRect fropt;
1435                 fropt.QStyleOption::operator=(*btn);
1436                 fropt.rect = subElementRect(isRadio ? SE_RadioButtonFocusRect
1437                                                     : SE_CheckBoxFocusRect, btn, widget);
1438                 proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, p, widget);
1439             }
1440         }
1441         break;
1442     case CE_RadioButtonLabel:
1443     case CE_CheckBoxLabel:
1444         if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
1445             uint alignment = visualAlignment(btn->direction, Qt::AlignLeft | Qt::AlignVCenter);
1446 
1447             if (!proxy()->styleHint(SH_UnderlineShortcut, btn, widget))
1448                 alignment |= Qt::TextHideMnemonic;
1449             QPixmap pix;
1450             QRect textRect = btn->rect;
1451             if (!btn->icon.isNull()) {
1452                 pix = btn->icon.pixmap(qt_getWindow(widget), btn->iconSize, btn->state & State_Enabled ? QIcon::Normal : QIcon::Disabled);
1453                 proxy()->drawItemPixmap(p, btn->rect, alignment, pix);
1454                 if (btn->direction == Qt::RightToLeft)
1455                     textRect.setRight(textRect.right() - btn->iconSize.width() - 4);
1456                 else
1457                     textRect.setLeft(textRect.left() + btn->iconSize.width() + 4);
1458             }
1459             if (!btn->text.isEmpty()){
1460                 proxy()->drawItemText(p, textRect, alignment | Qt::TextShowMnemonic,
1461                     btn->palette, btn->state & State_Enabled, btn->text, QPalette::WindowText);
1462             }
1463         }
1464         break;
1465 #if QT_CONFIG(menu)
1466     case CE_MenuScroller: {
1467         QStyleOption arrowOpt = *opt;
1468         arrowOpt.state |= State_Enabled;
1469         proxy()->drawPrimitive(((opt->state & State_DownArrow) ? PE_IndicatorArrowDown : PE_IndicatorArrowUp),
1470                     &arrowOpt, p, widget);
1471         break; }
1472     case CE_MenuTearoff:
1473         if (opt->state & State_Selected)
1474             p->fillRect(opt->rect, opt->palette.brush(QPalette::Highlight));
1475         else
1476             p->fillRect(opt->rect, opt->palette.brush(QPalette::Button));
1477         p->setPen(QPen(opt->palette.dark().color(), 1, Qt::DashLine));
1478         p->drawLine(opt->rect.x() + 2, opt->rect.y() + opt->rect.height() / 2 - 1,
1479                     opt->rect.x() + opt->rect.width() - 4,
1480                     opt->rect.y() + opt->rect.height() / 2 - 1);
1481         p->setPen(QPen(opt->palette.light().color(), 1, Qt::DashLine));
1482         p->drawLine(opt->rect.x() + 2, opt->rect.y() + opt->rect.height() / 2,
1483                     opt->rect.x() + opt->rect.width() - 4, opt->rect.y() + opt->rect.height() / 2);
1484         break;
1485 #endif // QT_CONFIG(menu)
1486 #if QT_CONFIG(menubar)
1487     case CE_MenuBarItem:
1488         if (const QStyleOptionMenuItem *mbi = qstyleoption_cast<const QStyleOptionMenuItem *>(opt)) {
1489             uint alignment = Qt::AlignCenter | Qt::TextShowMnemonic | Qt::TextDontClip
1490                             | Qt::TextSingleLine;
1491             if (!proxy()->styleHint(SH_UnderlineShortcut, mbi, widget))
1492                 alignment |= Qt::TextHideMnemonic;
1493             int iconExtent = proxy()->pixelMetric(PM_SmallIconSize, opt);
1494             QPixmap pix = mbi->icon.pixmap(qt_getWindow(widget), QSize(iconExtent, iconExtent), (mbi->state & State_Enabled) ? QIcon::Normal : QIcon::Disabled);
1495             if (!pix.isNull())
1496                 proxy()->drawItemPixmap(p,mbi->rect, alignment, pix);
1497             else
1498                 proxy()->drawItemText(p, mbi->rect, alignment, mbi->palette, mbi->state & State_Enabled,
1499                              mbi->text, QPalette::ButtonText);
1500         }
1501         break;
1502     case CE_MenuBarEmptyArea:
1503         if (widget && !widget->testAttribute(Qt::WA_NoSystemBackground))
1504             p->eraseRect(opt->rect);
1505         break;
1506 #endif // QT_CONFIG(menubar)
1507 #if QT_CONFIG(progressbar)
1508     case CE_ProgressBar:
1509         if (const QStyleOptionProgressBar *pb
1510                 = qstyleoption_cast<const QStyleOptionProgressBar *>(opt)) {
1511             QStyleOptionProgressBar subopt = *pb;
1512             subopt.rect = subElementRect(SE_ProgressBarGroove, pb, widget);
1513             proxy()->drawControl(CE_ProgressBarGroove, &subopt, p, widget);
1514             subopt.rect = subElementRect(SE_ProgressBarContents, pb, widget);
1515             proxy()->drawControl(CE_ProgressBarContents, &subopt, p, widget);
1516             if (pb->textVisible) {
1517                 subopt.rect = subElementRect(SE_ProgressBarLabel, pb, widget);
1518                 proxy()->drawControl(CE_ProgressBarLabel, &subopt, p, widget);
1519             }
1520         }
1521         break;
1522     case CE_ProgressBarGroove:
1523         if (opt->rect.isValid())
1524             qDrawShadePanel(p, opt->rect, opt->palette, true, 1,
1525                             &opt->palette.brush(QPalette::Window));
1526         break;
1527     case CE_ProgressBarLabel:
1528         if (const QStyleOptionProgressBar *pb = qstyleoption_cast<const QStyleOptionProgressBar *>(opt)) {
1529             const bool vertical = pb->orientation == Qt::Vertical;
1530             if (!vertical) {
1531                 QPalette::ColorRole textRole = QPalette::NoRole;
1532                 if ((pb->textAlignment & Qt::AlignCenter) && pb->textVisible
1533                     && ((qint64(pb->progress) - qint64(pb->minimum)) * 2 >= (qint64(pb->maximum) - qint64(pb->minimum)))) {
1534                     textRole = QPalette::HighlightedText;
1535                     //Draw text shadow, This will increase readability when the background of same color
1536                     QRect shadowRect(pb->rect);
1537                     shadowRect.translate(1,1);
1538                     QColor shadowColor = (pb->palette.color(textRole).value() <= 128)
1539                        ? QColor(255,255,255,160) : QColor(0,0,0,160);
1540                     QPalette shadowPalette = pb->palette;
1541                     shadowPalette.setColor(textRole, shadowColor);
1542                     proxy()->drawItemText(p, shadowRect, Qt::AlignCenter | Qt::TextSingleLine, shadowPalette,
1543                                  pb->state & State_Enabled, pb->text, textRole);
1544                 }
1545                 proxy()->drawItemText(p, pb->rect, Qt::AlignCenter | Qt::TextSingleLine, pb->palette,
1546                              pb->state & State_Enabled, pb->text, textRole);
1547             }
1548         }
1549         break;
1550     case CE_ProgressBarContents:
1551         if (const QStyleOptionProgressBar *pb = qstyleoption_cast<const QStyleOptionProgressBar *>(opt)) {
1552 
1553             QRect rect = pb->rect;
1554             const bool vertical = pb->orientation == Qt::Vertical;
1555             const bool inverted = pb->invertedAppearance;
1556             qint64 minimum = qint64(pb->minimum);
1557             qint64 maximum = qint64(pb->maximum);
1558             qint64 progress = qint64(pb->progress);
1559 
1560             QTransform m;
1561 
1562             if (vertical) {
1563                 rect = QRect(rect.y(), rect.x(), rect.height(), rect.width()); // flip width and height
1564                 m.rotate(90);
1565                 m.translate(0, -(rect.height() + rect.y()*2));
1566             }
1567 
1568             QPalette pal2 = pb->palette;
1569             // Correct the highlight color if it is the same as the background
1570             if (pal2.highlight() == pal2.window())
1571                 pal2.setColor(QPalette::Highlight, pb->palette.color(QPalette::Active,
1572                                                                      QPalette::Highlight));
1573             bool reverse = ((!vertical && (pb->direction == Qt::RightToLeft)) || vertical);
1574             if (inverted)
1575                 reverse = !reverse;
1576             int w = rect.width();
1577             if (pb->minimum == 0 && pb->maximum == 0) {
1578                 // draw busy indicator
1579                 int x = (progress - minimum) % (w * 2);
1580                 if (x > w)
1581                     x = 2 * w - x;
1582                 x = reverse ? rect.right() - x : x + rect.x();
1583                 p->setPen(QPen(pal2.highlight().color(), 4));
1584                 p->drawLine(x, rect.y(), x, rect.height());
1585             } else {
1586                 const int unit_width = proxy()->pixelMetric(PM_ProgressBarChunkWidth, pb, widget);
1587                 if (!unit_width)
1588                     return;
1589 
1590                 int u;
1591                 if (unit_width > 1)
1592                     u = ((rect.width() + unit_width) / unit_width);
1593                 else
1594                     u = w / unit_width;
1595                 qint64 p_v = progress - minimum;
1596                 qint64 t_s = (maximum - minimum) ? (maximum - minimum) : qint64(1);
1597 
1598                 if (u > 0 && p_v >= INT_MAX / u && t_s >= u) {
1599                     // scale down to something usable.
1600                     p_v /= u;
1601                     t_s /= u;
1602                 }
1603 
1604                 // nu < tnu, if last chunk is only a partial chunk
1605                 int tnu, nu;
1606                 tnu = nu = p_v * u / t_s;
1607 
1608                 if (nu * unit_width > w)
1609                     --nu;
1610 
1611                 // Draw nu units out of a possible u of unit_width
1612                 // width, each a rectangle bordered by background
1613                 // color, all in a sunken panel with a percentage text
1614                 // display at the end.
1615                 int x = 0;
1616                 int x0 = reverse ? rect.right() - ((unit_width > 1) ? unit_width : 0)
1617                                  : rect.x();
1618 
1619                 QStyleOptionProgressBar pbBits = *pb;
1620                 pbBits.rect = rect;
1621                 pbBits.palette = pal2;
1622                 int myY = pbBits.rect.y();
1623                 int myHeight = pbBits.rect.height();
1624                 pbBits.state = State_None;
1625                 for (int i = 0; i < nu; ++i) {
1626                     pbBits.rect.setRect(x0 + x, myY, unit_width, myHeight);
1627                     pbBits.rect = m.mapRect(QRectF(pbBits.rect)).toRect();
1628                     proxy()->drawPrimitive(PE_IndicatorProgressChunk, &pbBits, p, widget);
1629                     x += reverse ? -unit_width : unit_width;
1630                 }
1631 
1632                 // Draw the last partial chunk to fill up the
1633                 // progress bar entirely
1634                 if (nu < tnu) {
1635                     int pixels_left = w - (nu * unit_width);
1636                     int offset = reverse ? x0 + x + unit_width-pixels_left : x0 + x;
1637                     pbBits.rect.setRect(offset, myY, pixels_left, myHeight);
1638                     pbBits.rect = m.mapRect(QRectF(pbBits.rect)).toRect();
1639                     proxy()->drawPrimitive(PE_IndicatorProgressChunk, &pbBits, p, widget);
1640                 }
1641             }
1642         }
1643         break;
1644 #endif // QT_CONFIG(progressbar)
1645     case CE_HeaderLabel:
1646         if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(opt)) {
1647             QRect rect = header->rect;
1648             if (!header->icon.isNull()) {
1649                 int iconExtent = proxy()->pixelMetric(PM_SmallIconSize, opt);
1650                 QPixmap pixmap
1651                     = header->icon.pixmap(qt_getWindow(widget), QSize(iconExtent, iconExtent), (header->state & State_Enabled) ? QIcon::Normal : QIcon::Disabled);
1652                 int pixw = pixmap.width() / pixmap.devicePixelRatio();
1653 
1654                 QRect aligned = alignedRect(header->direction, QFlag(header->iconAlignment), pixmap.size() / pixmap.devicePixelRatio(), rect);
1655                 QRect inter = aligned.intersected(rect);
1656                 p->drawPixmap(inter.x(), inter.y(), pixmap,
1657                               inter.x() - aligned.x(), inter.y() - aligned.y(),
1658                               aligned.width() * pixmap.devicePixelRatio(),
1659                               pixmap.height() * pixmap.devicePixelRatio());
1660 
1661                 const int margin = proxy()->pixelMetric(QStyle::PM_HeaderMargin, opt, widget);
1662                 if (header->direction == Qt::LeftToRight)
1663                     rect.setLeft(rect.left() + pixw + margin);
1664                 else
1665                     rect.setRight(rect.right() - pixw - margin);
1666             }
1667             if (header->state & QStyle::State_On) {
1668                 QFont fnt = p->font();
1669                 fnt.setBold(true);
1670                 p->setFont(fnt);
1671             }
1672             proxy()->drawItemText(p, rect, header->textAlignment, header->palette,
1673                          (header->state & State_Enabled), header->text, QPalette::ButtonText);
1674         }
1675         break;
1676 #if QT_CONFIG(toolbutton)
1677     case CE_ToolButtonLabel:
1678         if (const QStyleOptionToolButton *toolbutton
1679                 = qstyleoption_cast<const QStyleOptionToolButton *>(opt)) {
1680             QRect rect = toolbutton->rect;
1681             int shiftX = 0;
1682             int shiftY = 0;
1683             if (toolbutton->state & (State_Sunken | State_On)) {
1684                 shiftX = proxy()->pixelMetric(PM_ButtonShiftHorizontal, toolbutton, widget);
1685                 shiftY = proxy()->pixelMetric(PM_ButtonShiftVertical, toolbutton, widget);
1686             }
1687             // Arrow type always overrules and is always shown
1688             bool hasArrow = toolbutton->features & QStyleOptionToolButton::Arrow;
1689             if (((!hasArrow && toolbutton->icon.isNull()) && !toolbutton->text.isEmpty())
1690                 || toolbutton->toolButtonStyle == Qt::ToolButtonTextOnly) {
1691                 int alignment = Qt::AlignCenter | Qt::TextShowMnemonic;
1692                 if (!proxy()->styleHint(SH_UnderlineShortcut, opt, widget))
1693                     alignment |= Qt::TextHideMnemonic;
1694                 rect.translate(shiftX, shiftY);
1695                 p->setFont(toolbutton->font);
1696                 proxy()->drawItemText(p, rect, alignment, toolbutton->palette,
1697                              opt->state & State_Enabled, toolbutton->text,
1698                              QPalette::ButtonText);
1699             } else {
1700                 QPixmap pm;
1701                 QSize pmSize = toolbutton->iconSize;
1702                 if (!toolbutton->icon.isNull()) {
1703                     QIcon::State state = toolbutton->state & State_On ? QIcon::On : QIcon::Off;
1704                     QIcon::Mode mode;
1705                     if (!(toolbutton->state & State_Enabled))
1706                         mode = QIcon::Disabled;
1707                     else if ((opt->state & State_MouseOver) && (opt->state & State_AutoRaise))
1708                         mode = QIcon::Active;
1709                     else
1710                         mode = QIcon::Normal;
1711                     pm = toolbutton->icon.pixmap(qt_getWindow(widget), toolbutton->rect.size().boundedTo(toolbutton->iconSize),
1712                                                  mode, state);
1713                     pmSize = pm.size() / pm.devicePixelRatio();
1714                 }
1715 
1716                 if (toolbutton->toolButtonStyle != Qt::ToolButtonIconOnly) {
1717                     p->setFont(toolbutton->font);
1718                     QRect pr = rect,
1719                     tr = rect;
1720                     int alignment = Qt::TextShowMnemonic;
1721                     if (!proxy()->styleHint(SH_UnderlineShortcut, opt, widget))
1722                         alignment |= Qt::TextHideMnemonic;
1723 
1724                     if (toolbutton->toolButtonStyle == Qt::ToolButtonTextUnderIcon) {
1725                         pr.setHeight(pmSize.height() + 4); //### 4 is currently hardcoded in QToolButton::sizeHint()
1726                         tr.adjust(0, pr.height() - 1, 0, -1);
1727                         pr.translate(shiftX, shiftY);
1728                         if (!hasArrow) {
1729                             proxy()->drawItemPixmap(p, pr, Qt::AlignCenter, pm);
1730                         } else {
1731                             drawArrow(proxy(), toolbutton, pr, p, widget);
1732                         }
1733                         alignment |= Qt::AlignCenter;
1734                     } else {
1735                         pr.setWidth(pmSize.width() + 4); //### 4 is currently hardcoded in QToolButton::sizeHint()
1736                         tr.adjust(pr.width(), 0, 0, 0);
1737                         pr.translate(shiftX, shiftY);
1738                         if (!hasArrow) {
1739                             proxy()->drawItemPixmap(p, QStyle::visualRect(opt->direction, rect, pr), Qt::AlignCenter, pm);
1740                         } else {
1741                             drawArrow(proxy(), toolbutton, pr, p, widget);
1742                         }
1743                         alignment |= Qt::AlignLeft | Qt::AlignVCenter;
1744                     }
1745                     tr.translate(shiftX, shiftY);
1746                     const QString text = d->toolButtonElideText(toolbutton, tr, alignment);
1747                     proxy()->drawItemText(p, QStyle::visualRect(opt->direction, rect, tr), alignment, toolbutton->palette,
1748                                  toolbutton->state & State_Enabled, text,
1749                                  QPalette::ButtonText);
1750                 } else {
1751                     rect.translate(shiftX, shiftY);
1752                     if (hasArrow) {
1753                         drawArrow(proxy(), toolbutton, rect, p, widget);
1754                     } else {
1755                         proxy()->drawItemPixmap(p, rect, Qt::AlignCenter, pm);
1756                     }
1757                 }
1758             }
1759         }
1760         break;
1761 #endif // QT_CONFIG(toolbutton)
1762 #if QT_CONFIG(toolbox)
1763     case CE_ToolBoxTab:
1764         if (const QStyleOptionToolBox *tb = qstyleoption_cast<const QStyleOptionToolBox *>(opt)) {
1765             proxy()->drawControl(CE_ToolBoxTabShape, tb, p, widget);
1766             proxy()->drawControl(CE_ToolBoxTabLabel, tb, p, widget);
1767         }
1768         break;
1769     case CE_ToolBoxTabShape:
1770         if (const QStyleOptionToolBox *tb = qstyleoption_cast<const QStyleOptionToolBox *>(opt)) {
1771             p->setPen(tb->palette.mid().color().darker(150));
1772             bool oldQt4CompatiblePainting = p->testRenderHint(QPainter::Qt4CompatiblePainting);
1773             p->setRenderHint(QPainter::Qt4CompatiblePainting);
1774             int d = 20 + tb->rect.height() - 3;
1775             if (tb->direction != Qt::RightToLeft) {
1776                 const QPoint points[] = {
1777                     QPoint(-1, tb->rect.height() + 1),
1778                     QPoint(-1, 1),
1779                     QPoint(tb->rect.width() - d, 1),
1780                     QPoint(tb->rect.width() - 20, tb->rect.height() - 2),
1781                     QPoint(tb->rect.width() - 1, tb->rect.height() - 2),
1782                     QPoint(tb->rect.width() - 1, tb->rect.height() + 1),
1783                     QPoint(-1, tb->rect.height() + 1),
1784                 };
1785                 p->drawPolygon(points, sizeof points / sizeof *points);
1786             } else {
1787                 const QPoint points[] = {
1788                     QPoint(tb->rect.width(), tb->rect.height() + 1),
1789                     QPoint(tb->rect.width(), 1),
1790                     QPoint(d - 1, 1),
1791                     QPoint(20 - 1, tb->rect.height() - 2),
1792                     QPoint(0, tb->rect.height() - 2),
1793                     QPoint(0, tb->rect.height() + 1),
1794                     QPoint(tb->rect.width(), tb->rect.height() + 1),
1795                 };
1796                 p->drawPolygon(points, sizeof points / sizeof *points);
1797             }
1798             p->setRenderHint(QPainter::Qt4CompatiblePainting, oldQt4CompatiblePainting);
1799             p->setPen(tb->palette.light().color());
1800             if (tb->direction != Qt::RightToLeft) {
1801                 p->drawLine(0, 2, tb->rect.width() - d, 2);
1802                 p->drawLine(tb->rect.width() - d - 1, 2, tb->rect.width() - 21, tb->rect.height() - 1);
1803                 p->drawLine(tb->rect.width() - 20, tb->rect.height() - 1,
1804                             tb->rect.width(), tb->rect.height() - 1);
1805             } else {
1806                 p->drawLine(tb->rect.width() - 1, 2, d - 1, 2);
1807                 p->drawLine(d, 2, 20, tb->rect.height() - 1);
1808                 p->drawLine(19, tb->rect.height() - 1,
1809                             -1, tb->rect.height() - 1);
1810             }
1811             p->setBrush(Qt::NoBrush);
1812         }
1813         break;
1814 #endif // QT_CONFIG(toolbox)
1815 #if QT_CONFIG(tabbar)
1816     case CE_TabBarTab:
1817         if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(opt)) {
1818             proxy()->drawControl(CE_TabBarTabShape, tab, p, widget);
1819             proxy()->drawControl(CE_TabBarTabLabel, tab, p, widget);
1820         }
1821         break;
1822     case CE_TabBarTabShape:
1823         if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(opt)) {
1824             p->save();
1825 
1826             QRect rect(tab->rect);
1827             bool selected = tab->state & State_Selected;
1828             bool onlyOne = tab->position == QStyleOptionTab::OnlyOneTab;
1829             int tabOverlap = onlyOne ? 0 : proxy()->pixelMetric(PM_TabBarTabOverlap, opt, widget);
1830 
1831             if (!selected) {
1832                 switch (tab->shape) {
1833                 case QTabBar::TriangularNorth:
1834                     rect.adjust(0, 0, 0, -tabOverlap);
1835                     if(!selected)
1836                         rect.adjust(1, 1, -1, 0);
1837                     break;
1838                 case QTabBar::TriangularSouth:
1839                     rect.adjust(0, tabOverlap, 0, 0);
1840                     if(!selected)
1841                         rect.adjust(1, 0, -1, -1);
1842                     break;
1843                 case QTabBar::TriangularEast:
1844                     rect.adjust(tabOverlap, 0, 0, 0);
1845                     if(!selected)
1846                         rect.adjust(0, 1, -1, -1);
1847                     break;
1848                 case QTabBar::TriangularWest:
1849                     rect.adjust(0, 0, -tabOverlap, 0);
1850                     if(!selected)
1851                         rect.adjust(1, 1, 0, -1);
1852                     break;
1853                 default:
1854                     break;
1855                 }
1856             }
1857 
1858             p->setPen(QPen(tab->palette.windowText(), 0));
1859             if (selected) {
1860                 p->setBrush(tab->palette.base());
1861             } else {
1862                 if (widget && widget->parentWidget())
1863                     p->setBrush(widget->parentWidget()->palette().window());
1864                 else
1865                     p->setBrush(tab->palette.window());
1866             }
1867 
1868             int y;
1869             int x;
1870             QPolygon a(10);
1871             switch (tab->shape) {
1872             case QTabBar::TriangularNorth:
1873             case QTabBar::TriangularSouth: {
1874                 a.setPoint(0, 0, -1);
1875                 a.setPoint(1, 0, 0);
1876                 y = rect.height() - 2;
1877                 x = y / 3;
1878                 a.setPoint(2, x++, y - 1);
1879                 ++x;
1880                 a.setPoint(3, x++, y++);
1881                 a.setPoint(4, x, y);
1882 
1883                 int i;
1884                 int right = rect.width() - 1;
1885                 for (i = 0; i < 5; ++i)
1886                     a.setPoint(9 - i, right - a.point(i).x(), a.point(i).y());
1887                 if (tab->shape == QTabBar::TriangularNorth)
1888                     for (i = 0; i < 10; ++i)
1889                         a.setPoint(i, a.point(i).x(), rect.height() - 1 - a.point(i).y());
1890 
1891                 a.translate(rect.left(), rect.top());
1892                 p->setRenderHint(QPainter::Antialiasing);
1893                 p->translate(0, 0.5);
1894 
1895                 QPainterPath path;
1896                 path.addPolygon(a);
1897                 p->drawPath(path);
1898                 break; }
1899             case QTabBar::TriangularEast:
1900             case QTabBar::TriangularWest: {
1901                 a.setPoint(0, -1, 0);
1902                 a.setPoint(1, 0, 0);
1903                 x = rect.width() - 2;
1904                 y = x / 3;
1905                 a.setPoint(2, x - 1, y++);
1906                 ++y;
1907                 a.setPoint(3, x++, y++);
1908                 a.setPoint(4, x, y);
1909                 int i;
1910                 int bottom = rect.height() - 1;
1911                 for (i = 0; i < 5; ++i)
1912                     a.setPoint(9 - i, a.point(i).x(), bottom - a.point(i).y());
1913                 if (tab->shape == QTabBar::TriangularWest)
1914                     for (i = 0; i < 10; ++i)
1915                         a.setPoint(i, rect.width() - 1 - a.point(i).x(), a.point(i).y());
1916                 a.translate(rect.left(), rect.top());
1917                 p->setRenderHint(QPainter::Antialiasing);
1918                 p->translate(0.5, 0);
1919                 QPainterPath path;
1920                 path.addPolygon(a);
1921                 p->drawPath(path);
1922                 break; }
1923             default:
1924                 break;
1925             }
1926             p->restore();
1927         }
1928         break;
1929     case CE_ToolBoxTabLabel:
1930         if (const QStyleOptionToolBox *tb = qstyleoption_cast<const QStyleOptionToolBox *>(opt)) {
1931             bool enabled = tb->state & State_Enabled;
1932             bool selected = tb->state & State_Selected;
1933             int iconExtent = proxy()->pixelMetric(QStyle::PM_SmallIconSize, tb, widget);
1934             QPixmap pm = tb->icon.pixmap(qt_getWindow(widget), QSize(iconExtent, iconExtent),
1935                                          enabled ? QIcon::Normal : QIcon::Disabled);
1936 
1937             QRect cr = subElementRect(QStyle::SE_ToolBoxTabContents, tb, widget);
1938             QRect tr, ir;
1939             int ih = 0;
1940             if (pm.isNull()) {
1941                 tr = cr;
1942                 tr.adjust(4, 0, -8, 0);
1943             } else {
1944                 int iw = pm.width() / pm.devicePixelRatio() + 4;
1945                 ih = pm.height()/ pm.devicePixelRatio();
1946                 ir = QRect(cr.left() + 4, cr.top(), iw + 2, ih);
1947                 tr = QRect(ir.right(), cr.top(), cr.width() - ir.right() - 4, cr.height());
1948             }
1949 
1950             if (selected && proxy()->styleHint(QStyle::SH_ToolBox_SelectedPageTitleBold, tb, widget)) {
1951                 QFont f(p->font());
1952                 f.setBold(true);
1953                 p->setFont(f);
1954             }
1955 
1956             QString txt = tb->fontMetrics.elidedText(tb->text, Qt::ElideRight, tr.width());
1957 
1958             if (ih)
1959                 p->drawPixmap(ir.left(), (tb->rect.height() - ih) / 2, pm);
1960 
1961             int alignment = Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic;
1962             if (!proxy()->styleHint(QStyle::SH_UnderlineShortcut, tb, widget))
1963                 alignment |= Qt::TextHideMnemonic;
1964             proxy()->drawItemText(p, tr, alignment, tb->palette, enabled, txt, QPalette::ButtonText);
1965 
1966             if (!txt.isEmpty() && opt->state & State_HasFocus) {
1967                 QStyleOptionFocusRect opt;
1968                 opt.rect = tr;
1969                 opt.palette = tb->palette;
1970                 opt.state = QStyle::State_None;
1971                 proxy()->drawPrimitive(QStyle::PE_FrameFocusRect, &opt, p, widget);
1972             }
1973         }
1974         break;
1975     case CE_TabBarTabLabel:
1976         if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(opt)) {
1977             QRect tr = tab->rect;
1978             bool verticalTabs = tab->shape == QTabBar::RoundedEast
1979                                 || tab->shape == QTabBar::RoundedWest
1980                                 || tab->shape == QTabBar::TriangularEast
1981                                 || tab->shape == QTabBar::TriangularWest;
1982 
1983             int alignment = Qt::AlignCenter | Qt::TextShowMnemonic;
1984             if (!proxy()->styleHint(SH_UnderlineShortcut, opt, widget))
1985                 alignment |= Qt::TextHideMnemonic;
1986 
1987             if (verticalTabs) {
1988                 p->save();
1989                 int newX, newY, newRot;
1990                 if (tab->shape == QTabBar::RoundedEast || tab->shape == QTabBar::TriangularEast) {
1991                     newX = tr.width() + tr.x();
1992                     newY = tr.y();
1993                     newRot = 90;
1994                 } else {
1995                     newX = tr.x();
1996                     newY = tr.y() + tr.height();
1997                     newRot = -90;
1998                 }
1999                 QTransform m = QTransform::fromTranslate(newX, newY);
2000                 m.rotate(newRot);
2001                 p->setTransform(m, true);
2002             }
2003             QRect iconRect;
2004             d->tabLayout(tab, widget, &tr, &iconRect);
2005             tr = proxy()->subElementRect(SE_TabBarTabText, opt, widget); //we compute tr twice because the style may override subElementRect
2006 
2007             if (!tab->icon.isNull()) {
2008                 QPixmap tabIcon = tab->icon.pixmap(qt_getWindow(widget), tab->iconSize,
2009                                                    (tab->state & State_Enabled) ? QIcon::Normal
2010                                                                                 : QIcon::Disabled,
2011                                                    (tab->state & State_Selected) ? QIcon::On
2012                                                                                  : QIcon::Off);
2013                 p->drawPixmap(iconRect.x(), iconRect.y(), tabIcon);
2014             }
2015 
2016             proxy()->drawItemText(p, tr, alignment, tab->palette, tab->state & State_Enabled, tab->text, QPalette::WindowText);
2017             if (verticalTabs)
2018                 p->restore();
2019 
2020             if (tab->state & State_HasFocus) {
2021                 const int OFFSET = 1 + pixelMetric(PM_DefaultFrameWidth);
2022 
2023                 int x1, x2;
2024                 x1 = tab->rect.left();
2025                 x2 = tab->rect.right() - 1;
2026 
2027                 QStyleOptionFocusRect fropt;
2028                 fropt.QStyleOption::operator=(*tab);
2029                 fropt.rect.setRect(x1 + 1 + OFFSET, tab->rect.y() + OFFSET,
2030                                    x2 - x1 - 2*OFFSET, tab->rect.height() - 2*OFFSET);
2031                 drawPrimitive(PE_FrameFocusRect, &fropt, p, widget);
2032             }
2033         }
2034         break;
2035 #endif // QT_CONFIG(tabbar)
2036 #if QT_CONFIG(sizegrip)
2037     case CE_SizeGrip: {
2038         p->save();
2039         int x, y, w, h;
2040         opt->rect.getRect(&x, &y, &w, &h);
2041 
2042         int sw = qMin(h, w);
2043         if (h > w)
2044             p->translate(0, h - w);
2045         else
2046             p->translate(w - h, 0);
2047 
2048         int sx = x;
2049         int sy = y;
2050         int s = sw / 3;
2051 
2052         Qt::Corner corner;
2053         if (const QStyleOptionSizeGrip *sgOpt = qstyleoption_cast<const QStyleOptionSizeGrip *>(opt))
2054             corner = sgOpt->corner;
2055         else if (opt->direction == Qt::RightToLeft)
2056             corner = Qt::BottomLeftCorner;
2057         else
2058             corner = Qt::BottomRightCorner;
2059 
2060         if (corner == Qt::BottomLeftCorner) {
2061             sx = x + sw;
2062             for (int i = 0; i < 4; ++i) {
2063                 p->setPen(QPen(opt->palette.light().color(), 1));
2064                 p->drawLine(x, sy - 1 , sx + 1, sw);
2065                 p->setPen(QPen(opt->palette.dark().color(), 1));
2066                 p->drawLine(x, sy, sx, sw);
2067                 p->setPen(QPen(opt->palette.dark().color(), 1));
2068                 p->drawLine(x, sy + 1, sx - 1, sw);
2069                 sx -= s;
2070                 sy += s;
2071             }
2072         } else if (corner == Qt::BottomRightCorner) {
2073             for (int i = 0; i < 4; ++i) {
2074                 p->setPen(QPen(opt->palette.light().color(), 1));
2075                 p->drawLine(sx - 1, sw, sw, sy - 1);
2076                 p->setPen(QPen(opt->palette.dark().color(), 1));
2077                 p->drawLine(sx, sw, sw, sy);
2078                 p->setPen(QPen(opt->palette.dark().color(), 1));
2079                 p->drawLine(sx + 1, sw, sw, sy + 1);
2080                 sx += s;
2081                 sy += s;
2082             }
2083         } else if (corner == Qt::TopRightCorner) {
2084             sy = y + sw;
2085             for (int i = 0; i < 4; ++i) {
2086                 p->setPen(QPen(opt->palette.light().color(), 1));
2087                 p->drawLine(sx - 1, y, sw, sy + 1);
2088                 p->setPen(QPen(opt->palette.dark().color(), 1));
2089                 p->drawLine(sx, y, sw, sy);
2090                 p->setPen(QPen(opt->palette.dark().color(), 1));
2091                 p->drawLine(sx + 1, y, sw, sy - 1);
2092                 sx += s;
2093                 sy -= s;
2094             }
2095         } else if (corner == Qt::TopLeftCorner) {
2096             for (int i = 0; i < 4; ++i) {
2097                 p->setPen(QPen(opt->palette.light().color(), 1));
2098                 p->drawLine(x, sy - 1, sx - 1, y);
2099                 p->setPen(QPen(opt->palette.dark().color(), 1));
2100                 p->drawLine(x, sy, sx, y);
2101                 p->setPen(QPen(opt->palette.dark().color(), 1));
2102                 p->drawLine(x, sy + 1, sx + 1, y);
2103                 sx += s;
2104                 sy += s;
2105             }
2106         }
2107         p->restore();
2108         break; }
2109 #endif // QT_CONFIG(sizegrip)
2110 #if QT_CONFIG(rubberband)
2111     case CE_RubberBand: {
2112         if (const QStyleOptionRubberBand *rbOpt = qstyleoption_cast<const QStyleOptionRubberBand *>(opt)) {
2113             QPixmap tiledPixmap(16, 16);
2114             QPainter pixmapPainter(&tiledPixmap);
2115             pixmapPainter.setPen(Qt::NoPen);
2116             pixmapPainter.setBrush(Qt::Dense4Pattern);
2117             pixmapPainter.setBackground(QBrush(opt->palette.base()));
2118             pixmapPainter.setBackgroundMode(Qt::OpaqueMode);
2119             pixmapPainter.drawRect(0, 0, tiledPixmap.width(), tiledPixmap.height());
2120             pixmapPainter.end();
2121             // ### workaround for borked XRENDER
2122             tiledPixmap = QPixmap::fromImage(tiledPixmap.toImage());
2123 
2124             p->save();
2125             QRect r = opt->rect;
2126             QStyleHintReturnMask mask;
2127             if (proxy()->styleHint(QStyle::SH_RubberBand_Mask, opt, widget, &mask))
2128                 p->setClipRegion(mask.region);
2129             p->drawTiledPixmap(r.x(), r.y(), r.width(), r.height(), tiledPixmap);
2130             p->setPen(opt->palette.color(QPalette::Active, QPalette::WindowText));
2131             p->setBrush(Qt::NoBrush);
2132             p->drawRect(r.adjusted(0, 0, -1, -1));
2133             if (rbOpt->shape == QRubberBand::Rectangle)
2134                 p->drawRect(r.adjusted(3, 3, -4, -4));
2135             p->restore();
2136         }
2137         break; }
2138 #endif // QT_CONFIG(rubberband)
2139 #if QT_CONFIG(dockwidget)
2140     case CE_DockWidgetTitle:
2141         if (const QStyleOptionDockWidget *dwOpt = qstyleoption_cast<const QStyleOptionDockWidget *>(opt)) {
2142             QRect r = dwOpt->rect.adjusted(0, 0, -1, -1);
2143             if (dwOpt->movable) {
2144                 p->setPen(dwOpt->palette.color(QPalette::Dark));
2145                 p->drawRect(r);
2146             }
2147 
2148             if (!dwOpt->title.isEmpty()) {
2149                 const bool verticalTitleBar = dwOpt->verticalTitleBar;
2150 
2151                 if (verticalTitleBar) {
2152                     r = r.transposed();
2153 
2154                     p->save();
2155                     p->translate(r.left(), r.top() + r.width());
2156                     p->rotate(-90);
2157                     p->translate(-r.left(), -r.top());
2158                 }
2159 
2160                 const int indent = p->fontMetrics().descent();
2161                 proxy()->drawItemText(p, r.adjusted(indent + 1, 1, -indent - 1, -1),
2162                               Qt::AlignLeft | Qt::AlignVCenter, dwOpt->palette,
2163                               dwOpt->state & State_Enabled, dwOpt->title,
2164                               QPalette::WindowText);
2165 
2166                 if (verticalTitleBar)
2167                     p->restore();
2168             }
2169         }
2170         break;
2171 #endif // QT_CONFIG(dockwidget)
2172     case CE_Header:
2173         if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(opt)) {
2174             QRegion clipRegion = p->clipRegion();
2175             p->setClipRect(opt->rect);
2176             proxy()->drawControl(CE_HeaderSection, header, p, widget);
2177             QStyleOptionHeader subopt = *header;
2178             subopt.rect = subElementRect(SE_HeaderLabel, header, widget);
2179             if (subopt.rect.isValid())
2180                 proxy()->drawControl(CE_HeaderLabel, &subopt, p, widget);
2181             if (header->sortIndicator != QStyleOptionHeader::None) {
2182                 subopt.rect = subElementRect(SE_HeaderArrow, opt, widget);
2183                 proxy()->drawPrimitive(PE_IndicatorHeaderArrow, &subopt, p, widget);
2184             }
2185             p->setClipRegion(clipRegion);
2186         }
2187         break;
2188     case CE_FocusFrame:
2189             p->fillRect(opt->rect, opt->palette.windowText());
2190         break;
2191     case CE_HeaderSection:
2192             qDrawShadePanel(p, opt->rect, opt->palette,
2193                         opt->state & State_Sunken, 1,
2194                         &opt->palette.brush(QPalette::Button));
2195         break;
2196     case CE_HeaderEmptyArea:
2197             p->fillRect(opt->rect, opt->palette.window());
2198         break;
2199 #if QT_CONFIG(combobox)
2200     case CE_ComboBoxLabel:
2201         if (const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(opt)) {
2202             QRect editRect = proxy()->subControlRect(CC_ComboBox, cb, SC_ComboBoxEditField, widget);
2203             p->save();
2204             p->setClipRect(editRect);
2205             if (!cb->currentIcon.isNull()) {
2206                 QIcon::Mode mode = cb->state & State_Enabled ? QIcon::Normal
2207                                                              : QIcon::Disabled;
2208                 QPixmap pixmap = cb->currentIcon.pixmap(qt_getWindow(widget), cb->iconSize, mode);
2209                 QRect iconRect(editRect);
2210                 iconRect.setWidth(cb->iconSize.width() + 4);
2211                 iconRect = alignedRect(cb->direction,
2212                                        Qt::AlignLeft | Qt::AlignVCenter,
2213                                        iconRect.size(), editRect);
2214                 if (cb->editable)
2215                     p->fillRect(iconRect, opt->palette.brush(QPalette::Base));
2216                 proxy()->drawItemPixmap(p, iconRect, Qt::AlignCenter, pixmap);
2217 
2218                 if (cb->direction == Qt::RightToLeft)
2219                     editRect.translate(-4 - cb->iconSize.width(), 0);
2220                 else
2221                     editRect.translate(cb->iconSize.width() + 4, 0);
2222             }
2223             if (!cb->currentText.isEmpty() && !cb->editable) {
2224                 proxy()->drawItemText(p, editRect.adjusted(1, 0, -1, 0),
2225                              visualAlignment(cb->direction, Qt::AlignLeft | Qt::AlignVCenter),
2226                              cb->palette, cb->state & State_Enabled, cb->currentText);
2227             }
2228             p->restore();
2229         }
2230         break;
2231 #endif // QT_CONFIG(combobox)
2232 #if QT_CONFIG(toolbar)
2233     case CE_ToolBar:
2234         if (const QStyleOptionToolBar *toolBar = qstyleoption_cast<const QStyleOptionToolBar *>(opt)) {
2235             // Compatibility with styles that use PE_PanelToolBar
2236             QStyleOptionFrame frame;
2237             frame.QStyleOption::operator=(*toolBar);
2238             frame.lineWidth = toolBar->lineWidth;
2239             frame.midLineWidth = toolBar->midLineWidth;
2240             proxy()->drawPrimitive(PE_PanelToolBar, opt, p, widget);
2241 
2242             if (widget && qobject_cast<QToolBar *>(widget->parentWidget()))
2243                 break;
2244             qDrawShadePanel(p, toolBar->rect, toolBar->palette, false, toolBar->lineWidth,
2245                             &toolBar->palette.brush(QPalette::Button));
2246         }
2247         break;
2248 #endif // QT_CONFIG(toolbar)
2249     case CE_ColumnViewGrip: {
2250         // draw background gradients
2251         QLinearGradient g(0, 0, opt->rect.width(), 0);
2252         g.setColorAt(0, opt->palette.color(QPalette::Active, QPalette::Mid));
2253         g.setColorAt(0.5, Qt::white);
2254         p->fillRect(QRect(0, 0, opt->rect.width(), opt->rect.height()), g);
2255 
2256         // draw the two lines
2257         QPen pen(p->pen());
2258         pen.setWidth(opt->rect.width()/20);
2259         pen.setColor(opt->palette.color(QPalette::Active, QPalette::Dark));
2260         p->setPen(pen);
2261 
2262         int line1starting = opt->rect.width()*8 / 20;
2263         int line2starting = opt->rect.width()*13 / 20;
2264         int top = opt->rect.height()*20/75;
2265         int bottom = opt->rect.height() - 1 - top;
2266         p->drawLine(line1starting, top, line1starting, bottom);
2267         p->drawLine(line2starting, top, line2starting, bottom);
2268         }
2269         break;
2270 
2271 #if QT_CONFIG(itemviews)
2272     case CE_ItemViewItem:
2273         if (const QStyleOptionViewItem *vopt = qstyleoption_cast<const QStyleOptionViewItem *>(opt)) {
2274             p->save();
2275             p->setClipRect(opt->rect);
2276 
2277             QRect checkRect = proxy()->subElementRect(SE_ItemViewItemCheckIndicator, vopt, widget);
2278             QRect iconRect = proxy()->subElementRect(SE_ItemViewItemDecoration, vopt, widget);
2279             QRect textRect = proxy()->subElementRect(SE_ItemViewItemText, vopt, widget);
2280 
2281             // draw the background
2282             proxy()->drawPrimitive(PE_PanelItemViewItem, opt, p, widget);
2283 
2284             // draw the check mark
2285             if (vopt->features & QStyleOptionViewItem::HasCheckIndicator) {
2286                 QStyleOptionViewItem option(*vopt);
2287                 option.rect = checkRect;
2288                 option.state = option.state & ~QStyle::State_HasFocus;
2289 
2290                 switch (vopt->checkState) {
2291                 case Qt::Unchecked:
2292                     option.state |= QStyle::State_Off;
2293                     break;
2294                 case Qt::PartiallyChecked:
2295                     option.state |= QStyle::State_NoChange;
2296                     break;
2297                 case Qt::Checked:
2298                     option.state |= QStyle::State_On;
2299                     break;
2300                 }
2301                 proxy()->drawPrimitive(QStyle::PE_IndicatorItemViewItemCheck, &option, p, widget);
2302             }
2303 
2304             // draw the icon
2305             QIcon::Mode mode = QIcon::Normal;
2306             if (!(vopt->state & QStyle::State_Enabled))
2307                 mode = QIcon::Disabled;
2308             else if (vopt->state & QStyle::State_Selected)
2309                 mode = QIcon::Selected;
2310             QIcon::State state = vopt->state & QStyle::State_Open ? QIcon::On : QIcon::Off;
2311             vopt->icon.paint(p, iconRect, vopt->decorationAlignment, mode, state);
2312 
2313             // draw the text
2314             if (!vopt->text.isEmpty()) {
2315                 QPalette::ColorGroup cg = vopt->state & QStyle::State_Enabled
2316                                       ? QPalette::Normal : QPalette::Disabled;
2317                 if (cg == QPalette::Normal && !(vopt->state & QStyle::State_Active))
2318                     cg = QPalette::Inactive;
2319 
2320                 if (vopt->state & QStyle::State_Selected) {
2321                     p->setPen(vopt->palette.color(cg, QPalette::HighlightedText));
2322                 } else {
2323                     p->setPen(vopt->palette.color(cg, QPalette::Text));
2324                 }
2325                 if (vopt->state & QStyle::State_Editing) {
2326                     p->setPen(vopt->palette.color(cg, QPalette::Text));
2327                     p->drawRect(textRect.adjusted(0, 0, -1, -1));
2328                 }
2329 
2330                 d->viewItemDrawText(p, vopt, textRect);
2331             }
2332 
2333             // draw the focus rect
2334              if (vopt->state & QStyle::State_HasFocus) {
2335                 QStyleOptionFocusRect o;
2336                 o.QStyleOption::operator=(*vopt);
2337                 o.rect = proxy()->subElementRect(SE_ItemViewItemFocusRect, vopt, widget);
2338                 o.state |= QStyle::State_KeyboardFocusChange;
2339                 o.state |= QStyle::State_Item;
2340                 QPalette::ColorGroup cg = (vopt->state & QStyle::State_Enabled)
2341                               ? QPalette::Normal : QPalette::Disabled;
2342                 o.backgroundColor = vopt->palette.color(cg, (vopt->state & QStyle::State_Selected)
2343                                              ? QPalette::Highlight : QPalette::Window);
2344                 proxy()->drawPrimitive(QStyle::PE_FrameFocusRect, &o, p, widget);
2345             }
2346 
2347              p->restore();
2348         }
2349         break;
2350 
2351 #endif // QT_CONFIG(itemviews)
2352 #ifndef QT_NO_FRAME
2353     case CE_ShapedFrame:
2354         if (const QStyleOptionFrame *f = qstyleoption_cast<const QStyleOptionFrame *>(opt)) {
2355             int frameShape  = f->frameShape;
2356             int frameShadow = QFrame::Plain;
2357             if (f->state & QStyle::State_Sunken) {
2358                 frameShadow = QFrame::Sunken;
2359             } else if (f->state & QStyle::State_Raised) {
2360                 frameShadow = QFrame::Raised;
2361             }
2362 
2363             int lw = f->lineWidth;
2364             int mlw = f->midLineWidth;
2365             QPalette::ColorRole foregroundRole = QPalette::WindowText;
2366             if (widget)
2367                 foregroundRole = widget->foregroundRole();
2368 
2369             switch (frameShape) {
2370             case QFrame::Box:
2371                 if (frameShadow == QFrame::Plain) {
2372                     qDrawPlainRect(p, f->rect, f->palette.color(foregroundRole), lw);
2373                 } else {
2374                     qDrawShadeRect(p, f->rect, f->palette, frameShadow == QFrame::Sunken, lw, mlw);
2375                 }
2376                 break;
2377             case QFrame::StyledPanel:
2378                 //keep the compatibility with Qt 4.4 if there is a proxy style.
2379                 //be sure to call drawPrimitive(QStyle::PE_Frame) on the proxy style
2380                 if (widget) {
2381                     widget->style()->drawPrimitive(QStyle::PE_Frame, opt, p, widget);
2382                 } else {
2383                     proxy()->drawPrimitive(QStyle::PE_Frame, opt, p, widget);
2384                 }
2385                 break;
2386             case QFrame::Panel:
2387                 if (frameShadow == QFrame::Plain) {
2388                     qDrawPlainRect(p, f->rect, f->palette.color(foregroundRole), lw);
2389                 } else {
2390                     qDrawShadePanel(p, f->rect, f->palette, frameShadow == QFrame::Sunken, lw);
2391                 }
2392                 break;
2393             case QFrame::WinPanel:
2394                 if (frameShadow == QFrame::Plain) {
2395                     qDrawPlainRect(p, f->rect, f->palette.color(foregroundRole), lw);
2396                 } else {
2397                     qDrawWinPanel(p, f->rect, f->palette, frameShadow == QFrame::Sunken);
2398                 }
2399                 break;
2400             case QFrame::HLine:
2401             case QFrame::VLine: {
2402                 QPoint p1, p2;
2403                 if (frameShape == QFrame::HLine) {
2404                     p1 = QPoint(opt->rect.x(), opt->rect.y() + opt->rect.height() / 2);
2405                     p2 = QPoint(opt->rect.x() + opt->rect.width(), p1.y());
2406                 } else {
2407                     p1 = QPoint(opt->rect.x() + opt->rect.width() / 2, opt->rect.y());
2408                     p2 = QPoint(p1.x(), p1.y() + opt->rect.height());
2409                 }
2410                 if (frameShadow == QFrame::Plain) {
2411                     QPen oldPen = p->pen();
2412                     p->setPen(QPen(opt->palette.brush(foregroundRole), lw));
2413                     p->drawLine(p1, p2);
2414                     p->setPen(oldPen);
2415                 } else {
2416                     qDrawShadeLine(p, p1, p2, f->palette, frameShadow == QFrame::Sunken, lw, mlw);
2417                 }
2418                 break;
2419                 }
2420             }
2421         }
2422         break;
2423 #endif
2424     default:
2425         break;
2426     }
2427 #if !QT_CONFIG(tabbar) && !QT_CONFIG(itemviews)
2428     Q_UNUSED(d);
2429 #endif
2430 }
2431 
2432 /*!
2433   \reimp
2434 */
subElementRect(SubElement sr,const QStyleOption * opt,const QWidget * widget) const2435 QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
2436                                    const QWidget *widget) const
2437 {
2438     Q_D(const QCommonStyle);
2439     QRect r;
2440     switch (sr) {
2441     case SE_PushButtonContents:
2442         if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
2443             int dx1, dx2;
2444             dx1 = proxy()->pixelMetric(PM_DefaultFrameWidth, btn, widget);
2445             if (btn->features & QStyleOptionButton::AutoDefaultButton)
2446                 dx1 += proxy()->pixelMetric(PM_ButtonDefaultIndicator, btn, widget);
2447             dx2 = dx1 * 2;
2448             r.setRect(opt->rect.x() + dx1, opt->rect.y() + dx1, opt->rect.width() - dx2,
2449                       opt->rect.height() - dx2);
2450             r = visualRect(opt->direction, opt->rect, r);
2451         }
2452         break;
2453     case SE_PushButtonFocusRect:
2454         if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
2455             int dbw1 = 0, dbw2 = 0;
2456             if (btn->features & QStyleOptionButton::AutoDefaultButton){
2457                 dbw1 = proxy()->pixelMetric(PM_ButtonDefaultIndicator, btn, widget);
2458                 dbw2 = dbw1 * 2;
2459             }
2460 
2461             int dfw1 = proxy()->pixelMetric(PM_DefaultFrameWidth, btn, widget) + 1,
2462                 dfw2 = dfw1 * 2;
2463 
2464             r.setRect(btn->rect.x() + dfw1 + dbw1, btn->rect.y() + dfw1 + dbw1,
2465                       btn->rect.width() - dfw2 - dbw2, btn->rect.height()- dfw2 - dbw2);
2466             r = visualRect(opt->direction, opt->rect, r);
2467         }
2468         break;
2469     case SE_PushButtonBevel:
2470         {
2471             r = opt->rect;
2472             r = visualRect(opt->direction, opt->rect, r);
2473         }
2474         break;
2475     case SE_CheckBoxIndicator:
2476         {
2477             int h = proxy()->pixelMetric(PM_IndicatorHeight, opt, widget);
2478             r.setRect(opt->rect.x(), opt->rect.y() + ((opt->rect.height() - h) / 2),
2479                       proxy()->pixelMetric(PM_IndicatorWidth, opt, widget), h);
2480             r = visualRect(opt->direction, opt->rect, r);
2481         }
2482         break;
2483 
2484     case SE_CheckBoxContents:
2485         {
2486             // Deal with the logical first, then convert it back to screen coords.
2487             QRect ir = visualRect(opt->direction, opt->rect,
2488                                   subElementRect(SE_CheckBoxIndicator, opt, widget));
2489             int spacing = proxy()->pixelMetric(PM_CheckBoxLabelSpacing, opt, widget);
2490             r.setRect(ir.right() + spacing, opt->rect.y(), opt->rect.width() - ir.width() - spacing,
2491                       opt->rect.height());
2492             r = visualRect(opt->direction, opt->rect, r);
2493         }
2494         break;
2495 
2496     case SE_CheckBoxFocusRect:
2497         if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
2498             if (btn->icon.isNull() && btn->text.isEmpty()) {
2499                 r = subElementRect(SE_CheckBoxIndicator, opt, widget);
2500                 r.adjust(1, 1, -1, -1);
2501                 break;
2502             }
2503             // As above, deal with the logical first, then convert it back to screen coords.
2504             QRect cr = visualRect(btn->direction, btn->rect,
2505                                   subElementRect(SE_CheckBoxContents, btn, widget));
2506 
2507             QRect iconRect, textRect;
2508             if (!btn->text.isEmpty()) {
2509                 textRect = itemTextRect(opt->fontMetrics, cr, Qt::AlignAbsolute | Qt::AlignLeft
2510                                         | Qt::AlignVCenter | Qt::TextShowMnemonic,
2511                                         btn->state & State_Enabled, btn->text);
2512             }
2513             if (!btn->icon.isNull()) {
2514                 iconRect = itemPixmapRect(cr, Qt::AlignAbsolute | Qt::AlignLeft | Qt::AlignVCenter
2515                                         | Qt::TextShowMnemonic,
2516                                    btn->icon.pixmap(qt_getWindow(widget), btn->iconSize, QIcon::Normal));
2517                 if (!textRect.isEmpty())
2518                     textRect.translate(iconRect.right() + 4, 0);
2519             }
2520             r = iconRect | textRect;
2521             r.adjust(-3, -2, 3, 2);
2522             r = r.intersected(btn->rect);
2523             r = visualRect(btn->direction, btn->rect, r);
2524         }
2525         break;
2526 
2527     case SE_RadioButtonIndicator:
2528         {
2529             int h = proxy()->pixelMetric(PM_ExclusiveIndicatorHeight, opt, widget);
2530             r.setRect(opt->rect.x(), opt->rect.y() + ((opt->rect.height() - h) / 2),
2531                     proxy()->pixelMetric(PM_ExclusiveIndicatorWidth, opt, widget), h);
2532             r = visualRect(opt->direction, opt->rect, r);
2533         }
2534         break;
2535 
2536     case SE_RadioButtonContents:
2537         {
2538             QRect ir = visualRect(opt->direction, opt->rect,
2539                                   subElementRect(SE_RadioButtonIndicator, opt, widget));
2540             int spacing = proxy()->pixelMetric(PM_RadioButtonLabelSpacing, opt, widget);
2541             r.setRect(ir.left() + ir.width() + spacing, opt->rect.y(), opt->rect.width() - ir.width() - spacing,
2542                       opt->rect.height());
2543             r = visualRect(opt->direction, opt->rect, r);
2544             break;
2545         }
2546 
2547     case SE_RadioButtonFocusRect:
2548         if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
2549             if (btn->icon.isNull() && btn->text.isEmpty()) {
2550                 r = subElementRect(SE_RadioButtonIndicator, opt, widget);
2551                 r.adjust(1, 1, -1, -1);
2552                 break;
2553             }
2554             QRect cr = visualRect(btn->direction, btn->rect,
2555                                   subElementRect(SE_RadioButtonContents, opt, widget));
2556 
2557             QRect iconRect, textRect;
2558             if (!btn->text.isEmpty()){
2559                 textRect = itemTextRect(opt->fontMetrics, cr, Qt::AlignAbsolute | Qt::AlignLeft | Qt::AlignVCenter
2560                                  | Qt::TextShowMnemonic, btn->state & State_Enabled, btn->text);
2561             }
2562             if (!btn->icon.isNull()) {
2563                 iconRect = itemPixmapRect(cr, Qt::AlignAbsolute | Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic,
2564                                    btn->icon.pixmap(qt_getWindow(widget), btn->iconSize, QIcon::Normal));
2565                 if (!textRect.isEmpty())
2566                     textRect.translate(iconRect.right() + 4, 0);
2567             }
2568             r = iconRect | textRect;
2569             r.adjust(-3, -2, 3, 2);
2570             r = r.intersected(btn->rect);
2571             r = visualRect(btn->direction, btn->rect, r);
2572         }
2573         break;
2574 #if QT_CONFIG(slider)
2575     case SE_SliderFocusRect:
2576         if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
2577             int tickOffset = proxy()->pixelMetric(PM_SliderTickmarkOffset, slider, widget);
2578             int thickness  = proxy()->pixelMetric(PM_SliderControlThickness, slider, widget);
2579             if (slider->orientation == Qt::Horizontal)
2580                 r.setRect(0, tickOffset - 1, slider->rect.width(), thickness + 2);
2581             else
2582                 r.setRect(tickOffset - 1, 0, thickness + 2, slider->rect.height());
2583             r = r.intersected(slider->rect);
2584             r = visualRect(opt->direction, opt->rect, r);
2585         }
2586         break;
2587 #endif // QT_CONFIG(slider)
2588 #if QT_CONFIG(progressbar)
2589     case SE_ProgressBarGroove:
2590     case SE_ProgressBarContents:
2591     case SE_ProgressBarLabel:
2592         if (const QStyleOptionProgressBar *pb = qstyleoption_cast<const QStyleOptionProgressBar *>(opt)) {
2593             int textw = 0;
2594             const bool vertical = pb->orientation == Qt::Vertical;
2595             if (!vertical) {
2596                 if (pb->textVisible)
2597                     textw = qMax(pb->fontMetrics.horizontalAdvance(pb->text), pb->fontMetrics.horizontalAdvance(QLatin1String("100%"))) + 6;
2598             }
2599 
2600             if ((pb->textAlignment & Qt::AlignCenter) == 0) {
2601                 if (sr != SE_ProgressBarLabel)
2602                     r.setCoords(pb->rect.left(), pb->rect.top(),
2603                                 pb->rect.right() - textw, pb->rect.bottom());
2604                 else
2605                     r.setCoords(pb->rect.right() - textw, pb->rect.top(),
2606                                 pb->rect.right(), pb->rect.bottom());
2607             } else {
2608                 r = pb->rect;
2609             }
2610             r = visualRect(pb->direction, pb->rect, r);
2611         }
2612         break;
2613 #endif // QT_CONFIG(progressbar)
2614 #if QT_CONFIG(combobox)
2615     case SE_ComboBoxFocusRect:
2616         if (const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(opt)) {
2617             int margin = cb->frame ? 3 : 0;
2618             r.setRect(opt->rect.left() + margin, opt->rect.top() + margin,
2619                       opt->rect.width() - 2*margin - 16, opt->rect.height() - 2*margin);
2620             r = visualRect(opt->direction, opt->rect, r);
2621         }
2622         break;
2623 #endif // QT_CONFIG(combobox)
2624 #if QT_CONFIG(toolbox)
2625     case SE_ToolBoxTabContents:
2626         r = opt->rect;
2627         r.adjust(0, 0, -30, 0);
2628         break;
2629 #endif // QT_CONFIG(toolbox)
2630     case SE_HeaderLabel: {
2631         int margin = proxy()->pixelMetric(QStyle::PM_HeaderMargin, opt, widget);
2632         r.setRect(opt->rect.x() + margin, opt->rect.y() + margin,
2633                   opt->rect.width() - margin * 2, opt->rect.height() - margin * 2);
2634 
2635         if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(opt)) {
2636             // Subtract width needed for arrow, if there is one
2637             if (header->sortIndicator != QStyleOptionHeader::None) {
2638                 if (opt->state & State_Horizontal)
2639                     r.setWidth(r.width() - (opt->rect.height() / 2) - (margin * 2));
2640                 else
2641                     r.setHeight(r.height() - (opt->rect.width() / 2) - (margin * 2));
2642             }
2643         }
2644         r = visualRect(opt->direction, opt->rect, r);
2645         break; }
2646     case SE_HeaderArrow: {
2647         int h = opt->rect.height();
2648         int w = opt->rect.width();
2649         int x = opt->rect.x();
2650         int y = opt->rect.y();
2651         int margin = proxy()->pixelMetric(QStyle::PM_HeaderMargin, opt, widget);
2652 
2653         if (opt->state & State_Horizontal) {
2654             int horiz_size = h / 2;
2655             r.setRect(x + w - margin * 2 - horiz_size, y + 5,
2656                       horiz_size, h - margin * 2 - 5);
2657         } else {
2658             int vert_size = w / 2;
2659             r.setRect(x + 5, y + h - margin * 2 - vert_size,
2660                       w - margin * 2 - 5, vert_size);
2661         }
2662         r = visualRect(opt->direction, opt->rect, r);
2663         break; }
2664 
2665     case SE_RadioButtonClickRect:
2666         r = subElementRect(SE_RadioButtonFocusRect, opt, widget);
2667         r |= subElementRect(SE_RadioButtonIndicator, opt, widget);
2668         break;
2669     case SE_CheckBoxClickRect:
2670         r = subElementRect(SE_CheckBoxFocusRect, opt, widget);
2671         r |= subElementRect(SE_CheckBoxIndicator, opt, widget);
2672         break;
2673 #if QT_CONFIG(tabwidget)
2674     case SE_TabWidgetTabBar:
2675         if (const QStyleOptionTabWidgetFrame *twf
2676                 = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(opt)) {
2677             r.setSize(twf->tabBarSize);
2678             const uint alingMask = Qt::AlignLeft | Qt::AlignRight | Qt::AlignHCenter;
2679             switch (twf->shape) {
2680             case QTabBar::RoundedNorth:
2681             case QTabBar::TriangularNorth:
2682                 // Constrain the size now, otherwise, center could get off the page
2683                 // This of course repeated for all the other directions
2684                 r.setWidth(qMin(r.width(), twf->rect.width()
2685                                             - twf->leftCornerWidgetSize.width()
2686                                             - twf->rightCornerWidgetSize.width()));
2687                 switch (proxy()->styleHint(SH_TabBar_Alignment, twf, widget) & alingMask) {
2688                 default:
2689                 case Qt::AlignLeft:
2690                     r.moveTopLeft(QPoint(twf->leftCornerWidgetSize.width(), 0));
2691                     break;
2692                 case Qt::AlignHCenter:
2693                     r.moveTopLeft(QPoint(twf->rect.center().x() - qRound(r.width() / 2.0f)
2694                                          + (twf->leftCornerWidgetSize.width() / 2)
2695                                          - (twf->rightCornerWidgetSize.width() / 2), 0));
2696                     break;
2697                 case Qt::AlignRight:
2698                     r.moveTopLeft(QPoint(twf->rect.width() - twf->tabBarSize.width()
2699                                          - twf->rightCornerWidgetSize.width(), 0));
2700                     break;
2701                 }
2702                 r = visualRect(twf->direction, twf->rect, r);
2703                 break;
2704             case QTabBar::RoundedSouth:
2705             case QTabBar::TriangularSouth:
2706                 r.setWidth(qMin(r.width(), twf->rect.width()
2707                                             - twf->leftCornerWidgetSize.width()
2708                                             - twf->rightCornerWidgetSize.width()));
2709                 switch (proxy()->styleHint(SH_TabBar_Alignment, twf, widget) & alingMask) {
2710                 default:
2711                 case Qt::AlignLeft:
2712                     r.moveTopLeft(QPoint(twf->leftCornerWidgetSize.width(),
2713                                          twf->rect.height() - twf->tabBarSize.height()));
2714                     break;
2715                 case Qt::AlignHCenter:
2716                     r.moveTopLeft(QPoint(twf->rect.center().x() - qRound(r.width() / 2.0f)
2717                                          + (twf->leftCornerWidgetSize.width() / 2)
2718                                          - (twf->rightCornerWidgetSize.width() / 2),
2719                                          twf->rect.height() - twf->tabBarSize.height()));
2720                     break;
2721                 case Qt::AlignRight:
2722                     r.moveTopLeft(QPoint(twf->rect.width() - twf->tabBarSize.width()
2723                                          - twf->rightCornerWidgetSize.width(),
2724                                          twf->rect.height() - twf->tabBarSize.height()));
2725                     break;
2726                 }
2727                 r = visualRect(twf->direction, twf->rect, r);
2728                 break;
2729             case QTabBar::RoundedEast:
2730             case QTabBar::TriangularEast:
2731                 r.setHeight(qMin(r.height(), twf->rect.height()
2732                                             - twf->leftCornerWidgetSize.height()
2733                                             - twf->rightCornerWidgetSize.height()));
2734                 switch (proxy()->styleHint(SH_TabBar_Alignment, twf, widget) & alingMask) {
2735                 default:
2736                 case Qt::AlignLeft:
2737                     r.moveTopLeft(QPoint(twf->rect.width() - twf->tabBarSize.width(),
2738                                          twf->leftCornerWidgetSize.height()));
2739                     break;
2740                 case Qt::AlignHCenter:
2741                     r.moveTopLeft(QPoint(twf->rect.width() - twf->tabBarSize.width(),
2742                                          twf->rect.center().y() - r.height() / 2));
2743                     break;
2744                 case Qt::AlignRight:
2745                     r.moveTopLeft(QPoint(twf->rect.width() - twf->tabBarSize.width(),
2746                                          twf->rect.height() - twf->tabBarSize.height()
2747                                          - twf->rightCornerWidgetSize.height()));
2748                     break;
2749                 }
2750                 break;
2751             case QTabBar::RoundedWest:
2752             case QTabBar::TriangularWest:
2753                 r.setHeight(qMin(r.height(), twf->rect.height()
2754                                              - twf->leftCornerWidgetSize.height()
2755                                              - twf->rightCornerWidgetSize.height()));
2756                 switch (proxy()->styleHint(SH_TabBar_Alignment, twf, widget) & alingMask) {
2757                 default:
2758                 case Qt::AlignLeft:
2759                     r.moveTopLeft(QPoint(0, twf->leftCornerWidgetSize.height()));
2760                     break;
2761                 case Qt::AlignHCenter:
2762                     r.moveTopLeft(QPoint(0, twf->rect.center().y() - r.height() / 2));
2763                     break;
2764                 case Qt::AlignRight:
2765                     r.moveTopLeft(QPoint(0, twf->rect.height() - twf->tabBarSize.height()
2766                                          - twf->rightCornerWidgetSize.height()));
2767                     break;
2768                 }
2769                 break;
2770             }
2771         }
2772         break;
2773     case SE_TabWidgetTabPane:
2774     case SE_TabWidgetTabContents:
2775         if (const QStyleOptionTabWidgetFrame *twf = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(opt)) {
2776             QStyleOptionTab tabopt;
2777             tabopt.shape = twf->shape;
2778             int overlap = proxy()->pixelMetric(PM_TabBarBaseOverlap, &tabopt, widget);
2779             if (twf->lineWidth == 0)
2780                 overlap = 0;
2781             switch (twf->shape) {
2782             case QTabBar::RoundedNorth:
2783             case QTabBar::TriangularNorth:
2784                 r = QRect(QPoint(0,qMax(twf->tabBarSize.height() - overlap, 0)),
2785                           QSize(twf->rect.width(), qMin(twf->rect.height() - twf->tabBarSize.height() + overlap, twf->rect.height())));
2786                 break;
2787             case QTabBar::RoundedSouth:
2788             case QTabBar::TriangularSouth:
2789                 r = QRect(QPoint(0,0), QSize(twf->rect.width(), qMin(twf->rect.height() - twf->tabBarSize.height() + overlap, twf->rect.height())));
2790                 break;
2791             case QTabBar::RoundedEast:
2792             case QTabBar::TriangularEast:
2793                 r = QRect(QPoint(0, 0), QSize(qMin(twf->rect.width() - twf->tabBarSize.width() + overlap, twf->rect.width()), twf->rect.height()));
2794                 break;
2795             case QTabBar::RoundedWest:
2796             case QTabBar::TriangularWest:
2797                 r = QRect(QPoint(qMax(twf->tabBarSize.width() - overlap, 0), 0),
2798                           QSize(qMin(twf->rect.width() - twf->tabBarSize.width() + overlap, twf->rect.width()), twf->rect.height()));
2799                 break;
2800             }
2801             if (sr == SE_TabWidgetTabContents && twf->lineWidth > 0)
2802                r.adjust(2, 2, -2, -2);
2803         }
2804         break;
2805     case SE_TabWidgetLeftCorner:
2806         if (const QStyleOptionTabWidgetFrame *twf = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(opt)) {
2807             QRect paneRect = subElementRect(SE_TabWidgetTabPane, twf, widget);
2808             switch (twf->shape) {
2809             case QTabBar::RoundedNorth:
2810             case QTabBar::TriangularNorth:
2811                 r = QRect(QPoint(paneRect.x(), paneRect.y() - twf->leftCornerWidgetSize.height()),
2812                           twf->leftCornerWidgetSize);
2813                 break;
2814             case QTabBar::RoundedSouth:
2815             case QTabBar::TriangularSouth:
2816                 r = QRect(QPoint(paneRect.x(), paneRect.height()), twf->leftCornerWidgetSize);
2817                break;
2818             default:
2819                break;
2820             }
2821            r = visualRect(twf->direction, twf->rect, r);
2822         }
2823         break;
2824    case SE_TabWidgetRightCorner:
2825        if (const QStyleOptionTabWidgetFrame *twf = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(opt)) {
2826            QRect paneRect = subElementRect(SE_TabWidgetTabPane, twf, widget);
2827            switch (twf->shape) {
2828            case QTabBar::RoundedNorth:
2829            case QTabBar::TriangularNorth:
2830                 r = QRect(QPoint(paneRect.width() - twf->rightCornerWidgetSize.width(),
2831                                  paneRect.y() - twf->rightCornerWidgetSize.height()),
2832                           twf->rightCornerWidgetSize);
2833                break;
2834            case QTabBar::RoundedSouth:
2835            case QTabBar::TriangularSouth:
2836                 r = QRect(QPoint(paneRect.width() - twf->rightCornerWidgetSize.width(),
2837                                  paneRect.height()), twf->rightCornerWidgetSize);
2838                break;
2839            default:
2840                break;
2841            }
2842            r = visualRect(twf->direction, twf->rect, r);
2843         }
2844         break;
2845     case SE_TabBarTabText:
2846         if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(opt)) {
2847             QRect dummyIconRect;
2848             d->tabLayout(tab, widget, &r, &dummyIconRect);
2849         }
2850         break;
2851     case SE_TabBarTabLeftButton:
2852     case SE_TabBarTabRightButton:
2853         if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(opt)) {
2854             bool selected = tab->state & State_Selected;
2855             int verticalShift = proxy()->pixelMetric(QStyle::PM_TabBarTabShiftVertical, tab, widget);
2856             int horizontalShift = proxy()->pixelMetric(QStyle::PM_TabBarTabShiftHorizontal, tab, widget);
2857             int hpadding = proxy()->pixelMetric(QStyle::PM_TabBarTabHSpace, opt, widget) / 2;
2858             hpadding = qMax(hpadding, 4); //workaround KStyle returning 0 because they workaround an old bug in Qt
2859 
2860             bool verticalTabs = tab->shape == QTabBar::RoundedEast
2861                     || tab->shape == QTabBar::RoundedWest
2862                     || tab->shape == QTabBar::TriangularEast
2863                     || tab->shape == QTabBar::TriangularWest;
2864 
2865             QRect tr = tab->rect;
2866             if (tab->shape == QTabBar::RoundedSouth || tab->shape == QTabBar::TriangularSouth)
2867                 verticalShift = -verticalShift;
2868             if (verticalTabs) {
2869                 qSwap(horizontalShift, verticalShift);
2870                 horizontalShift *= -1;
2871                 verticalShift *= -1;
2872             }
2873             if (tab->shape == QTabBar::RoundedWest || tab->shape == QTabBar::TriangularWest)
2874                 horizontalShift = -horizontalShift;
2875 
2876             tr.adjust(0, 0, horizontalShift, verticalShift);
2877             if (selected)
2878             {
2879                 tr.setBottom(tr.bottom() - verticalShift);
2880                 tr.setRight(tr.right() - horizontalShift);
2881             }
2882 
2883             QSize size = (sr == SE_TabBarTabLeftButton) ? tab->leftButtonSize : tab->rightButtonSize;
2884             int w = size.width();
2885             int h = size.height();
2886             int midHeight = static_cast<int>(qCeil(float(tr.height() - h) / 2));
2887             int midWidth = ((tr.width() - w) / 2);
2888 
2889             bool atTheTop = true;
2890             switch (tab->shape) {
2891             case QTabBar::RoundedWest:
2892             case QTabBar::TriangularWest:
2893                 atTheTop = (sr == SE_TabBarTabLeftButton);
2894                 break;
2895             case QTabBar::RoundedEast:
2896             case QTabBar::TriangularEast:
2897                 atTheTop = (sr == SE_TabBarTabRightButton);
2898                 break;
2899             default:
2900                 if (sr == SE_TabBarTabLeftButton)
2901                     r = QRect(tab->rect.x() + hpadding, midHeight, w, h);
2902                 else
2903                     r = QRect(tab->rect.right() - w - hpadding, midHeight, w, h);
2904                 r = visualRect(tab->direction, tab->rect, r);
2905             }
2906             if (verticalTabs) {
2907                 if (atTheTop)
2908                     r = QRect(midWidth, tr.y() + tab->rect.height() - hpadding - h, w, h);
2909                 else
2910                     r = QRect(midWidth, tr.y() + hpadding, w, h);
2911             }
2912         }
2913 
2914         break;
2915 #endif // QT_CONFIG(tabwidget)
2916 #if QT_CONFIG(tabbar)
2917     case SE_TabBarTearIndicator:
2918         if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(opt)) {
2919             switch (tab->shape) {
2920             case QTabBar::RoundedNorth:
2921             case QTabBar::TriangularNorth:
2922             case QTabBar::RoundedSouth:
2923             case QTabBar::TriangularSouth:
2924                 r.setRect(tab->rect.left(), tab->rect.top(), 8, opt->rect.height());
2925                 break;
2926             case QTabBar::RoundedWest:
2927             case QTabBar::TriangularWest:
2928             case QTabBar::RoundedEast:
2929             case QTabBar::TriangularEast:
2930                 r.setRect(tab->rect.left(), tab->rect.top(), opt->rect.width(), 8);
2931                 break;
2932             default:
2933                 break;
2934             }
2935             r = visualRect(opt->direction, opt->rect, r);
2936         }
2937         break;
2938     case SE_TabBarScrollLeftButton: {
2939         const bool vertical = opt->rect.width() < opt->rect.height();
2940         const Qt::LayoutDirection ld = widget->layoutDirection();
2941         const int buttonWidth = qMax(proxy()->pixelMetric(QStyle::PM_TabBarScrollButtonWidth, nullptr, widget), QApplication::globalStrut().width());
2942         const int buttonOverlap = proxy()->pixelMetric(QStyle::PM_TabBar_ScrollButtonOverlap, nullptr, widget);
2943 
2944         r = vertical ? QRect(0, opt->rect.height() - (buttonWidth * 2) + buttonOverlap, opt->rect.width(), buttonWidth)
2945             : QStyle::visualRect(ld, opt->rect, QRect(opt->rect.width() - (buttonWidth * 2) + buttonOverlap, 0, buttonWidth, opt->rect.height()));
2946         break; }
2947     case SE_TabBarScrollRightButton: {
2948         const bool vertical = opt->rect.width() < opt->rect.height();
2949         const Qt::LayoutDirection ld = widget->layoutDirection();
2950         const int buttonWidth = qMax(proxy()->pixelMetric(QStyle::PM_TabBarScrollButtonWidth, nullptr, widget), QApplication::globalStrut().width());
2951 
2952         r = vertical ? QRect(0, opt->rect.height() - buttonWidth, opt->rect.width(), buttonWidth)
2953             : QStyle::visualRect(ld, opt->rect, QRect(opt->rect.width() - buttonWidth, 0, buttonWidth, opt->rect.height()));
2954         break; }
2955 #endif
2956     case SE_TreeViewDisclosureItem:
2957         r = opt->rect;
2958         break;
2959     case SE_LineEditContents:
2960         if (const QStyleOptionFrame *f = qstyleoption_cast<const QStyleOptionFrame *>(opt)) {
2961             r = f->rect.adjusted(f->lineWidth, f->lineWidth, -f->lineWidth, -f->lineWidth);
2962             r = visualRect(opt->direction, opt->rect, r);
2963         }
2964         break;
2965     case SE_FrameContents:
2966         if (const QStyleOptionFrame *f = qstyleoption_cast<const QStyleOptionFrame *>(opt)) {
2967             int fw = proxy()->pixelMetric(PM_DefaultFrameWidth, f, widget);
2968             r = opt->rect.adjusted(fw, fw, -fw, -fw);
2969             r = visualRect(opt->direction, opt->rect, r);
2970         }
2971         break;
2972     case SE_ShapedFrameContents:
2973         if (const QStyleOptionFrame *f = qstyleoption_cast<const QStyleOptionFrame *>(opt)) {
2974             int frameShape  = f->frameShape;
2975             int frameShadow = QFrame::Plain;
2976             if (f->state & QStyle::State_Sunken) {
2977                 frameShadow = QFrame::Sunken;
2978             } else if (f->state & QStyle::State_Raised) {
2979                 frameShadow = QFrame::Raised;
2980             }
2981 
2982             int frameWidth = 0;
2983 
2984             switch (frameShape) {
2985             case QFrame::NoFrame:
2986                 frameWidth = 0;
2987                 break;
2988 
2989             case QFrame::Box:
2990             case QFrame::HLine:
2991             case QFrame::VLine:
2992                 switch (frameShadow) {
2993                 case QFrame::Plain:
2994                     frameWidth = f->lineWidth;
2995                     break;
2996                 case QFrame::Raised:
2997                 case QFrame::Sunken:
2998                     frameWidth = (short)(f->lineWidth*2 + f->midLineWidth);
2999                     break;
3000                 }
3001                 break;
3002 
3003             case QFrame::StyledPanel:
3004                 //keep the compatibility with Qt 4.4 if there is a proxy style.
3005                 //be sure to call drawPrimitive(QStyle::SE_FrameContents) on the proxy style
3006                 if (widget)
3007                     return widget->style()->subElementRect(QStyle::SE_FrameContents, opt, widget);
3008                 else
3009                     return subElementRect(QStyle::SE_FrameContents, opt, widget);
3010 
3011             case QFrame::WinPanel:
3012                 frameWidth = 2;
3013                 break;
3014 
3015             case QFrame::Panel:
3016                 switch (frameShadow) {
3017                 case QFrame::Plain:
3018                 case QFrame::Raised:
3019                 case QFrame::Sunken:
3020                     frameWidth = f->lineWidth;
3021                     break;
3022                 }
3023                 break;
3024             }
3025             r = f->rect.adjusted(frameWidth, frameWidth, -frameWidth, -frameWidth);
3026         }
3027         break;
3028 #if QT_CONFIG(dockwidget)
3029     case SE_DockWidgetCloseButton:
3030     case SE_DockWidgetFloatButton:
3031     case SE_DockWidgetTitleBarText:
3032     case SE_DockWidgetIcon: {
3033         int iconSize = proxy()->pixelMetric(PM_SmallIconSize, opt, widget);
3034         int buttonMargin = proxy()->pixelMetric(PM_DockWidgetTitleBarButtonMargin, opt, widget);
3035         int margin = proxy()->pixelMetric(QStyle::PM_DockWidgetTitleMargin, opt, widget);
3036         QRect rect = opt->rect;
3037 
3038         const QStyleOptionDockWidget *dwOpt
3039             = qstyleoption_cast<const QStyleOptionDockWidget*>(opt);
3040         bool canClose = dwOpt == nullptr ? true : dwOpt->closable;
3041         bool canFloat = dwOpt == nullptr ? false : dwOpt->floatable;
3042 
3043         const bool verticalTitleBar = dwOpt && dwOpt->verticalTitleBar;
3044 
3045         // If this is a vertical titlebar, we transpose and work as if it was
3046         // horizontal, then transpose again.
3047 
3048         if (verticalTitleBar)
3049             rect = rect.transposed();
3050 
3051         do {
3052 
3053             int right = rect.right();
3054             int left = rect.left();
3055 
3056             QRect closeRect;
3057             if (canClose) {
3058                 QSize sz = proxy()->standardIcon(QStyle::SP_TitleBarCloseButton,
3059                                         opt, widget).actualSize(QSize(iconSize, iconSize));
3060                 sz += QSize(buttonMargin, buttonMargin);
3061                 if (verticalTitleBar)
3062                     sz = sz.transposed();
3063                 closeRect = QRect(right - sz.width(),
3064                                     rect.center().y() - sz.height()/2,
3065                                     sz.width(), sz.height());
3066                 right = closeRect.left() - 1;
3067             }
3068             if (sr == SE_DockWidgetCloseButton) {
3069                 r = closeRect;
3070                 break;
3071             }
3072 
3073             QRect floatRect;
3074             if (canFloat) {
3075                 QSize sz = proxy()->standardIcon(QStyle::SP_TitleBarNormalButton,
3076                                         opt, widget).actualSize(QSize(iconSize, iconSize));
3077                 sz += QSize(buttonMargin, buttonMargin);
3078                 if (verticalTitleBar)
3079                     sz = sz.transposed();
3080                 floatRect = QRect(right - sz.width(),
3081                                     rect.center().y() - sz.height()/2,
3082                                     sz.width(), sz.height());
3083                 right = floatRect.left() - 1;
3084             }
3085             if (sr == SE_DockWidgetFloatButton) {
3086                 r = floatRect;
3087                 break;
3088             }
3089 
3090             QRect iconRect;
3091             if (const QDockWidget *dw = qobject_cast<const QDockWidget*>(widget)) {
3092                 QIcon icon;
3093                 if (dw->isFloating())
3094                     icon = dw->windowIcon();
3095                 if (!icon.isNull()
3096                         && icon.cacheKey() != QApplication::windowIcon().cacheKey()) {
3097                     QSize sz = icon.actualSize(QSize(r.height(), r.height()));
3098                     if (verticalTitleBar)
3099                         sz = sz.transposed();
3100                     iconRect = QRect(left, rect.center().y() - sz.height()/2,
3101                                         sz.width(), sz.height());
3102                     left = iconRect.right() + margin;
3103                 }
3104             }
3105             if (sr == SE_DockWidgetIcon) {
3106                 r = iconRect;
3107                 break;
3108             }
3109 
3110             QRect textRect = QRect(left, rect.top(),
3111                                     right - left, rect.height());
3112             if (sr == SE_DockWidgetTitleBarText) {
3113                 r = textRect;
3114                 break;
3115             }
3116 
3117         } while (false);
3118 
3119         if (verticalTitleBar) {
3120             r = QRect(rect.left() + r.top() - rect.top(),
3121                         rect.top() + rect.right() - r.right(),
3122                         r.height(), r.width());
3123         } else {
3124             r = visualRect(opt->direction, rect, r);
3125         }
3126         break;
3127     }
3128 #endif
3129 #if QT_CONFIG(itemviews)
3130     case SE_ItemViewItemCheckIndicator:
3131         if (!qstyleoption_cast<const QStyleOptionViewItem *>(opt)) {
3132             r = subElementRect(SE_CheckBoxIndicator, opt, widget);
3133             break;
3134         }
3135         Q_FALLTHROUGH();
3136     case SE_ItemViewItemDecoration:
3137     case SE_ItemViewItemText:
3138     case SE_ItemViewItemFocusRect:
3139         if (const QStyleOptionViewItem *vopt = qstyleoption_cast<const QStyleOptionViewItem *>(opt)) {
3140             if (!d->isViewItemCached(*vopt)) {
3141                 d->viewItemLayout(vopt, &d->checkRect, &d->decorationRect, &d->displayRect, false);
3142                 if (d->cachedOption) {
3143                     delete d->cachedOption;
3144                     d->cachedOption = nullptr;
3145                 }
3146                 d->cachedOption = new QStyleOptionViewItem(*vopt);
3147             }
3148             if (sr == SE_ItemViewItemCheckIndicator)
3149                 r = d->checkRect;
3150             else if (sr == SE_ItemViewItemDecoration)
3151                 r = d->decorationRect;
3152             else if (sr == SE_ItemViewItemText || sr == SE_ItemViewItemFocusRect)
3153                 r = d->displayRect;
3154                                }
3155         break;
3156 #endif // QT_CONFIG(itemviews)
3157 #if QT_CONFIG(toolbar)
3158     case SE_ToolBarHandle:
3159         if (const QStyleOptionToolBar *tbopt = qstyleoption_cast<const QStyleOptionToolBar *>(opt)) {
3160             if (tbopt->features & QStyleOptionToolBar::Movable) {
3161                 ///we need to access the widget here because the style option doesn't
3162                 //have all the information we need (ie. the layout's margin)
3163                 const QToolBar *tb = qobject_cast<const QToolBar*>(widget);
3164                 const QMargins margins = tb && tb->layout() ? tb->layout()->contentsMargins() : QMargins(2, 2, 2, 2);
3165                 const int handleExtent = proxy()->pixelMetric(QStyle::PM_ToolBarHandleExtent, opt, tb);
3166                 if (tbopt->state & QStyle::State_Horizontal) {
3167                     r = QRect(margins.left(), margins.top(),
3168                               handleExtent,
3169                               tbopt->rect.height() - (margins.top() + margins.bottom()));
3170                     r = QStyle::visualRect(tbopt->direction, tbopt->rect, r);
3171                 } else {
3172                     r = QRect(margins.left(), margins.top(),
3173                               tbopt->rect.width() - (margins.left() + margins.right()),
3174                               handleExtent);
3175                 }
3176             }
3177         }
3178         break;
3179 #endif // QT_CONFIG(toolbar)
3180     default:
3181         break;
3182     }
3183     return r;
3184 #if !QT_CONFIG(tabwidget) && !QT_CONFIG(itemviews)
3185     Q_UNUSED(d);
3186 #endif
3187 }
3188 
3189 #if QT_CONFIG(dial)
3190 
3191 // in lieu of std::array, minimal API
3192 template <int N>
3193 struct StaticPolygonF
3194 {
3195     QPointF data[N];
3196 
sizeStaticPolygonF3197     Q_DECL_CONSTEXPR int size() const { return N; }
cbeginStaticPolygonF3198     Q_DECL_CONSTEXPR const QPointF *cbegin() const { return data; }
operator []StaticPolygonF3199     Q_DECL_CONSTEXPR const QPointF &operator[](int idx) const { return data[idx]; }
3200 };
3201 
calcArrow(const QStyleOptionSlider * dial,qreal & a)3202 static StaticPolygonF<3> calcArrow(const QStyleOptionSlider *dial, qreal &a)
3203 {
3204     int width = dial->rect.width();
3205     int height = dial->rect.height();
3206     int r = qMin(width, height) / 2;
3207     int currentSliderPosition = dial->upsideDown ? dial->sliderPosition : (dial->maximum - dial->sliderPosition);
3208 
3209     if (dial->maximum == dial->minimum)
3210         a = Q_PI / 2;
3211     else if (dial->dialWrapping)
3212         a = Q_PI * 3 / 2 - (currentSliderPosition - dial->minimum) * 2 * Q_PI
3213             / (dial->maximum - dial->minimum);
3214     else
3215         a = (Q_PI * 8 - (currentSliderPosition - dial->minimum) * 10 * Q_PI
3216             / (dial->maximum - dial->minimum)) / 6;
3217 
3218     int xc = width / 2;
3219     int yc = height / 2;
3220 
3221     int len = r - QStyleHelper::calcBigLineSize(r) - 5;
3222     if (len < 5)
3223         len = 5;
3224     int back = len / 2;
3225 
3226     StaticPolygonF<3> arrow = {{
3227         QPointF(0.5 + xc + len * qCos(a),
3228                 0.5 + yc - len * qSin(a)),
3229         QPointF(0.5 + xc + back * qCos(a + Q_PI * 5 / 6),
3230                 0.5 + yc - back * qSin(a + Q_PI * 5 / 6)),
3231         QPointF(0.5 + xc + back * qCos(a - Q_PI * 5 / 6),
3232                 0.5 + yc - back * qSin(a - Q_PI * 5 / 6)),
3233     }};
3234     return arrow;
3235 }
3236 
3237 #endif // QT_CONFIG(dial)
3238 
3239 /*!
3240   \reimp
3241 */
drawComplexControl(ComplexControl cc,const QStyleOptionComplex * opt,QPainter * p,const QWidget * widget) const3242 void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex *opt,
3243                                       QPainter *p, const QWidget *widget) const
3244 {
3245     switch (cc) {
3246 #if QT_CONFIG(slider)
3247     case CC_Slider:
3248         if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
3249             if (slider->subControls == SC_SliderTickmarks) {
3250                 int tickOffset = proxy()->pixelMetric(PM_SliderTickmarkOffset, slider, widget);
3251                 int ticks = slider->tickPosition;
3252                 int thickness = proxy()->pixelMetric(PM_SliderControlThickness, slider, widget);
3253                 int len = proxy()->pixelMetric(PM_SliderLength, slider, widget);
3254                 int available = proxy()->pixelMetric(PM_SliderSpaceAvailable, slider, widget);
3255                 int interval = slider->tickInterval;
3256                 if (interval <= 0) {
3257                     interval = slider->singleStep;
3258                     if (QStyle::sliderPositionFromValue(slider->minimum, slider->maximum, interval,
3259                                                         available)
3260                         - QStyle::sliderPositionFromValue(slider->minimum, slider->maximum,
3261                                                           0, available) < 3)
3262                         interval = slider->pageStep;
3263                 }
3264                 if (!interval)
3265                     interval = 1;
3266                 int fudge = len / 2;
3267                 int pos;
3268                 // Since there is no subrect for tickmarks do a translation here.
3269                 p->save();
3270                 p->translate(slider->rect.x(), slider->rect.y());
3271                 p->setPen(slider->palette.windowText().color());
3272                 int v = slider->minimum;
3273                 while (v <= slider->maximum + 1) {
3274                     if (v == slider->maximum + 1 && interval == 1)
3275                         break;
3276                     const int v_ = qMin(v, slider->maximum);
3277                     pos = QStyle::sliderPositionFromValue(slider->minimum, slider->maximum,
3278                                                           v_, available) + fudge;
3279                     if (slider->orientation == Qt::Horizontal) {
3280                         if (ticks & QSlider::TicksAbove)
3281                             p->drawLine(pos, 0, pos, tickOffset - 2);
3282                         if (ticks & QSlider::TicksBelow)
3283                             p->drawLine(pos, tickOffset + thickness + 1, pos,
3284                                         slider->rect.height()-1);
3285                     } else {
3286                         if (ticks & QSlider::TicksAbove)
3287                             p->drawLine(0, pos, tickOffset - 2, pos);
3288                         if (ticks & QSlider::TicksBelow)
3289                             p->drawLine(tickOffset + thickness + 1, pos,
3290                                         slider->rect.width()-1, pos);
3291                     }
3292                     // in the case where maximum is max int
3293                     int nextInterval = v + interval;
3294                     if (nextInterval < v)
3295                         break;
3296                     v = nextInterval;
3297                 }
3298                 p->restore();
3299             }
3300         }
3301         break;
3302 #endif // QT_CONFIG(slider)
3303 #if QT_CONFIG(scrollbar)
3304     case CC_ScrollBar:
3305         if (const QStyleOptionSlider *scrollbar = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
3306             // Make a copy here and reset it for each primitive.
3307             QStyleOptionSlider newScrollbar = *scrollbar;
3308             State saveFlags = scrollbar->state;
3309 
3310             if (scrollbar->subControls & SC_ScrollBarSubLine) {
3311                 newScrollbar.state = saveFlags;
3312                 newScrollbar.rect = proxy()->subControlRect(cc, &newScrollbar, SC_ScrollBarSubLine, widget);
3313                 if (newScrollbar.rect.isValid()) {
3314                     if (!(scrollbar->activeSubControls & SC_ScrollBarSubLine))
3315                         newScrollbar.state &= ~(State_Sunken | State_MouseOver);
3316                     proxy()->drawControl(CE_ScrollBarSubLine, &newScrollbar, p, widget);
3317                 }
3318             }
3319             if (scrollbar->subControls & SC_ScrollBarAddLine) {
3320                 newScrollbar.rect = scrollbar->rect;
3321                 newScrollbar.state = saveFlags;
3322                 newScrollbar.rect = proxy()->subControlRect(cc, &newScrollbar, SC_ScrollBarAddLine, widget);
3323                 if (newScrollbar.rect.isValid()) {
3324                     if (!(scrollbar->activeSubControls & SC_ScrollBarAddLine))
3325                         newScrollbar.state &= ~(State_Sunken | State_MouseOver);
3326                     proxy()->drawControl(CE_ScrollBarAddLine, &newScrollbar, p, widget);
3327                 }
3328             }
3329             if (scrollbar->subControls & SC_ScrollBarSubPage) {
3330                 newScrollbar.rect = scrollbar->rect;
3331                 newScrollbar.state = saveFlags;
3332                 newScrollbar.rect = proxy()->subControlRect(cc, &newScrollbar, SC_ScrollBarSubPage, widget);
3333                 if (newScrollbar.rect.isValid()) {
3334                     if (!(scrollbar->activeSubControls & SC_ScrollBarSubPage))
3335                         newScrollbar.state &= ~(State_Sunken | State_MouseOver);
3336                     proxy()->drawControl(CE_ScrollBarSubPage, &newScrollbar, p, widget);
3337                 }
3338             }
3339             if (scrollbar->subControls & SC_ScrollBarAddPage) {
3340                 newScrollbar.rect = scrollbar->rect;
3341                 newScrollbar.state = saveFlags;
3342                 newScrollbar.rect = proxy()->subControlRect(cc, &newScrollbar, SC_ScrollBarAddPage, widget);
3343                 if (newScrollbar.rect.isValid()) {
3344                     if (!(scrollbar->activeSubControls & SC_ScrollBarAddPage))
3345                         newScrollbar.state &= ~(State_Sunken | State_MouseOver);
3346                     proxy()->drawControl(CE_ScrollBarAddPage, &newScrollbar, p, widget);
3347                 }
3348             }
3349             if (scrollbar->subControls & SC_ScrollBarFirst) {
3350                 newScrollbar.rect = scrollbar->rect;
3351                 newScrollbar.state = saveFlags;
3352                 newScrollbar.rect = proxy()->subControlRect(cc, &newScrollbar, SC_ScrollBarFirst, widget);
3353                 if (newScrollbar.rect.isValid()) {
3354                     if (!(scrollbar->activeSubControls & SC_ScrollBarFirst))
3355                         newScrollbar.state &= ~(State_Sunken | State_MouseOver);
3356                     proxy()->drawControl(CE_ScrollBarFirst, &newScrollbar, p, widget);
3357                 }
3358             }
3359             if (scrollbar->subControls & SC_ScrollBarLast) {
3360                 newScrollbar.rect = scrollbar->rect;
3361                 newScrollbar.state = saveFlags;
3362                 newScrollbar.rect = proxy()->subControlRect(cc, &newScrollbar, SC_ScrollBarLast, widget);
3363                 if (newScrollbar.rect.isValid()) {
3364                     if (!(scrollbar->activeSubControls & SC_ScrollBarLast))
3365                         newScrollbar.state &= ~(State_Sunken | State_MouseOver);
3366                     proxy()->drawControl(CE_ScrollBarLast, &newScrollbar, p, widget);
3367                 }
3368             }
3369             if (scrollbar->subControls & SC_ScrollBarSlider) {
3370                 newScrollbar.rect = scrollbar->rect;
3371                 newScrollbar.state = saveFlags;
3372                 newScrollbar.rect = proxy()->subControlRect(cc, &newScrollbar, SC_ScrollBarSlider, widget);
3373                 if (newScrollbar.rect.isValid()) {
3374                     if (!(scrollbar->activeSubControls & SC_ScrollBarSlider))
3375                         newScrollbar.state &= ~(State_Sunken | State_MouseOver);
3376                     proxy()->drawControl(CE_ScrollBarSlider, &newScrollbar, p, widget);
3377 
3378                     if (scrollbar->state & State_HasFocus) {
3379                         QStyleOptionFocusRect fropt;
3380                         fropt.QStyleOption::operator=(newScrollbar);
3381                         fropt.rect.setRect(newScrollbar.rect.x() + 2, newScrollbar.rect.y() + 2,
3382                                            newScrollbar.rect.width() - 5,
3383                                            newScrollbar.rect.height() - 5);
3384                         proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, p, widget);
3385                     }
3386                 }
3387             }
3388         }
3389         break;
3390 #endif // QT_CONFIG(scrollbar)
3391 #if QT_CONFIG(spinbox)
3392     case CC_SpinBox:
3393         if (const QStyleOptionSpinBox *sb = qstyleoption_cast<const QStyleOptionSpinBox *>(opt)) {
3394             QStyleOptionSpinBox copy = *sb;
3395             PrimitiveElement pe;
3396 
3397             if (sb->frame && (sb->subControls & SC_SpinBoxFrame)) {
3398                 QRect r = proxy()->subControlRect(CC_SpinBox, sb, SC_SpinBoxFrame, widget);
3399                 qDrawWinPanel(p, r, sb->palette, true);
3400             }
3401 
3402             if (sb->subControls & SC_SpinBoxUp) {
3403                 copy.subControls = SC_SpinBoxUp;
3404                 QPalette pal2 = sb->palette;
3405                 if (!(sb->stepEnabled & QAbstractSpinBox::StepUpEnabled)) {
3406                     pal2.setCurrentColorGroup(QPalette::Disabled);
3407                     copy.state &= ~State_Enabled;
3408                 }
3409 
3410                 copy.palette = pal2;
3411 
3412                 if (sb->activeSubControls == SC_SpinBoxUp && (sb->state & State_Sunken)) {
3413                     copy.state |= State_On;
3414                     copy.state |= State_Sunken;
3415                 } else {
3416                     copy.state |= State_Raised;
3417                     copy.state &= ~State_Sunken;
3418                 }
3419                 pe = (sb->buttonSymbols == QAbstractSpinBox::PlusMinus ? PE_IndicatorSpinPlus
3420                       : PE_IndicatorSpinUp);
3421 
3422                 copy.rect = proxy()->subControlRect(CC_SpinBox, sb, SC_SpinBoxUp, widget);
3423                 proxy()->drawPrimitive(PE_PanelButtonBevel, &copy, p, widget);
3424                 copy.rect.adjust(3, 0, -4, 0);
3425                 proxy()->drawPrimitive(pe, &copy, p, widget);
3426             }
3427 
3428             if (sb->subControls & SC_SpinBoxDown) {
3429                 copy.subControls = SC_SpinBoxDown;
3430                 copy.state = sb->state;
3431                 QPalette pal2 = sb->palette;
3432                 if (!(sb->stepEnabled & QAbstractSpinBox::StepDownEnabled)) {
3433                     pal2.setCurrentColorGroup(QPalette::Disabled);
3434                     copy.state &= ~State_Enabled;
3435                 }
3436                 copy.palette = pal2;
3437 
3438                 if (sb->activeSubControls == SC_SpinBoxDown && (sb->state & State_Sunken)) {
3439                     copy.state |= State_On;
3440                     copy.state |= State_Sunken;
3441                 } else {
3442                     copy.state |= State_Raised;
3443                     copy.state &= ~State_Sunken;
3444                 }
3445                 pe = (sb->buttonSymbols == QAbstractSpinBox::PlusMinus ? PE_IndicatorSpinMinus
3446                       : PE_IndicatorSpinDown);
3447 
3448                 copy.rect = proxy()->subControlRect(CC_SpinBox, sb, SC_SpinBoxDown, widget);
3449                 proxy()->drawPrimitive(PE_PanelButtonBevel, &copy, p, widget);
3450                 copy.rect.adjust(3, 0, -4, 0);
3451                 proxy()->drawPrimitive(pe, &copy, p, widget);
3452             }
3453         }
3454         break;
3455 #endif // QT_CONFIG(spinbox)
3456 #if QT_CONFIG(toolbutton)
3457     case CC_ToolButton:
3458         if (const QStyleOptionToolButton *toolbutton
3459             = qstyleoption_cast<const QStyleOptionToolButton *>(opt)) {
3460             QRect button, menuarea;
3461             button = proxy()->subControlRect(cc, toolbutton, SC_ToolButton, widget);
3462             menuarea = proxy()->subControlRect(cc, toolbutton, SC_ToolButtonMenu, widget);
3463 
3464             State bflags = toolbutton->state & ~State_Sunken;
3465 
3466             if (bflags & State_AutoRaise) {
3467                 if (!(bflags & State_MouseOver) || !(bflags & State_Enabled)) {
3468                     bflags &= ~State_Raised;
3469                 }
3470             }
3471             State mflags = bflags;
3472             if (toolbutton->state & State_Sunken) {
3473                 if (toolbutton->activeSubControls & SC_ToolButton)
3474                     bflags |= State_Sunken;
3475                 mflags |= State_Sunken;
3476             }
3477 
3478             QStyleOption tool = *toolbutton;
3479             if (toolbutton->subControls & SC_ToolButton) {
3480                 if (bflags & (State_Sunken | State_On | State_Raised)) {
3481                     tool.rect = button;
3482                     tool.state = bflags;
3483                     proxy()->drawPrimitive(PE_PanelButtonTool, &tool, p, widget);
3484                 }
3485             }
3486 
3487             if (toolbutton->state & State_HasFocus) {
3488                 QStyleOptionFocusRect fr;
3489                 fr.QStyleOption::operator=(*toolbutton);
3490                 fr.rect.adjust(3, 3, -3, -3);
3491                 if (toolbutton->features & QStyleOptionToolButton::MenuButtonPopup)
3492                     fr.rect.adjust(0, 0, -proxy()->pixelMetric(QStyle::PM_MenuButtonIndicator,
3493                                                       toolbutton, widget), 0);
3494                 proxy()->drawPrimitive(PE_FrameFocusRect, &fr, p, widget);
3495             }
3496             QStyleOptionToolButton label = *toolbutton;
3497             label.state = bflags;
3498             int fw = proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget);
3499             label.rect = button.adjusted(fw, fw, -fw, -fw);
3500             proxy()->drawControl(CE_ToolButtonLabel, &label, p, widget);
3501 
3502             if (toolbutton->subControls & SC_ToolButtonMenu) {
3503                 tool.rect = menuarea;
3504                 tool.state = mflags;
3505                 if (mflags & (State_Sunken | State_On | State_Raised))
3506                     proxy()->drawPrimitive(PE_IndicatorButtonDropDown, &tool, p, widget);
3507                 proxy()->drawPrimitive(PE_IndicatorArrowDown, &tool, p, widget);
3508             } else if (toolbutton->features & QStyleOptionToolButton::HasMenu) {
3509                 int mbi = proxy()->pixelMetric(PM_MenuButtonIndicator, toolbutton, widget);
3510                 QRect ir = toolbutton->rect;
3511                 QStyleOptionToolButton newBtn = *toolbutton;
3512                 newBtn.rect = QRect(ir.right() + 5 - mbi, ir.y() + ir.height() - mbi + 4, mbi - 6, mbi - 6);
3513                 newBtn.rect = visualRect(toolbutton->direction, button, newBtn.rect);
3514                 proxy()->drawPrimitive(PE_IndicatorArrowDown, &newBtn, p, widget);
3515             }
3516         }
3517         break;
3518 #endif // QT_CONFIG(toolbutton)
3519     case CC_TitleBar:
3520         if (const QStyleOptionTitleBar *tb = qstyleoption_cast<const QStyleOptionTitleBar *>(opt)) {
3521             QRect ir;
3522             if (opt->subControls & SC_TitleBarLabel) {
3523                 QColor left = tb->palette.highlight().color();
3524                 QColor right = tb->palette.base().color();
3525 
3526                 QBrush fillBrush(left);
3527                 if (left != right) {
3528                     QPoint p1(tb->rect.x(), tb->rect.top() + tb->rect.height()/2);
3529                     QPoint p2(tb->rect.right(), tb->rect.top() + tb->rect.height()/2);
3530                     QLinearGradient lg(p1, p2);
3531                     lg.setColorAt(0, left);
3532                     lg.setColorAt(1, right);
3533                     fillBrush = lg;
3534                 }
3535 
3536                 p->fillRect(opt->rect, fillBrush);
3537 
3538                 ir = proxy()->subControlRect(CC_TitleBar, tb, SC_TitleBarLabel, widget);
3539 
3540                 p->setPen(tb->palette.highlightedText().color());
3541                 p->drawText(ir.x() + 2, ir.y(), ir.width() - 2, ir.height(),
3542                             Qt::AlignLeft | Qt::AlignVCenter | Qt::TextSingleLine, tb->text);
3543             }
3544 
3545             bool down = false;
3546             QPixmap pm;
3547 
3548             QStyleOption tool = *tb;
3549             if (tb->subControls & SC_TitleBarCloseButton && tb->titleBarFlags & Qt::WindowSystemMenuHint) {
3550                 ir = proxy()->subControlRect(CC_TitleBar, tb, SC_TitleBarCloseButton, widget);
3551                 down = tb->activeSubControls & SC_TitleBarCloseButton && (opt->state & State_Sunken);
3552                 if ((tb->titleBarFlags & Qt::WindowType_Mask) == Qt::Tool
3553 #if QT_CONFIG(dockwidget)
3554                     || qobject_cast<const QDockWidget *>(widget)
3555 #endif
3556                     )
3557                     pm = proxy()->standardIcon(SP_DockWidgetCloseButton, &tool, widget).pixmap(qt_getWindow(widget), QSize(10, 10));
3558                 else
3559                     pm = proxy()->standardIcon(SP_TitleBarCloseButton, &tool, widget).pixmap(qt_getWindow(widget), QSize(10, 10));
3560                 tool.rect = ir;
3561                 tool.state = down ? State_Sunken : State_Raised;
3562                 proxy()->drawPrimitive(PE_PanelButtonTool, &tool, p, widget);
3563 
3564                 p->save();
3565                 if (down)
3566                     p->translate(proxy()->pixelMetric(PM_ButtonShiftHorizontal, tb, widget),
3567                                  proxy()->pixelMetric(PM_ButtonShiftVertical, tb, widget));
3568                 proxy()->drawItemPixmap(p, ir, Qt::AlignCenter, pm);
3569                 p->restore();
3570             }
3571 
3572             if (tb->subControls & SC_TitleBarMaxButton
3573                     && tb->titleBarFlags & Qt::WindowMaximizeButtonHint
3574                     && !(tb->titleBarState & Qt::WindowMaximized)) {
3575                 ir = proxy()->subControlRect(CC_TitleBar, tb, SC_TitleBarMaxButton, widget);
3576 
3577                 down = tb->activeSubControls & SC_TitleBarMaxButton && (opt->state & State_Sunken);
3578                 pm = proxy()->standardIcon(SP_TitleBarMaxButton, &tool, widget).pixmap(qt_getWindow(widget), QSize(10, 10));
3579                 tool.rect = ir;
3580                 tool.state = down ? State_Sunken : State_Raised;
3581                 proxy()->drawPrimitive(PE_PanelButtonTool, &tool, p, widget);
3582 
3583                 p->save();
3584                 if (down)
3585                     p->translate(proxy()->pixelMetric(PM_ButtonShiftHorizontal, tb, widget),
3586                                  proxy()->pixelMetric(PM_ButtonShiftVertical, tb, widget));
3587                 proxy()->drawItemPixmap(p, ir, Qt::AlignCenter, pm);
3588                 p->restore();
3589             }
3590 
3591             if (tb->subControls & SC_TitleBarMinButton
3592                     && tb->titleBarFlags & Qt::WindowMinimizeButtonHint
3593                     && !(tb->titleBarState & Qt::WindowMinimized)) {
3594                 ir = proxy()->subControlRect(CC_TitleBar, tb, SC_TitleBarMinButton, widget);
3595                 down = tb->activeSubControls & SC_TitleBarMinButton && (opt->state & State_Sunken);
3596                 pm = proxy()->standardIcon(SP_TitleBarMinButton, &tool, widget).pixmap(qt_getWindow(widget), QSize(10, 10));
3597                 tool.rect = ir;
3598                 tool.state = down ? State_Sunken : State_Raised;
3599                 proxy()->drawPrimitive(PE_PanelButtonTool, &tool, p, widget);
3600 
3601                 p->save();
3602                 if (down)
3603                     p->translate(proxy()->pixelMetric(PM_ButtonShiftHorizontal, tb, widget),
3604                                  proxy()->pixelMetric(PM_ButtonShiftVertical, tb, widget));
3605                 proxy()->drawItemPixmap(p, ir, Qt::AlignCenter, pm);
3606                 p->restore();
3607             }
3608 
3609             bool drawNormalButton = (tb->subControls & SC_TitleBarNormalButton)
3610                                     && (((tb->titleBarFlags & Qt::WindowMinimizeButtonHint)
3611                                     && (tb->titleBarState & Qt::WindowMinimized))
3612                                     || ((tb->titleBarFlags & Qt::WindowMaximizeButtonHint)
3613                                     && (tb->titleBarState & Qt::WindowMaximized)));
3614 
3615             if (drawNormalButton) {
3616                 ir = proxy()->subControlRect(CC_TitleBar, tb, SC_TitleBarNormalButton, widget);
3617                 down = tb->activeSubControls & SC_TitleBarNormalButton && (opt->state & State_Sunken);
3618                 pm = proxy()->standardIcon(SP_TitleBarNormalButton, &tool, widget).pixmap(qt_getWindow(widget), QSize(10, 10));
3619                 tool.rect = ir;
3620                 tool.state = down ? State_Sunken : State_Raised;
3621                 proxy()->drawPrimitive(PE_PanelButtonTool, &tool, p, widget);
3622 
3623                 p->save();
3624                 if (down)
3625                     p->translate(proxy()->pixelMetric(PM_ButtonShiftHorizontal, tb, widget),
3626                                  proxy()->pixelMetric(PM_ButtonShiftVertical, tb, widget));
3627                 proxy()->drawItemPixmap(p, ir, Qt::AlignCenter, pm);
3628                 p->restore();
3629             }
3630 
3631             if (tb->subControls & SC_TitleBarShadeButton
3632                     && tb->titleBarFlags & Qt::WindowShadeButtonHint
3633                     && !(tb->titleBarState & Qt::WindowMinimized)) {
3634                 ir = proxy()->subControlRect(CC_TitleBar, tb, SC_TitleBarShadeButton, widget);
3635                 down = (tb->activeSubControls & SC_TitleBarShadeButton && (opt->state & State_Sunken));
3636                 pm = proxy()->standardIcon(SP_TitleBarShadeButton, &tool, widget).pixmap(qt_getWindow(widget), QSize(10, 10));
3637                 tool.rect = ir;
3638                 tool.state = down ? State_Sunken : State_Raised;
3639                 proxy()->drawPrimitive(PE_PanelButtonTool, &tool, p, widget);
3640                 p->save();
3641                 if (down)
3642                     p->translate(proxy()->pixelMetric(PM_ButtonShiftHorizontal, tb, widget),
3643                                  proxy()->pixelMetric(PM_ButtonShiftVertical, tb, widget));
3644                 proxy()->drawItemPixmap(p, ir, Qt::AlignCenter, pm);
3645                 p->restore();
3646             }
3647 
3648             if (tb->subControls & SC_TitleBarUnshadeButton
3649                     && tb->titleBarFlags & Qt::WindowShadeButtonHint
3650                     && tb->titleBarState & Qt::WindowMinimized) {
3651                 ir = proxy()->subControlRect(CC_TitleBar, tb, SC_TitleBarUnshadeButton, widget);
3652 
3653                 down = tb->activeSubControls & SC_TitleBarUnshadeButton  && (opt->state & State_Sunken);
3654                 pm = proxy()->standardIcon(SP_TitleBarUnshadeButton, &tool, widget).pixmap(qt_getWindow(widget), QSize(10, 10));
3655                 tool.rect = ir;
3656                 tool.state = down ? State_Sunken : State_Raised;
3657                 proxy()->drawPrimitive(PE_PanelButtonTool, &tool, p, widget);
3658                 p->save();
3659                 if (down)
3660                     p->translate(proxy()->pixelMetric(PM_ButtonShiftHorizontal, tb, widget),
3661                                  proxy()->pixelMetric(PM_ButtonShiftVertical, tb, widget));
3662                 proxy()->drawItemPixmap(p, ir, Qt::AlignCenter, pm);
3663                 p->restore();
3664             }
3665             if (tb->subControls & SC_TitleBarContextHelpButton
3666                     && tb->titleBarFlags & Qt::WindowContextHelpButtonHint) {
3667                 ir = proxy()->subControlRect(CC_TitleBar, tb, SC_TitleBarContextHelpButton, widget);
3668 
3669                 down = tb->activeSubControls & SC_TitleBarContextHelpButton  && (opt->state & State_Sunken);
3670                 pm = proxy()->standardIcon(SP_TitleBarContextHelpButton, &tool, widget).pixmap(qt_getWindow(widget), QSize(10, 10));
3671                 tool.rect = ir;
3672                 tool.state = down ? State_Sunken : State_Raised;
3673                 proxy()->drawPrimitive(PE_PanelButtonTool, &tool, p, widget);
3674                 p->save();
3675                 if (down)
3676                     p->translate(proxy()->pixelMetric(PM_ButtonShiftHorizontal, tb, widget),
3677                                  proxy()->pixelMetric(PM_ButtonShiftVertical, tb, widget));
3678                 proxy()->drawItemPixmap(p, ir, Qt::AlignCenter, pm);
3679                 p->restore();
3680             }
3681             if (tb->subControls & SC_TitleBarSysMenu && tb->titleBarFlags & Qt::WindowSystemMenuHint) {
3682                 ir = proxy()->subControlRect(CC_TitleBar, tb, SC_TitleBarSysMenu, widget);
3683                 if (!tb->icon.isNull()) {
3684                     tb->icon.paint(p, ir);
3685                 } else {
3686                     int iconSize = proxy()->pixelMetric(PM_SmallIconSize, tb, widget);
3687                     pm = proxy()->standardIcon(SP_TitleBarMenuButton, &tool, widget).pixmap(qt_getWindow(widget), QSize(iconSize, iconSize));
3688                     tool.rect = ir;
3689                     p->save();
3690                     proxy()->drawItemPixmap(p, ir, Qt::AlignCenter, pm);
3691                     p->restore();
3692                 }
3693             }
3694         }
3695         break;
3696 #if QT_CONFIG(dial)
3697     case CC_Dial:
3698         if (const QStyleOptionSlider *dial = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
3699             // OK, this is more a port of things over
3700             p->save();
3701 
3702             // avoid dithering
3703             if (p->paintEngine()->hasFeature(QPaintEngine::Antialiasing))
3704                 p->setRenderHint(QPainter::Antialiasing);
3705 
3706             int width = dial->rect.width();
3707             int height = dial->rect.height();
3708             qreal r = qMin(width, height) / 2;
3709             qreal d_ = r / 6;
3710             qreal dx = dial->rect.x() + d_ + (width - 2 * r) / 2 + 1;
3711             qreal dy = dial->rect.y() + d_ + (height - 2 * r) / 2 + 1;
3712             QRect br = QRect(int(dx), int(dy), int(r * 2 - 2 * d_ - 2), int(r * 2 - 2 * d_ - 2));
3713 
3714             QPalette pal = opt->palette;
3715             // draw notches
3716             if (dial->subControls & QStyle::SC_DialTickmarks) {
3717                 p->setPen(pal.windowText().color());
3718                 p->drawLines(QStyleHelper::calcLines(dial));
3719             }
3720 
3721             if (dial->state & State_Enabled) {
3722                 p->setBrush(pal.brush(QPalette::ColorRole(proxy()->styleHint(SH_Dial_BackgroundRole,
3723                                                                     dial, widget))));
3724                 p->setPen(Qt::NoPen);
3725                 p->drawEllipse(br);
3726                 p->setBrush(Qt::NoBrush);
3727             }
3728             p->setPen(QPen(pal.dark().color()));
3729             p->drawArc(br, 60 * 16, 180 * 16);
3730             p->setPen(QPen(pal.light().color()));
3731             p->drawArc(br, 240 * 16, 180 * 16);
3732 
3733             qreal a;
3734             const StaticPolygonF<3> arrow = calcArrow(dial, a);
3735 
3736             p->setPen(Qt::NoPen);
3737             p->setBrush(pal.button());
3738             p->setRenderHint(QPainter::Qt4CompatiblePainting);
3739             p->drawPolygon(arrow.cbegin(), arrow.size());
3740 
3741             a = QStyleHelper::angle(QPointF(width / 2, height / 2), arrow[0]);
3742             p->setBrush(Qt::NoBrush);
3743 
3744             if (a <= 0 || a > 200) {
3745                 p->setPen(pal.light().color());
3746                 p->drawLine(arrow[2], arrow[0]);
3747                 p->drawLine(arrow[1], arrow[2]);
3748                 p->setPen(pal.dark().color());
3749                 p->drawLine(arrow[0], arrow[1]);
3750             } else if (a > 0 && a < 45) {
3751                 p->setPen(pal.light().color());
3752                 p->drawLine(arrow[2], arrow[0]);
3753                 p->setPen(pal.dark().color());
3754                 p->drawLine(arrow[1], arrow[2]);
3755                 p->drawLine(arrow[0], arrow[1]);
3756             } else if (a >= 45 && a < 135) {
3757                 p->setPen(pal.dark().color());
3758                 p->drawLine(arrow[2], arrow[0]);
3759                 p->drawLine(arrow[1], arrow[2]);
3760                 p->setPen(pal.light().color());
3761                 p->drawLine(arrow[0], arrow[1]);
3762             } else if (a >= 135 && a < 200) {
3763                 p->setPen(pal.dark().color());
3764                 p->drawLine(arrow[2], arrow[0]);
3765                 p->setPen(pal.light().color());
3766                 p->drawLine(arrow[0], arrow[1]);
3767                 p->drawLine(arrow[1], arrow[2]);
3768             }
3769 
3770             // draw focus rect around the dial
3771             QStyleOptionFocusRect fropt;
3772             fropt.rect = dial->rect;
3773             fropt.state = dial->state;
3774             fropt.palette = dial->palette;
3775             if (fropt.state & QStyle::State_HasFocus) {
3776                 br.adjust(0, 0, 2, 2);
3777                 if (dial->subControls & SC_DialTickmarks) {
3778                     int r = qMin(width, height) / 2;
3779                     br.translate(-r / 6, - r / 6);
3780                     br.setWidth(br.width() + r / 3);
3781                     br.setHeight(br.height() + r / 3);
3782                 }
3783                 fropt.rect = br.adjusted(-2, -2, 2, 2);
3784                 proxy()->drawPrimitive(QStyle::PE_FrameFocusRect, &fropt, p, widget);
3785             }
3786             p->restore();
3787         }
3788         break;
3789 #endif // QT_CONFIG(dial)
3790 #if QT_CONFIG(groupbox)
3791     case CC_GroupBox:
3792         if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast<const QStyleOptionGroupBox *>(opt)) {
3793             // Draw frame
3794             QRect textRect = proxy()->subControlRect(CC_GroupBox, opt, SC_GroupBoxLabel, widget);
3795             QRect checkBoxRect = proxy()->subControlRect(CC_GroupBox, opt, SC_GroupBoxCheckBox, widget);
3796             if (groupBox->subControls & QStyle::SC_GroupBoxFrame) {
3797                 QStyleOptionFrame frame;
3798                 frame.QStyleOption::operator=(*groupBox);
3799                 frame.features = groupBox->features;
3800                 frame.lineWidth = groupBox->lineWidth;
3801                 frame.midLineWidth = groupBox->midLineWidth;
3802                 frame.rect = proxy()->subControlRect(CC_GroupBox, opt, SC_GroupBoxFrame, widget);
3803                 p->save();
3804                 QRegion region(groupBox->rect);
3805                 if (!groupBox->text.isEmpty()) {
3806                     bool ltr = groupBox->direction == Qt::LeftToRight;
3807                     QRect finalRect;
3808                     if (groupBox->subControls & QStyle::SC_GroupBoxCheckBox) {
3809                         finalRect = checkBoxRect.united(textRect);
3810                         finalRect.adjust(ltr ? -4 : 0, 0, ltr ? 0 : 4, 0);
3811                     } else {
3812                         finalRect = textRect;
3813                     }
3814                     region -= finalRect;
3815                 }
3816                 p->setClipRegion(region);
3817                 proxy()->drawPrimitive(PE_FrameGroupBox, &frame, p, widget);
3818                 p->restore();
3819             }
3820 
3821             // Draw title
3822             if ((groupBox->subControls & QStyle::SC_GroupBoxLabel) && !groupBox->text.isEmpty()) {
3823                 QColor textColor = groupBox->textColor;
3824                 if (textColor.isValid())
3825                     p->setPen(textColor);
3826                 int alignment = int(groupBox->textAlignment);
3827                 if (!proxy()->styleHint(QStyle::SH_UnderlineShortcut, opt, widget))
3828                     alignment |= Qt::TextHideMnemonic;
3829 
3830                 proxy()->drawItemText(p, textRect,  Qt::TextShowMnemonic | Qt::AlignHCenter | alignment,
3831                              groupBox->palette, groupBox->state & State_Enabled, groupBox->text,
3832                              textColor.isValid() ? QPalette::NoRole : QPalette::WindowText);
3833 
3834                 if (groupBox->state & State_HasFocus) {
3835                     QStyleOptionFocusRect fropt;
3836                     fropt.QStyleOption::operator=(*groupBox);
3837                     fropt.rect = textRect;
3838                     proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, p, widget);
3839                 }
3840             }
3841 
3842             // Draw checkbox
3843             if (groupBox->subControls & SC_GroupBoxCheckBox) {
3844                 QStyleOptionButton box;
3845                 box.QStyleOption::operator=(*groupBox);
3846                 box.rect = checkBoxRect;
3847                 proxy()->drawPrimitive(PE_IndicatorCheckBox, &box, p, widget);
3848             }
3849         }
3850         break;
3851 #endif // QT_CONFIG(groupbox)
3852 #if QT_CONFIG(mdiarea)
3853     case CC_MdiControls:
3854         {
3855             QStyleOptionButton btnOpt;
3856             btnOpt.QStyleOption::operator=(*opt);
3857             btnOpt.state &= ~State_MouseOver;
3858             int bsx = 0;
3859             int bsy = 0;
3860             const int buttonIconMetric = proxy()->pixelMetric(PM_TitleBarButtonIconSize, &btnOpt, widget);
3861             const QSize buttonIconSize(buttonIconMetric, buttonIconMetric);
3862             if (opt->subControls & QStyle::SC_MdiCloseButton) {
3863                 if (opt->activeSubControls & QStyle::SC_MdiCloseButton && (opt->state & State_Sunken)) {
3864                     btnOpt.state |= State_Sunken;
3865                     btnOpt.state &= ~State_Raised;
3866                     bsx = proxy()->pixelMetric(PM_ButtonShiftHorizontal, opt);
3867                     bsy = proxy()->pixelMetric(PM_ButtonShiftVertical, opt);
3868                 } else {
3869                     btnOpt.state |= State_Raised;
3870                     btnOpt.state &= ~State_Sunken;
3871                     bsx = 0;
3872                     bsy = 0;
3873                 }
3874                 btnOpt.rect = proxy()->subControlRect(CC_MdiControls, opt, SC_MdiCloseButton, widget);
3875                 proxy()->drawPrimitive(PE_PanelButtonCommand, &btnOpt, p, widget);
3876                 QPixmap pm = proxy()->standardIcon(SP_TitleBarCloseButton).pixmap(qt_getWindow(widget), buttonIconSize);
3877                 proxy()->drawItemPixmap(p, btnOpt.rect.translated(bsx, bsy), Qt::AlignCenter, pm);
3878             }
3879             if (opt->subControls & QStyle::SC_MdiNormalButton) {
3880                 if (opt->activeSubControls & QStyle::SC_MdiNormalButton && (opt->state & State_Sunken)) {
3881                     btnOpt.state |= State_Sunken;
3882                     btnOpt.state &= ~State_Raised;
3883                     bsx = proxy()->pixelMetric(PM_ButtonShiftHorizontal, opt);
3884                     bsy = proxy()->pixelMetric(PM_ButtonShiftVertical, opt);
3885                 } else {
3886                     btnOpt.state |= State_Raised;
3887                     btnOpt.state &= ~State_Sunken;
3888                     bsx = 0;
3889                     bsy = 0;
3890                 }
3891                 btnOpt.rect = proxy()->subControlRect(CC_MdiControls, opt, SC_MdiNormalButton, widget);
3892                 proxy()->drawPrimitive(PE_PanelButtonCommand, &btnOpt, p, widget);
3893                 QPixmap pm = proxy()->standardIcon(SP_TitleBarNormalButton).pixmap(qt_getWindow(widget), buttonIconSize);
3894                 proxy()->drawItemPixmap(p, btnOpt.rect.translated(bsx, bsy), Qt::AlignCenter, pm);
3895             }
3896             if (opt->subControls & QStyle::SC_MdiMinButton) {
3897                 if (opt->activeSubControls & QStyle::SC_MdiMinButton && (opt->state & State_Sunken)) {
3898                     btnOpt.state |= State_Sunken;
3899                     btnOpt.state &= ~State_Raised;
3900                     bsx = proxy()->pixelMetric(PM_ButtonShiftHorizontal, opt);
3901                     bsy = proxy()->pixelMetric(PM_ButtonShiftVertical, opt);
3902                 } else {
3903                     btnOpt.state |= State_Raised;
3904                     btnOpt.state &= ~State_Sunken;
3905                     bsx = 0;
3906                     bsy = 0;
3907                 }
3908                 btnOpt.rect = proxy()->subControlRect(CC_MdiControls, opt, SC_MdiMinButton, widget);
3909                 proxy()->drawPrimitive(PE_PanelButtonCommand, &btnOpt, p, widget);
3910                 QPixmap pm = proxy()->standardIcon(SP_TitleBarMinButton).pixmap(qt_getWindow(widget), buttonIconSize);
3911                 proxy()->drawItemPixmap(p, btnOpt.rect.translated(bsx, bsy), Qt::AlignCenter, pm);
3912             }
3913         }
3914         break;
3915 #endif // QT_CONFIG(mdiarea)
3916     default:
3917         qWarning("QCommonStyle::drawComplexControl: Control %d not handled", cc);
3918     }
3919 }
3920 
3921 /*!
3922     \reimp
3923 */
hitTestComplexControl(ComplexControl cc,const QStyleOptionComplex * opt,const QPoint & pt,const QWidget * widget) const3924 QStyle::SubControl QCommonStyle::hitTestComplexControl(ComplexControl cc, const QStyleOptionComplex *opt,
3925                                                  const QPoint &pt, const QWidget *widget) const
3926 {
3927     SubControl sc = SC_None;
3928     switch (cc) {
3929 #if QT_CONFIG(slider)
3930     case CC_Slider:
3931         if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
3932             QRect r = proxy()->subControlRect(cc, slider, SC_SliderHandle, widget);
3933             if (r.isValid() && r.contains(pt)) {
3934                 sc = SC_SliderHandle;
3935             } else {
3936                 r = proxy()->subControlRect(cc, slider, SC_SliderGroove ,widget);
3937                 if (r.isValid() && r.contains(pt))
3938                     sc = SC_SliderGroove;
3939             }
3940         }
3941         break;
3942 #endif // QT_CONFIG(slider)
3943 #if QT_CONFIG(scrollbar)
3944     case CC_ScrollBar:
3945         if (const QStyleOptionSlider *scrollbar = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
3946             QRect r;
3947             uint ctrl = SC_ScrollBarAddLine;
3948             while (ctrl <= SC_ScrollBarGroove) {
3949                 r = proxy()->subControlRect(cc, scrollbar, QStyle::SubControl(ctrl), widget);
3950                 if (r.isValid() && r.contains(pt)) {
3951                     sc = QStyle::SubControl(ctrl);
3952                     break;
3953                 }
3954                 ctrl <<= 1;
3955             }
3956         }
3957         break;
3958 #endif // QT_CONFIG(scrollbar)
3959 #if QT_CONFIG(toolbutton)
3960     case CC_ToolButton:
3961         if (const QStyleOptionToolButton *toolbutton = qstyleoption_cast<const QStyleOptionToolButton *>(opt)) {
3962             QRect r;
3963             uint ctrl = SC_ToolButton;
3964             while (ctrl <= SC_ToolButtonMenu) {
3965                 r = proxy()->subControlRect(cc, toolbutton, QStyle::SubControl(ctrl), widget);
3966                 if (r.isValid() && r.contains(pt)) {
3967                     sc = QStyle::SubControl(ctrl);
3968                     break;
3969                 }
3970                 ctrl <<= 1;
3971             }
3972         }
3973         break;
3974 #endif // QT_CONFIG(toolbutton)
3975 #if QT_CONFIG(spinbox)
3976     case CC_SpinBox:
3977         if (const QStyleOptionSpinBox *spinbox = qstyleoption_cast<const QStyleOptionSpinBox *>(opt)) {
3978             QRect r;
3979             uint ctrl = SC_SpinBoxUp;
3980             while (ctrl <= SC_SpinBoxEditField) {
3981                 r = proxy()->subControlRect(cc, spinbox, QStyle::SubControl(ctrl), widget);
3982                 if (r.isValid() && r.contains(pt)) {
3983                     sc = QStyle::SubControl(ctrl);
3984                     break;
3985                 }
3986                 ctrl <<= 1;
3987             }
3988         }
3989         break;
3990 #endif // QT_CONFIG(spinbox)
3991     case CC_TitleBar:
3992         if (const QStyleOptionTitleBar *tb = qstyleoption_cast<const QStyleOptionTitleBar *>(opt)) {
3993             QRect r;
3994             uint ctrl = SC_TitleBarSysMenu;
3995 
3996             while (ctrl <= SC_TitleBarLabel) {
3997                 r = proxy()->subControlRect(cc, tb, QStyle::SubControl(ctrl), widget);
3998                 if (r.isValid() && r.contains(pt)) {
3999                     sc = QStyle::SubControl(ctrl);
4000                     break;
4001                 }
4002                 ctrl <<= 1;
4003             }
4004         }
4005         break;
4006 #if QT_CONFIG(combobox)
4007     case CC_ComboBox:
4008         if (const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(opt)) {
4009             QRect r;
4010             uint ctrl = SC_ComboBoxArrow;  // Start here and go down.
4011             while (ctrl > 0) {
4012                 r = proxy()->subControlRect(cc, cb, QStyle::SubControl(ctrl), widget);
4013                 if (r.isValid() && r.contains(pt)) {
4014                     sc = QStyle::SubControl(ctrl);
4015                     break;
4016                 }
4017                 ctrl >>= 1;
4018             }
4019         }
4020         break;
4021 #endif // QT_CONFIG(combobox)
4022 #if QT_CONFIG(groupbox)
4023     case CC_GroupBox:
4024         if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast<const QStyleOptionGroupBox *>(opt)) {
4025             QRect r;
4026             uint ctrl = SC_GroupBoxCheckBox;
4027             while (ctrl <= SC_GroupBoxFrame) {
4028                 r = proxy()->subControlRect(cc, groupBox, QStyle::SubControl(ctrl), widget);
4029                 if (r.isValid() && r.contains(pt)) {
4030                     sc = QStyle::SubControl(ctrl);
4031                     break;
4032                 }
4033                 ctrl <<= 1;
4034             }
4035         }
4036         break;
4037 #endif // QT_CONFIG(groupbox)
4038     case CC_MdiControls:
4039         {
4040             QRect r;
4041             uint ctrl = SC_MdiMinButton;
4042             while (ctrl <= SC_MdiCloseButton) {
4043                 r = proxy()->subControlRect(CC_MdiControls, opt, QStyle::SubControl(ctrl), widget);
4044                 if (r.isValid() && r.contains(pt) && (opt->subControls & ctrl)) {
4045                     sc = QStyle::SubControl(ctrl);
4046                     return sc;
4047                 }
4048                 ctrl <<= 1;
4049             }
4050         }
4051         break;
4052     default:
4053         qWarning("QCommonStyle::hitTestComplexControl: Case %d not handled", cc);
4054     }
4055     return sc;
4056 }
4057 
4058 /*!
4059     \reimp
4060 */
subControlRect(ComplexControl cc,const QStyleOptionComplex * opt,SubControl sc,const QWidget * widget) const4061 QRect QCommonStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *opt,
4062                                    SubControl sc, const QWidget *widget) const
4063 {
4064     QRect ret;
4065     switch (cc) {
4066 #if QT_CONFIG(slider)
4067     case CC_Slider:
4068         if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
4069             int tickOffset = proxy()->pixelMetric(PM_SliderTickmarkOffset, slider, widget);
4070             int thickness = proxy()->pixelMetric(PM_SliderControlThickness, slider, widget);
4071 
4072             switch (sc) {
4073             case SC_SliderHandle: {
4074                 int sliderPos = 0;
4075                 int len = proxy()->pixelMetric(PM_SliderLength, slider, widget);
4076                 bool horizontal = slider->orientation == Qt::Horizontal;
4077                 sliderPos = sliderPositionFromValue(slider->minimum, slider->maximum,
4078                                                     slider->sliderPosition,
4079                                                     (horizontal ? slider->rect.width()
4080                                                                 : slider->rect.height()) - len,
4081                                                     slider->upsideDown);
4082                 if (horizontal)
4083                     ret.setRect(slider->rect.x() + sliderPos, slider->rect.y() + tickOffset, len, thickness);
4084                 else
4085                     ret.setRect(slider->rect.x() + tickOffset, slider->rect.y() + sliderPos, thickness, len);
4086                 break; }
4087             case SC_SliderGroove:
4088                 if (slider->orientation == Qt::Horizontal)
4089                     ret.setRect(slider->rect.x(), slider->rect.y() + tickOffset,
4090                                 slider->rect.width(), thickness);
4091                 else
4092                     ret.setRect(slider->rect.x() + tickOffset, slider->rect.y(),
4093                                 thickness, slider->rect.height());
4094                 break;
4095             default:
4096                 break;
4097             }
4098             ret = visualRect(slider->direction, slider->rect, ret);
4099         }
4100         break;
4101 #endif // QT_CONFIG(slider)
4102 #if QT_CONFIG(scrollbar)
4103     case CC_ScrollBar:
4104         if (const QStyleOptionSlider *scrollbar = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
4105             const QRect scrollBarRect = scrollbar->rect;
4106             int sbextent = 0;
4107             if (!proxy()->styleHint(SH_ScrollBar_Transient, scrollbar, widget))
4108                 sbextent = proxy()->pixelMetric(PM_ScrollBarExtent, scrollbar, widget);
4109             int maxlen = ((scrollbar->orientation == Qt::Horizontal) ?
4110                           scrollBarRect.width() : scrollBarRect.height()) - (sbextent * 2);
4111             int sliderlen;
4112 
4113             // calculate slider length
4114             if (scrollbar->maximum != scrollbar->minimum) {
4115                 uint range = scrollbar->maximum - scrollbar->minimum;
4116                 sliderlen = (qint64(scrollbar->pageStep) * maxlen) / (range + scrollbar->pageStep);
4117 
4118                 int slidermin = proxy()->pixelMetric(PM_ScrollBarSliderMin, scrollbar, widget);
4119                 if (sliderlen < slidermin || range > INT_MAX / 2)
4120                     sliderlen = slidermin;
4121                 if (sliderlen > maxlen)
4122                     sliderlen = maxlen;
4123             } else {
4124                 sliderlen = maxlen;
4125             }
4126 
4127             int sliderstart = sbextent + sliderPositionFromValue(scrollbar->minimum,
4128                                                                  scrollbar->maximum,
4129                                                                  scrollbar->sliderPosition,
4130                                                                  maxlen - sliderlen,
4131                                                                  scrollbar->upsideDown);
4132 
4133             switch (sc) {
4134             case SC_ScrollBarSubLine:            // top/left button
4135                 if (scrollbar->orientation == Qt::Horizontal) {
4136                     int buttonWidth = qMin(scrollBarRect.width() / 2, sbextent);
4137                     ret.setRect(0, 0, buttonWidth, scrollBarRect.height());
4138                 } else {
4139                     int buttonHeight = qMin(scrollBarRect.height() / 2, sbextent);
4140                     ret.setRect(0, 0, scrollBarRect.width(), buttonHeight);
4141                 }
4142                 break;
4143             case SC_ScrollBarAddLine:            // bottom/right button
4144                 if (scrollbar->orientation == Qt::Horizontal) {
4145                     int buttonWidth = qMin(scrollBarRect.width()/2, sbextent);
4146                     ret.setRect(scrollBarRect.width() - buttonWidth, 0, buttonWidth, scrollBarRect.height());
4147                 } else {
4148                     int buttonHeight = qMin(scrollBarRect.height()/2, sbextent);
4149                     ret.setRect(0, scrollBarRect.height() - buttonHeight, scrollBarRect.width(), buttonHeight);
4150                 }
4151                 break;
4152             case SC_ScrollBarSubPage:            // between top/left button and slider
4153                 if (scrollbar->orientation == Qt::Horizontal)
4154                     ret.setRect(sbextent, 0, sliderstart - sbextent, scrollBarRect.height());
4155                 else
4156                     ret.setRect(0, sbextent, scrollBarRect.width(), sliderstart - sbextent);
4157                 break;
4158             case SC_ScrollBarAddPage:            // between bottom/right button and slider
4159                 if (scrollbar->orientation == Qt::Horizontal)
4160                     ret.setRect(sliderstart + sliderlen, 0,
4161                                 maxlen - sliderstart - sliderlen + sbextent, scrollBarRect.height());
4162                 else
4163                     ret.setRect(0, sliderstart + sliderlen, scrollBarRect.width(),
4164                                 maxlen - sliderstart - sliderlen + sbextent);
4165                 break;
4166             case SC_ScrollBarGroove:
4167                 if (scrollbar->orientation == Qt::Horizontal)
4168                     ret.setRect(sbextent, 0, scrollBarRect.width() - sbextent * 2,
4169                                 scrollBarRect.height());
4170                 else
4171                     ret.setRect(0, sbextent, scrollBarRect.width(),
4172                                 scrollBarRect.height() - sbextent * 2);
4173                 break;
4174             case SC_ScrollBarSlider:
4175                 if (scrollbar->orientation == Qt::Horizontal)
4176                     ret.setRect(sliderstart, 0, sliderlen, scrollBarRect.height());
4177                 else
4178                     ret.setRect(0, sliderstart, scrollBarRect.width(), sliderlen);
4179                 break;
4180             default:
4181                 break;
4182             }
4183             ret = visualRect(scrollbar->direction, scrollBarRect, ret);
4184         }
4185         break;
4186 #endif // QT_CONFIG(scrollbar)
4187 #if QT_CONFIG(spinbox)
4188     case CC_SpinBox:
4189         if (const QStyleOptionSpinBox *spinbox = qstyleoption_cast<const QStyleOptionSpinBox *>(opt)) {
4190             QSize bs;
4191             int fw = spinbox->frame ? proxy()->pixelMetric(PM_SpinBoxFrameWidth, spinbox, widget) : 0;
4192             bs.setHeight(qMax(8, spinbox->rect.height()/2 - fw));
4193             // 1.6 -approximate golden mean
4194             bs.setWidth(qMax(16, qMin(bs.height() * 8 / 5, spinbox->rect.width() / 4)));
4195             bs = bs.expandedTo(QApplication::globalStrut());
4196             int y = fw + spinbox->rect.y();
4197             int x, lx, rx;
4198             x = spinbox->rect.x() + spinbox->rect.width() - fw - bs.width();
4199             lx = fw;
4200             rx = x - fw;
4201             switch (sc) {
4202             case SC_SpinBoxUp:
4203                 if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons)
4204                     return QRect();
4205                 ret = QRect(x, y, bs.width(), bs.height());
4206                 break;
4207             case SC_SpinBoxDown:
4208                 if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons)
4209                     return QRect();
4210 
4211                 ret = QRect(x, y + bs.height(), bs.width(), bs.height());
4212                 break;
4213             case SC_SpinBoxEditField:
4214                 if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons) {
4215                     ret = QRect(lx, fw, spinbox->rect.width() - 2*fw, spinbox->rect.height() - 2*fw);
4216                 } else {
4217                     ret = QRect(lx, fw, rx, spinbox->rect.height() - 2*fw);
4218                 }
4219                 break;
4220             case SC_SpinBoxFrame:
4221                 ret = spinbox->rect;
4222             default:
4223                 break;
4224             }
4225             ret = visualRect(spinbox->direction, spinbox->rect, ret);
4226         }
4227         break;
4228 #endif // Qt_NO_SPINBOX
4229 #if QT_CONFIG(toolbutton)
4230     case CC_ToolButton:
4231         if (const QStyleOptionToolButton *tb = qstyleoption_cast<const QStyleOptionToolButton *>(opt)) {
4232             int mbi = proxy()->pixelMetric(PM_MenuButtonIndicator, tb, widget);
4233             ret = tb->rect;
4234             switch (sc) {
4235             case SC_ToolButton:
4236                 if ((tb->features
4237                      & (QStyleOptionToolButton::MenuButtonPopup | QStyleOptionToolButton::PopupDelay))
4238                     == QStyleOptionToolButton::MenuButtonPopup)
4239                     ret.adjust(0, 0, -mbi, 0);
4240                 break;
4241             case SC_ToolButtonMenu:
4242                 if ((tb->features
4243                      & (QStyleOptionToolButton::MenuButtonPopup | QStyleOptionToolButton::PopupDelay))
4244                     == QStyleOptionToolButton::MenuButtonPopup)
4245                     ret.adjust(ret.width() - mbi, 0, 0, 0);
4246                 break;
4247             default:
4248                 break;
4249             }
4250             ret = visualRect(tb->direction, tb->rect, ret);
4251         }
4252         break;
4253 #endif // QT_CONFIG(toolbutton)
4254 #if QT_CONFIG(combobox)
4255     case CC_ComboBox:
4256         if (const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(opt)) {
4257             const qreal dpi = QStyleHelper::dpi(opt);
4258             const int x = cb->rect.x(), y = cb->rect.y(), wi = cb->rect.width(), he = cb->rect.height();
4259             const int margin = cb->frame ? qRound(QStyleHelper::dpiScaled(3, dpi)) : 0;
4260             const int bmarg = cb->frame ? qRound(QStyleHelper::dpiScaled(2, dpi)) : 0;
4261             const int xpos = x + wi - bmarg - qRound(QStyleHelper::dpiScaled(16, dpi));
4262 
4263 
4264             switch (sc) {
4265             case SC_ComboBoxFrame:
4266                 ret = cb->rect;
4267                 break;
4268             case SC_ComboBoxArrow:
4269                 ret.setRect(xpos, y + bmarg, qRound(QStyleHelper::dpiScaled(16, opt)), he - 2*bmarg);
4270                 break;
4271             case SC_ComboBoxEditField:
4272                 ret.setRect(x + margin, y + margin, wi - 2 * margin - qRound(QStyleHelper::dpiScaled(16, dpi)), he - 2 * margin);
4273                 break;
4274             case SC_ComboBoxListBoxPopup:
4275                 ret = cb->rect;
4276                 break;
4277             default:
4278                 break;
4279             }
4280             ret = visualRect(cb->direction, cb->rect, ret);
4281         }
4282         break;
4283 #endif // QT_CONFIG(combobox)
4284     case CC_TitleBar:
4285         if (const QStyleOptionTitleBar *tb = qstyleoption_cast<const QStyleOptionTitleBar *>(opt)) {
4286             const int controlMargin = 2;
4287             const int controlHeight = tb->rect.height() - controlMargin *2;
4288             const int delta = controlHeight + controlMargin;
4289             int offset = 0;
4290 
4291             bool isMinimized = tb->titleBarState & Qt::WindowMinimized;
4292             bool isMaximized = tb->titleBarState & Qt::WindowMaximized;
4293 
4294             switch (sc) {
4295             case SC_TitleBarLabel:
4296                 if (tb->titleBarFlags & (Qt::WindowTitleHint | Qt::WindowSystemMenuHint)) {
4297                     ret = tb->rect;
4298                     if (tb->titleBarFlags & Qt::WindowSystemMenuHint)
4299                         ret.adjust(delta, 0, -delta, 0);
4300                     if (tb->titleBarFlags & Qt::WindowMinimizeButtonHint)
4301                         ret.adjust(0, 0, -delta, 0);
4302                     if (tb->titleBarFlags & Qt::WindowMaximizeButtonHint)
4303                         ret.adjust(0, 0, -delta, 0);
4304                     if (tb->titleBarFlags & Qt::WindowShadeButtonHint)
4305                         ret.adjust(0, 0, -delta, 0);
4306                     if (tb->titleBarFlags & Qt::WindowContextHelpButtonHint)
4307                         ret.adjust(0, 0, -delta, 0);
4308                 }
4309                 break;
4310             case SC_TitleBarContextHelpButton:
4311                 if (tb->titleBarFlags & Qt::WindowContextHelpButtonHint)
4312                     offset += delta;
4313                 Q_FALLTHROUGH();
4314             case SC_TitleBarMinButton:
4315                 if (!isMinimized && (tb->titleBarFlags & Qt::WindowMinimizeButtonHint))
4316                     offset += delta;
4317                 else if (sc == SC_TitleBarMinButton)
4318                     break;
4319                 Q_FALLTHROUGH();
4320             case SC_TitleBarNormalButton:
4321                 if (isMinimized && (tb->titleBarFlags & Qt::WindowMinimizeButtonHint))
4322                     offset += delta;
4323                 else if (isMaximized && (tb->titleBarFlags & Qt::WindowMaximizeButtonHint))
4324                     offset += delta;
4325                 else if (sc == SC_TitleBarNormalButton)
4326                     break;
4327                 Q_FALLTHROUGH();
4328             case SC_TitleBarMaxButton:
4329                 if (!isMaximized && (tb->titleBarFlags & Qt::WindowMaximizeButtonHint))
4330                     offset += delta;
4331                 else if (sc == SC_TitleBarMaxButton)
4332                     break;
4333                 Q_FALLTHROUGH();
4334             case SC_TitleBarShadeButton:
4335                 if (!isMinimized && (tb->titleBarFlags & Qt::WindowShadeButtonHint))
4336                     offset += delta;
4337                 else if (sc == SC_TitleBarShadeButton)
4338                     break;
4339                 Q_FALLTHROUGH();
4340             case SC_TitleBarUnshadeButton:
4341                 if (isMinimized && (tb->titleBarFlags & Qt::WindowShadeButtonHint))
4342                     offset += delta;
4343                 else if (sc == SC_TitleBarUnshadeButton)
4344                     break;
4345                 Q_FALLTHROUGH();
4346             case SC_TitleBarCloseButton:
4347                 if (tb->titleBarFlags & Qt::WindowSystemMenuHint)
4348                     offset += delta;
4349                 else if (sc == SC_TitleBarCloseButton)
4350                     break;
4351                 ret.setRect(tb->rect.right() - offset, tb->rect.top() + controlMargin,
4352                             controlHeight, controlHeight);
4353                 break;
4354             case SC_TitleBarSysMenu:
4355                 if (tb->titleBarFlags & Qt::WindowSystemMenuHint) {
4356                     ret.setRect(tb->rect.left() + controlMargin, tb->rect.top() + controlMargin,
4357                                 controlHeight, controlHeight);
4358                 }
4359                 break;
4360             default:
4361                 break;
4362             }
4363             ret = visualRect(tb->direction, tb->rect, ret);
4364         }
4365         break;
4366 #if QT_CONFIG(groupbox)
4367     case CC_GroupBox: {
4368         if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast<const QStyleOptionGroupBox *>(opt)) {
4369             switch (sc) {
4370             case SC_GroupBoxFrame:
4371             case SC_GroupBoxContents: {
4372                 int topMargin = 0;
4373                 int topHeight = 0;
4374                 int verticalAlignment = proxy()->styleHint(SH_GroupBox_TextLabelVerticalAlignment, groupBox, widget);
4375                 bool hasCheckBox = groupBox->subControls & QStyle::SC_GroupBoxCheckBox;
4376                 if (groupBox->text.size() || hasCheckBox) {
4377                     int checkBoxHeight = hasCheckBox ? proxy()->pixelMetric(PM_IndicatorHeight, groupBox, widget) : 0;
4378                     topHeight = qMax(groupBox->fontMetrics.height(), checkBoxHeight);
4379                     if (verticalAlignment & Qt::AlignVCenter)
4380                         topMargin = topHeight / 2;
4381                     else if (verticalAlignment & Qt::AlignTop)
4382                         topMargin = topHeight;
4383                 }
4384 
4385                 QRect frameRect = groupBox->rect;
4386                 frameRect.setTop(topMargin);
4387 
4388                 if (sc == SC_GroupBoxFrame) {
4389                     ret = frameRect;
4390                     break;
4391                 }
4392 
4393                 int frameWidth = 0;
4394                 if ((groupBox->features & QStyleOptionFrame::Flat) == 0)
4395                     frameWidth = proxy()->pixelMetric(PM_DefaultFrameWidth, groupBox, widget);
4396                 ret = frameRect.adjusted(frameWidth, frameWidth + topHeight - topMargin,
4397                                          -frameWidth, -frameWidth);
4398                 break;
4399             }
4400             case SC_GroupBoxCheckBox:
4401             case SC_GroupBoxLabel: {
4402                 QFontMetrics fontMetrics = groupBox->fontMetrics;
4403                 int th = fontMetrics.height();
4404                 int tw = fontMetrics.size(Qt::TextShowMnemonic, groupBox->text + QLatin1Char(' ')).width();
4405                 int marg = (groupBox->features & QStyleOptionFrame::Flat) ? 0 : 8;
4406                 ret = groupBox->rect.adjusted(marg, 0, -marg, 0);
4407 
4408                 int indicatorWidth = proxy()->pixelMetric(PM_IndicatorWidth, opt, widget);
4409                 int indicatorHeight = proxy()->pixelMetric(PM_IndicatorHeight, opt, widget);
4410                 int indicatorSpace = proxy()->pixelMetric(PM_CheckBoxLabelSpacing, opt, widget) - 1;
4411                 bool hasCheckBox = groupBox->subControls & QStyle::SC_GroupBoxCheckBox;
4412                 int checkBoxWidth = hasCheckBox ? (indicatorWidth + indicatorSpace) : 0;
4413                 int checkBoxHeight = hasCheckBox ? indicatorHeight : 0;
4414 
4415                 int h = qMax(th, checkBoxHeight);
4416                 ret.setHeight(h);
4417 
4418                 // Adjusted rect for label + indicatorWidth + indicatorSpace
4419                 QRect totalRect = alignedRect(groupBox->direction, groupBox->textAlignment,
4420                                               QSize(tw + checkBoxWidth, h), ret);
4421 
4422                 // Adjust totalRect if checkbox is set
4423                 if (hasCheckBox) {
4424                     bool ltr = groupBox->direction == Qt::LeftToRight;
4425                     int left = 0;
4426                     // Adjust for check box
4427                     if (sc == SC_GroupBoxCheckBox) {
4428                         left = ltr ? totalRect.left() : (totalRect.right() - indicatorWidth);
4429                         int top = totalRect.top() + (h - checkBoxHeight) / 2;
4430                         totalRect.setRect(left, top, indicatorWidth, indicatorHeight);
4431                     // Adjust for label
4432                     } else {
4433                         left = ltr ? (totalRect.left() + checkBoxWidth - 2) : totalRect.left();
4434                         int top = totalRect.top() + (h - th) / 2;
4435                         totalRect.setRect(left, top, totalRect.width() - checkBoxWidth, th);
4436                     }
4437                 }
4438                 ret = totalRect;
4439                 break;
4440             }
4441             default:
4442                 break;
4443             }
4444         }
4445         break;
4446     }
4447 #endif // QT_CONFIG(groupbox)
4448 #if QT_CONFIG(mdiarea)
4449     case CC_MdiControls:
4450     {
4451         int numSubControls = 0;
4452         if (opt->subControls & SC_MdiCloseButton)
4453             ++numSubControls;
4454         if (opt->subControls & SC_MdiMinButton)
4455             ++numSubControls;
4456         if (opt->subControls & SC_MdiNormalButton)
4457             ++numSubControls;
4458         if (numSubControls == 0)
4459             break;
4460 
4461         int buttonWidth = opt->rect.width() / numSubControls - 1;
4462         int offset = 0;
4463         switch (sc) {
4464         case SC_MdiCloseButton:
4465             // Only one sub control, no offset needed.
4466             if (numSubControls == 1)
4467                 break;
4468             offset += buttonWidth + 2;
4469             Q_FALLTHROUGH();
4470         case SC_MdiNormalButton:
4471             // No offset needed if
4472             // 1) There's only one sub control
4473             // 2) We have a close button and a normal button (offset already added in SC_MdiClose)
4474             if (numSubControls == 1 || (numSubControls == 2 && !(opt->subControls & SC_MdiMinButton)))
4475                 break;
4476             if (opt->subControls & SC_MdiNormalButton)
4477                 offset += buttonWidth;
4478             break;
4479         default:
4480             break;
4481         }
4482 
4483         // Subtract one pixel if we only have one sub control. At this point
4484         // buttonWidth is the actual width + 1 pixel margin, but we don't want the
4485         // margin when there are no other controllers.
4486         if (numSubControls == 1)
4487             --buttonWidth;
4488         ret = QRect(offset, 0, buttonWidth, opt->rect.height());
4489         break;
4490     }
4491 #endif // QT_CONFIG(mdiarea)
4492      default:
4493         qWarning("QCommonStyle::subControlRect: Case %d not handled", cc);
4494     }
4495 #if !QT_CONFIG(slider) && !QT_CONFIG(spinbox) && !QT_CONFIG(toolbutton) && !QT_CONFIG(groupbox)
4496     Q_UNUSED(widget);
4497 #endif
4498     return ret;
4499 }
4500 
4501 /*! \reimp */
pixelMetric(PixelMetric m,const QStyleOption * opt,const QWidget * widget) const4502 int QCommonStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const QWidget *widget) const
4503 {
4504     int ret;
4505 
4506     switch (m) {
4507     case PM_FocusFrameVMargin:
4508     case PM_FocusFrameHMargin:
4509         ret = 2;
4510         break;
4511     case PM_MenuBarVMargin:
4512     case PM_MenuBarHMargin:
4513         ret = 0;
4514         break;
4515     case PM_DialogButtonsSeparator:
4516         ret = int(QStyleHelper::dpiScaled(5, opt));
4517         break;
4518     case PM_DialogButtonsButtonWidth:
4519         ret = int(QStyleHelper::dpiScaled(70, opt));
4520         break;
4521     case PM_DialogButtonsButtonHeight:
4522         ret = int(QStyleHelper::dpiScaled(30, opt));
4523         break;
4524     case PM_TitleBarHeight: {
4525         if (const QStyleOptionTitleBar *tb = qstyleoption_cast<const QStyleOptionTitleBar *>(opt)) {
4526             if ((tb->titleBarFlags & Qt::WindowType_Mask) == Qt::Tool) {
4527                 ret = qMax(widget ? widget->fontMetrics().height() : opt->fontMetrics.height(), 16);
4528 #if QT_CONFIG(dockwidget)
4529             } else if (qobject_cast<const QDockWidget*>(widget)) {
4530                 ret = qMax(widget->fontMetrics().height(), int(QStyleHelper::dpiScaled(13, opt)));
4531 #endif
4532             } else {
4533                 ret = qMax(widget ? widget->fontMetrics().height() : opt->fontMetrics.height(), 18);
4534             }
4535         } else {
4536             ret = int(QStyleHelper::dpiScaled(18., opt));
4537         }
4538 
4539         break; }
4540     case PM_TitleBarButtonSize:
4541         ret = int(QStyleHelper::dpiScaled(16., opt));
4542         break;
4543     case PM_TitleBarButtonIconSize:
4544         ret = int(QStyleHelper::dpiScaled(16., opt));
4545         break;
4546 
4547     case PM_ScrollBarSliderMin:
4548         ret = int(QStyleHelper::dpiScaled(9., opt));
4549         break;
4550 
4551     case PM_ButtonMargin:
4552         ret = int(QStyleHelper::dpiScaled(6., opt));
4553         break;
4554 
4555     case PM_DockWidgetTitleBarButtonMargin:
4556         ret = int(QStyleHelper::dpiScaled(2., opt));
4557         break;
4558 
4559     case PM_ButtonDefaultIndicator:
4560         ret = 0;
4561         break;
4562 
4563     case PM_MenuButtonIndicator:
4564         ret = int(QStyleHelper::dpiScaled(12, opt));
4565         break;
4566 
4567     case PM_ButtonShiftHorizontal:
4568     case PM_ButtonShiftVertical:
4569 
4570     case PM_DefaultFrameWidth:
4571         ret = 2;
4572         break;
4573 
4574     case PM_ComboBoxFrameWidth:
4575     case PM_SpinBoxFrameWidth:
4576     case PM_MenuPanelWidth:
4577     case PM_TabBarBaseOverlap:
4578     case PM_TabBarBaseHeight:
4579         ret = proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget);
4580         break;
4581 
4582     case PM_MdiSubWindowFrameWidth:
4583         ret = int(QStyleHelper::dpiScaled(4, opt));
4584         break;
4585 
4586     case PM_MdiSubWindowMinimizedWidth:
4587         ret = int(QStyleHelper::dpiScaled(196, opt));
4588         break;
4589 
4590 #if QT_CONFIG(scrollbar)
4591     case PM_ScrollBarExtent:
4592         if (const QStyleOptionSlider *sb = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
4593             int s = sb->orientation == Qt::Horizontal ?
4594                     QApplication::globalStrut().height()
4595                     : QApplication::globalStrut().width();
4596             ret = qMax(16, s);
4597         } else {
4598             ret = int(QStyleHelper::dpiScaled(16, opt));
4599         }
4600         break;
4601 #endif
4602     case PM_MaximumDragDistance:
4603         ret = QGuiApplicationPrivate::platformTheme()->themeHint(QPlatformTheme::MaximumScrollBarDragDistance).toInt();
4604         break;
4605 
4606 #if QT_CONFIG(slider)
4607     case PM_SliderThickness:
4608         ret = int(QStyleHelper::dpiScaled(16, opt));
4609         break;
4610 
4611     case PM_SliderTickmarkOffset:
4612         if (const QStyleOptionSlider *sl = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
4613             int space = (sl->orientation == Qt::Horizontal) ? sl->rect.height()
4614                                                             : sl->rect.width();
4615             int thickness = proxy()->pixelMetric(PM_SliderControlThickness, sl, widget);
4616             int ticks = sl->tickPosition;
4617 
4618             if (ticks == QSlider::TicksBothSides)
4619                 ret = (space - thickness) / 2;
4620             else if (ticks == QSlider::TicksAbove)
4621                 ret = space - thickness;
4622             else
4623                 ret = 0;
4624         } else {
4625             ret = 0;
4626         }
4627         break;
4628 
4629     case PM_SliderSpaceAvailable:
4630         if (const QStyleOptionSlider *sl = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
4631             if (sl->orientation == Qt::Horizontal)
4632                 ret = sl->rect.width() - proxy()->pixelMetric(PM_SliderLength, sl, widget);
4633             else
4634                 ret = sl->rect.height() - proxy()->pixelMetric(PM_SliderLength, sl, widget);
4635         } else {
4636             ret = 0;
4637         }
4638         break;
4639 #endif // QT_CONFIG(slider)
4640 #if QT_CONFIG(dockwidget)
4641     case PM_DockWidgetSeparatorExtent:
4642         ret = int(QStyleHelper::dpiScaled(6, opt));
4643         break;
4644 
4645     case PM_DockWidgetHandleExtent:
4646         ret = int(QStyleHelper::dpiScaled(8, opt));
4647         break;
4648     case PM_DockWidgetTitleMargin:
4649         ret = 0;
4650         break;
4651     case PM_DockWidgetFrameWidth:
4652         ret = 1;
4653         break;
4654 #endif // QT_CONFIG(dockwidget)
4655 
4656     case PM_SpinBoxSliderHeight:
4657     case PM_MenuBarPanelWidth:
4658         ret = 2;
4659         break;
4660 
4661     case PM_MenuBarItemSpacing:
4662         ret = 0;
4663         break;
4664 
4665 #if QT_CONFIG(toolbar)
4666     case PM_ToolBarFrameWidth:
4667         ret = 1;
4668         break;
4669 
4670     case PM_ToolBarItemMargin:
4671         ret = 0;
4672         break;
4673 
4674     case PM_ToolBarItemSpacing:
4675         ret = int(QStyleHelper::dpiScaled(4, opt));
4676         break;
4677 
4678     case PM_ToolBarHandleExtent:
4679         ret = int(QStyleHelper::dpiScaled(8, opt));
4680         break;
4681 
4682     case PM_ToolBarSeparatorExtent:
4683         ret = int(QStyleHelper::dpiScaled(6, opt));
4684         break;
4685 
4686     case PM_ToolBarExtensionExtent:
4687         ret = int(QStyleHelper::dpiScaled(12, opt));
4688         break;
4689 #endif // QT_CONFIG(toolbar)
4690 
4691 #if QT_CONFIG(tabbar)
4692     case PM_TabBarTabOverlap:
4693         ret = 3;
4694         break;
4695 
4696     case PM_TabBarTabHSpace:
4697         ret = int(QStyleHelper::dpiScaled(24, opt));
4698         break;
4699 
4700     case PM_TabBarTabShiftHorizontal:
4701         ret = 0;
4702         break;
4703 
4704     case PM_TabBarTabShiftVertical:
4705         ret = 2;
4706         break;
4707 
4708     case PM_TabBarTabVSpace: {
4709         const QStyleOptionTab *tb = qstyleoption_cast<const QStyleOptionTab *>(opt);
4710         if (tb && (tb->shape == QTabBar::RoundedNorth || tb->shape == QTabBar::RoundedSouth
4711                    || tb->shape == QTabBar::RoundedWest || tb->shape == QTabBar::RoundedEast))
4712             ret = 8;
4713         else
4714             if(tb && (tb->shape == QTabBar::TriangularWest || tb->shape == QTabBar::TriangularEast))
4715                 ret = 3;
4716             else
4717                 ret = 2;
4718         break; }
4719 #endif
4720 
4721     case PM_ProgressBarChunkWidth:
4722         ret = 9;
4723         break;
4724 
4725     case PM_IndicatorWidth:
4726         ret = int(QStyleHelper::dpiScaled(13, opt));
4727         break;
4728 
4729     case PM_IndicatorHeight:
4730         ret = int(QStyleHelper::dpiScaled(13, opt));
4731         break;
4732 
4733     case PM_ExclusiveIndicatorWidth:
4734         ret = int(QStyleHelper::dpiScaled(12, opt));
4735         break;
4736 
4737     case PM_ExclusiveIndicatorHeight:
4738         ret = int(QStyleHelper::dpiScaled(12, opt));
4739         break;
4740 
4741     case PM_MenuTearoffHeight:
4742         ret = int(QStyleHelper::dpiScaled(10, opt));
4743         break;
4744 
4745     case PM_MenuScrollerHeight:
4746         ret = int(QStyleHelper::dpiScaled(10, opt));
4747         break;
4748 
4749     case PM_MenuDesktopFrameWidth:
4750     case PM_MenuHMargin:
4751     case PM_MenuVMargin:
4752         ret = 0;
4753         break;
4754 
4755     case PM_HeaderMargin:
4756         ret = int(QStyleHelper::dpiScaled(4, opt));
4757         break;
4758     case PM_HeaderMarkSize:
4759         ret = int(QStyleHelper::dpiScaled(16, opt));
4760         break;
4761     case PM_HeaderGripMargin:
4762         ret = int(QStyleHelper::dpiScaled(4, opt));
4763         break;
4764     case PM_HeaderDefaultSectionSizeHorizontal:
4765         ret = int(QStyleHelper::dpiScaled(100, opt));
4766         break;
4767     case PM_HeaderDefaultSectionSizeVertical:
4768         ret = int(QStyleHelper::dpiScaled(30, opt));
4769         break;
4770     case PM_TabBarScrollButtonWidth:
4771         ret = int(QStyleHelper::dpiScaled(16, opt));
4772         break;
4773     case PM_LayoutLeftMargin:
4774     case PM_LayoutTopMargin:
4775     case PM_LayoutRightMargin:
4776     case PM_LayoutBottomMargin:
4777         {
4778             bool isWindow = false;
4779             if (opt) {
4780                 isWindow = (opt->state & State_Window);
4781             } else if (widget) {
4782                 isWindow = widget->isWindow();
4783             }
4784 QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED
4785             ret = proxy()->pixelMetric(isWindow ? PM_DefaultTopLevelMargin : PM_DefaultChildMargin, opt);
4786 QT_WARNING_POP
4787         }
4788         break;
4789     case PM_LayoutHorizontalSpacing:
4790     case PM_LayoutVerticalSpacing:
4791 QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED
4792         ret = proxy()->pixelMetric(PM_DefaultLayoutSpacing, opt);
4793 QT_WARNING_POP
4794         break;
4795 
4796 QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED
4797     case PM_DefaultTopLevelMargin:
4798         ret = int(QStyleHelper::dpiScaled(11, opt));
4799         break;
4800     case PM_DefaultChildMargin:
4801         ret = int(QStyleHelper::dpiScaled(9, opt));
4802         break;
4803     case PM_DefaultLayoutSpacing:
4804         ret = int(QStyleHelper::dpiScaled(6, opt));
4805         break;
4806 QT_WARNING_POP
4807 
4808     case PM_ToolBarIconSize:
4809         ret = 0;
4810         if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme())
4811             ret = theme->themeHint(QPlatformTheme::ToolBarIconSize).toInt();
4812         if (ret <= 0)
4813             ret =  int(QStyleHelper::dpiScaled(24, opt));
4814         break;
4815 
4816     case PM_TabBarIconSize:
4817         ret = proxy()->pixelMetric(PM_SmallIconSize, opt, widget);
4818         break;
4819     case PM_ListViewIconSize:
4820 #if QT_CONFIG(filedialog)
4821         if (qobject_cast<const QSidebar *>(widget))
4822             ret = int(QStyleHelper::dpiScaled(24., opt));
4823         else
4824 #endif
4825             ret = proxy()->pixelMetric(PM_SmallIconSize, opt, widget);
4826         break;
4827 
4828     case PM_ButtonIconSize:
4829     case PM_SmallIconSize:
4830         ret = int(QStyleHelper::dpiScaled(16, opt));
4831         break;
4832     case PM_IconViewIconSize:
4833         ret = proxy()->pixelMetric(PM_LargeIconSize, opt, widget);
4834         break;
4835 
4836     case PM_LargeIconSize:
4837         ret = int(QStyleHelper::dpiScaled(32, opt));
4838         break;
4839 
4840     case PM_ToolTipLabelFrameWidth:
4841         ret = 1;
4842         break;
4843     case PM_CheckBoxLabelSpacing:
4844     case PM_RadioButtonLabelSpacing:
4845         ret = int(QStyleHelper::dpiScaled(6, opt));
4846         break;
4847     case PM_SizeGripSize:
4848         ret = int(QStyleHelper::dpiScaled(13, opt));
4849         break;
4850     case PM_MessageBoxIconSize:
4851 #ifdef Q_OS_MAC
4852         if (QGuiApplication::desktopSettingsAware()) {
4853             ret = 64; // No DPI scaling, it's handled elsewhere.
4854         } else
4855 #endif
4856         {
4857             ret = int(QStyleHelper::dpiScaled(32, opt));
4858         }
4859         break;
4860     case PM_TextCursorWidth:
4861         ret = QGuiApplicationPrivate::platformTheme()->themeHint(QPlatformTheme::TextCursorWidth).toInt();
4862         break;
4863     case PM_TabBar_ScrollButtonOverlap:
4864         ret = 1;
4865         break;
4866     case PM_TabCloseIndicatorWidth:
4867     case PM_TabCloseIndicatorHeight:
4868         ret = int(QStyleHelper::dpiScaled(16, opt));
4869         break;
4870     case PM_ScrollView_ScrollBarSpacing:
4871         ret = 2 * proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget);
4872         break;
4873     case PM_ScrollView_ScrollBarOverlap:
4874         ret = 0;
4875         break;
4876     case PM_SubMenuOverlap:
4877         ret = -proxy()->pixelMetric(QStyle::PM_MenuPanelWidth, opt, widget);
4878         break;
4879     case PM_TreeViewIndentation:
4880         ret = int(QStyleHelper::dpiScaled(20, opt));
4881         break;
4882     default:
4883         ret = 0;
4884         break;
4885     }
4886 
4887     return ret;
4888 }
4889 
4890 /*!
4891     \reimp
4892 */
sizeFromContents(ContentsType ct,const QStyleOption * opt,const QSize & csz,const QWidget * widget) const4893 QSize QCommonStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
4894                                      const QSize &csz, const QWidget *widget) const
4895 {
4896     Q_D(const QCommonStyle);
4897     QSize sz(csz);
4898     switch (ct) {
4899     case CT_PushButton:
4900         if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
4901             int w = csz.width(),
4902                 h = csz.height(),
4903                 bm = proxy()->pixelMetric(PM_ButtonMargin, btn, widget),
4904             fw = proxy()->pixelMetric(PM_DefaultFrameWidth, btn, widget) * 2;
4905             w += bm + fw;
4906             h += bm + fw;
4907             if (btn->features & QStyleOptionButton::AutoDefaultButton){
4908                 int dbw = proxy()->pixelMetric(PM_ButtonDefaultIndicator, btn, widget) * 2;
4909                 w += dbw;
4910                 h += dbw;
4911             }
4912             sz = QSize(w, h);
4913         }
4914         break;
4915     case CT_RadioButton:
4916     case CT_CheckBox:
4917         if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
4918             bool isRadio = (ct == CT_RadioButton);
4919 
4920             int w = proxy()->pixelMetric(isRadio ? PM_ExclusiveIndicatorWidth
4921                                         : PM_IndicatorWidth, btn, widget);
4922             int h = proxy()->pixelMetric(isRadio ? PM_ExclusiveIndicatorHeight
4923                                         : PM_IndicatorHeight, btn, widget);
4924 
4925             int margins = 0;
4926             // we add 4 pixels for label margins
4927             if (!btn->icon.isNull() || !btn->text.isEmpty())
4928                 margins = 4 + proxy()->pixelMetric(isRadio ? PM_RadioButtonLabelSpacing
4929                                                   : PM_CheckBoxLabelSpacing, opt, widget);
4930             sz += QSize(w + margins, 4);
4931             sz.setHeight(qMax(sz.height(), h));
4932         }
4933         break;
4934 #if QT_CONFIG(menu)
4935     case CT_MenuItem:
4936         if (const QStyleOptionMenuItem *mi = qstyleoption_cast<const QStyleOptionMenuItem *>(opt)) {
4937             bool checkable = mi->menuHasCheckableItems;
4938             int maxpmw = mi->maxIconWidth;
4939             int w = sz.width(), h = sz.height();
4940             if (mi->menuItemType == QStyleOptionMenuItem::Separator) {
4941                 w = 10;
4942                 h = 2;
4943             } else {
4944                 h =  mi->fontMetrics.height() + 8;
4945                 if (!mi->icon.isNull()) {
4946                     int iconExtent = proxy()->pixelMetric(PM_SmallIconSize, opt);
4947                     h = qMax(h, mi->icon.actualSize(QSize(iconExtent, iconExtent)).height() + 4);
4948                 }
4949             }
4950             if (mi->text.contains(QLatin1Char('\t')))
4951                 w += 12;
4952             if (maxpmw > 0)
4953                 w += maxpmw + 6;
4954             if (checkable && maxpmw < 20)
4955                 w += 20 - maxpmw;
4956             if (checkable || maxpmw > 0)
4957                 w += 2;
4958             w += 12;
4959             sz = QSize(w, h);
4960         }
4961         break;
4962 #endif // QT_CONFIG(menu)
4963 #if QT_CONFIG(toolbutton)
4964     case CT_ToolButton:
4965         sz = QSize(sz.width() + 6, sz.height() + 5);
4966         break;
4967 #endif // QT_CONFIG(toolbutton)
4968 #if QT_CONFIG(combobox)
4969     case CT_ComboBox:
4970         if (const QStyleOptionComboBox *cmb = qstyleoption_cast<const QStyleOptionComboBox *>(opt)) {
4971             int fw = cmb->frame ? proxy()->pixelMetric(PM_ComboBoxFrameWidth, opt, widget) * 2 : 0;
4972             const int textMargins = 2*(proxy()->pixelMetric(PM_FocusFrameHMargin, opt) + 1);
4973             // QItemDelegate::sizeHint expands the textMargins two times, thus the 2*textMargins...
4974             int other = qMax(23, 2*textMargins + proxy()->pixelMetric(QStyle::PM_ScrollBarExtent, opt, widget));
4975             sz = QSize(sz.width() + fw + other, sz.height() + fw);
4976         }
4977         break;
4978 #endif // QT_CONFIG(combobox)
4979     case CT_HeaderSection:
4980         if (const QStyleOptionHeader *hdr = qstyleoption_cast<const QStyleOptionHeader *>(opt)) {
4981             bool nullIcon = hdr->icon.isNull();
4982             int margin = proxy()->pixelMetric(QStyle::PM_HeaderMargin, hdr, widget);
4983             int iconSize = nullIcon ? 0 : proxy()->pixelMetric(QStyle::PM_SmallIconSize, hdr, widget);
4984             QSize txt = hdr->fontMetrics.size(0, hdr->text);
4985             sz.setHeight(margin + qMax(iconSize, txt.height()) + margin);
4986             sz.setWidth((nullIcon ? 0 : margin) + iconSize
4987                         + (hdr->text.isNull() ? 0 : margin) + txt.width() + margin);
4988             if (hdr->sortIndicator != QStyleOptionHeader::None) {
4989                 int margin = proxy()->pixelMetric(QStyle::PM_HeaderMargin, hdr, widget);
4990                 if (hdr->orientation == Qt::Horizontal)
4991                     sz.rwidth() += sz.height() + margin;
4992                 else
4993                     sz.rheight() += sz.width() + margin;
4994             }
4995         }
4996         break;
4997     case CT_TabWidget:
4998         sz += QSize(4, 4);
4999         break;
5000     case CT_LineEdit:
5001         if (const QStyleOptionFrame *f = qstyleoption_cast<const QStyleOptionFrame *>(opt))
5002             sz += QSize(2*f->lineWidth, 2*f->lineWidth);
5003         break;
5004 #if QT_CONFIG(groupbox)
5005     case CT_GroupBox:
5006         if (const QStyleOptionGroupBox *styleOpt = qstyleoption_cast<const QStyleOptionGroupBox *>(opt))
5007             sz += QSize(styleOpt->features.testFlag(QStyleOptionFrame::Flat) ? 0 : 16, 0);
5008         break;
5009 #endif // QT_CONFIG(groupbox)
5010     case CT_MdiControls:
5011         if (const QStyleOptionComplex *styleOpt = qstyleoption_cast<const QStyleOptionComplex *>(opt)) {
5012             const int buttonSize = proxy()->pixelMetric(PM_TitleBarButtonSize, styleOpt, widget);
5013             int width = 1;
5014             if (styleOpt->subControls & SC_MdiMinButton)
5015                 width += buttonSize + 1;
5016             if (styleOpt->subControls & SC_MdiNormalButton)
5017                 width += buttonSize + 1;
5018             if (styleOpt->subControls & SC_MdiCloseButton)
5019                 width += buttonSize + 1;
5020             sz = QSize(width, buttonSize);
5021         } else {
5022             const int buttonSize = proxy()->pixelMetric(PM_TitleBarButtonSize, opt, widget);
5023             sz = QSize(1 + 3 * (buttonSize + 1), buttonSize);
5024         }
5025         break;
5026 #if QT_CONFIG(itemviews)
5027     case CT_ItemViewItem:
5028         if (const QStyleOptionViewItem *vopt = qstyleoption_cast<const QStyleOptionViewItem *>(opt)) {
5029             QRect decorationRect, displayRect, checkRect;
5030             d->viewItemLayout(vopt, &checkRect, &decorationRect, &displayRect, true);
5031             sz = (decorationRect|displayRect|checkRect).size();
5032             if (decorationRect.isValid() && sz.height() == decorationRect.height())
5033                 sz.rheight() += 2; // Prevent icons from overlapping.
5034                       }
5035         break;
5036 #else
5037         Q_UNUSED(d);
5038 #endif // QT_CONFIG(itemviews)
5039 #if QT_CONFIG(spinbox)
5040     case CT_SpinBox:
5041         if (const QStyleOptionSpinBox *vopt = qstyleoption_cast<const QStyleOptionSpinBox *>(opt)) {
5042             // Add button + frame widths
5043             const qreal dpi = QStyleHelper::dpi(opt);
5044             const bool hasButtons = (vopt->buttonSymbols != QAbstractSpinBox::NoButtons);
5045             const int buttonWidth = hasButtons ? qRound(QStyleHelper::dpiScaled(16, dpi)) : 0;
5046             const int fw = vopt->frame ? proxy()->pixelMetric(PM_SpinBoxFrameWidth, vopt, widget) : 0;
5047             sz += QSize(buttonWidth + 2*fw, 2*fw);
5048         }
5049         break;
5050 #endif
5051     case CT_ScrollBar:
5052     case CT_MenuBar:
5053     case CT_Menu:
5054     case CT_MenuBarItem:
5055     case CT_Slider:
5056     case CT_ProgressBar:
5057     case CT_TabBarTab:
5058         // just return the contentsSize for now
5059         Q_FALLTHROUGH();
5060     default:
5061         break;
5062     }
5063     return sz;
5064 }
5065 
5066 
5067 /*! \reimp */
styleHint(StyleHint sh,const QStyleOption * opt,const QWidget * widget,QStyleHintReturn * hret) const5068 int QCommonStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget *widget,
5069                             QStyleHintReturn *hret) const
5070 {
5071     int ret = 0;
5072 
5073     switch (sh) {
5074     case SH_Menu_KeyboardSearch:
5075         ret = false;
5076         break;
5077     case SH_Slider_AbsoluteSetButtons:
5078         ret = Qt::MiddleButton;
5079         break;
5080     case SH_Slider_PageSetButtons:
5081         ret = Qt::LeftButton;
5082         break;
5083     case SH_ScrollBar_ContextMenu:
5084         ret = true;
5085         break;
5086 #if QT_CONFIG(dialogbuttonbox)
5087     case SH_DialogButtons_DefaultButton:  // This value not used anywhere.
5088         ret = QDialogButtonBox::AcceptRole;
5089         break;
5090 #endif
5091 #if QT_CONFIG(groupbox)
5092     case SH_GroupBox_TextLabelVerticalAlignment:
5093         ret = Qt::AlignVCenter;
5094         break;
5095 
5096     case SH_GroupBox_TextLabelColor:
5097         ret = opt ? int(opt->palette.color(QPalette::Text).rgba()) : 0;
5098         break;
5099 #endif // QT_CONFIG(groupbox)
5100 
5101     case SH_ListViewExpand_SelectMouseType:
5102     case SH_TabBar_SelectMouseType:
5103         ret = QEvent::MouseButtonPress;
5104         break;
5105 
5106 
5107     case SH_TabBar_Alignment:
5108         ret = Qt::AlignLeft;
5109         break;
5110 
5111     case SH_Header_ArrowAlignment:
5112         ret = Qt::AlignRight | Qt::AlignVCenter;
5113         break;
5114 
5115     case SH_TitleBar_AutoRaise:
5116         ret = false;
5117         break;
5118 
5119     case SH_Menu_SubMenuPopupDelay:
5120         ret = 256;
5121         break;
5122 
5123     case SH_Menu_SloppySubMenus:
5124         ret = true;
5125         break;
5126 
5127     case SH_Menu_SubMenuUniDirection:
5128         ret = false;
5129         break;
5130     case SH_Menu_SubMenuUniDirectionFailCount:
5131         ret = 1;
5132         break;
5133     case SH_Menu_SubMenuSloppySelectOtherActions:
5134         ret = true;
5135         break;
5136     case SH_Menu_SubMenuSloppyCloseTimeout:
5137         ret = 1000;
5138         break;
5139     case SH_Menu_SubMenuResetWhenReenteringParent:
5140         ret = false;
5141         break;
5142     case SH_Menu_SubMenuDontStartSloppyOnLeave:
5143         ret = false;
5144         break;
5145 
5146     case SH_ProgressDialog_TextLabelAlignment:
5147         ret = Qt::AlignCenter;
5148         break;
5149 
5150     case SH_BlinkCursorWhenTextSelected:
5151 #if defined(Q_OS_DARWIN)
5152         ret = 0;
5153 #else
5154         ret = 1;
5155 #endif
5156         break;
5157 
5158     case SH_Table_GridLineColor:
5159         if (opt)
5160             ret = opt->palette.color(QPalette::Mid).rgba();
5161         else
5162             ret = -1;
5163         break;
5164     case SH_LineEdit_PasswordCharacter: {
5165         const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme();
5166         const QPlatformTheme::ThemeHint hintType = QPlatformTheme::PasswordMaskCharacter;
5167         const QVariant hint = theme ? theme->themeHint(hintType) : QPlatformTheme::defaultThemeHint(hintType);
5168         ret = hint.toChar().unicode();
5169         break;
5170     }
5171     case SH_LineEdit_PasswordMaskDelay:
5172         ret = QGuiApplicationPrivate::platformTheme()->themeHint(QPlatformTheme::PasswordMaskDelay).toInt();
5173         break;
5174     case SH_ToolBox_SelectedPageTitleBold:
5175         ret = 1;
5176         break;
5177 
5178     case SH_UnderlineShortcut:
5179         ret = 1;
5180         break;
5181 
5182     case SH_SpinBox_ClickAutoRepeatRate:
5183         ret = 150;
5184         break;
5185 
5186     case SH_SpinBox_ClickAutoRepeatThreshold:
5187         ret = 500;
5188         break;
5189 
5190     case SH_SpinBox_KeyPressAutoRepeatRate:
5191         ret = 75;
5192         break;
5193 
5194     case SH_Menu_SelectionWrap:
5195         ret = true;
5196         break;
5197 
5198     case SH_Menu_FillScreenWithScroll:
5199         ret = true;
5200         break;
5201 
5202     case SH_ToolTipLabel_Opacity:
5203         ret = 255;
5204         break;
5205 
5206     case SH_Button_FocusPolicy:
5207         ret = Qt::StrongFocus;
5208         break;
5209 
5210     case SH_MessageBox_UseBorderForButtonSpacing:
5211         ret = 0;
5212         break;
5213 
5214     case SH_ToolButton_PopupDelay:
5215         ret = 600;
5216         break;
5217 
5218     case SH_FocusFrame_Mask:
5219         ret = 1;
5220         if (widget) {
5221             if(QStyleHintReturnMask *mask = qstyleoption_cast<QStyleHintReturnMask*>(hret)) {
5222                 mask->region = widget->rect();
5223                 const int vmargin = proxy()->pixelMetric(QStyle::PM_FocusFrameVMargin, opt);
5224                 const int hmargin = proxy()->pixelMetric(QStyle::PM_FocusFrameHMargin, opt);
5225                 mask->region -= QRect(widget->rect().adjusted(hmargin, vmargin, -hmargin, -vmargin));
5226             }
5227         }
5228         break;
5229 #if QT_CONFIG(rubberband)
5230     case SH_RubberBand_Mask:
5231         if (const QStyleOptionRubberBand *rbOpt = qstyleoption_cast<const QStyleOptionRubberBand *>(opt)) {
5232             ret = 0;
5233             if (rbOpt->shape == QRubberBand::Rectangle) {
5234                 ret = true;
5235                 if(QStyleHintReturnMask *mask = qstyleoption_cast<QStyleHintReturnMask*>(hret)) {
5236                     mask->region = opt->rect;
5237                     const int margin = proxy()->pixelMetric(PM_DefaultFrameWidth, opt) * 2;
5238                     mask->region -= opt->rect.adjusted(margin, margin, -margin, -margin);
5239                 }
5240             }
5241         }
5242         break;
5243 #endif // QT_CONFIG(rubberband)
5244     case SH_SpinControls_DisableOnBounds:
5245         ret = 1;
5246         break;
5247 
5248     case SH_Dial_BackgroundRole:
5249         ret = QPalette::Window;
5250         break;
5251 
5252     case SH_ComboBox_LayoutDirection:
5253         ret = opt ? opt->direction : Qt::LeftToRight;
5254         break;
5255 
5256     case SH_ItemView_EllipsisLocation:
5257         ret = Qt::AlignTrailing;
5258         break;
5259 
5260     case SH_ItemView_ShowDecorationSelected:
5261         ret = false;
5262         break;
5263 
5264     case SH_ItemView_ActivateItemOnSingleClick:
5265         ret = 0;
5266         if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme())
5267             ret = theme->themeHint(QPlatformTheme::ItemViewActivateItemOnSingleClick).toBool() ? 1 : 0;
5268         break;
5269     case SH_TitleBar_ModifyNotification:
5270         ret = true;
5271         break;
5272     case SH_ScrollBar_RollBetweenButtons:
5273         ret = false;
5274         break;
5275     case SH_TabBar_ElideMode:
5276         ret = Qt::ElideNone;
5277         break;
5278 #if QT_CONFIG(dialogbuttonbox)
5279     case SH_DialogButtonLayout:
5280         ret = QDialogButtonBox::WinLayout;
5281         if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme())
5282             ret = theme->themeHint(QPlatformTheme::DialogButtonBoxLayout).toInt();
5283         break;
5284 #endif
5285     case SH_ComboBox_PopupFrameStyle:
5286         ret = QFrame::StyledPanel | QFrame::Plain;
5287         break;
5288     case SH_MessageBox_TextInteractionFlags:
5289         ret = Qt::LinksAccessibleByMouse;
5290         break;
5291     case SH_DialogButtonBox_ButtonsHaveIcons:
5292         ret = 0;
5293         if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme())
5294             ret = theme->themeHint(QPlatformTheme::DialogButtonBoxButtonsHaveIcons).toBool() ? 1 : 0;
5295         break;
5296     case SH_SpellCheckUnderlineStyle:
5297         ret = QTextCharFormat::WaveUnderline;
5298         break;
5299     case SH_MessageBox_CenterButtons:
5300         ret = true;
5301         break;
5302     case SH_ItemView_MovementWithoutUpdatingSelection:
5303         ret = true;
5304         break;
5305     case SH_FocusFrame_AboveWidget:
5306         ret = false;
5307         break;
5308 #if QT_CONFIG(tabwidget)
5309     case SH_TabWidget_DefaultTabPosition:
5310         ret = QTabWidget::North;
5311         break;
5312 #endif
5313     case SH_ToolBar_Movable:
5314         ret = true;
5315         break;
5316     case SH_TextControl_FocusIndicatorTextCharFormat:
5317         ret = true;
5318         if (QStyleHintReturnVariant *vret = qstyleoption_cast<QStyleHintReturnVariant*>(hret)) {
5319             QPen outline(opt->palette.color(QPalette::Text), 1, Qt::DotLine);
5320             QTextCharFormat fmt;
5321             fmt.setProperty(QTextFormat::OutlinePen, outline);
5322             vret->variant = fmt;
5323         }
5324         break;
5325 #if QT_CONFIG(wizard)
5326     case SH_WizardStyle:
5327         ret = QWizard::ClassicStyle;
5328         break;
5329 #endif
5330 #if QT_CONFIG(formlayout)
5331     case SH_FormLayoutWrapPolicy:
5332         ret = QFormLayout::DontWrapRows;
5333         break;
5334     case SH_FormLayoutFieldGrowthPolicy:
5335         ret = QFormLayout::AllNonFixedFieldsGrow;
5336         break;
5337 #endif
5338     case SH_FormLayoutFormAlignment:
5339         ret = Qt::AlignLeft | Qt::AlignTop;
5340         break;
5341     case SH_FormLayoutLabelAlignment:
5342         ret = Qt::AlignLeft;
5343         break;
5344     case SH_ItemView_ArrowKeysNavigateIntoChildren:
5345         ret = false;
5346         break;
5347     case SH_ItemView_DrawDelegateFrame:
5348         ret = 0;
5349         break;
5350 #if QT_CONFIG(tabbar)
5351     case SH_TabBar_CloseButtonPosition:
5352         ret = QTabBar::RightSide;
5353         break;
5354     case SH_TabBar_ChangeCurrentDelay:
5355         ret = 500;
5356         break;
5357 #endif
5358     case SH_DockWidget_ButtonsHaveFrame:
5359         ret = true;
5360         break;
5361     case SH_ToolButtonStyle:
5362         ret = 0;
5363         if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme())
5364             ret = theme->themeHint(QPlatformTheme::ToolButtonStyle).toInt();
5365         break;
5366     case SH_RequestSoftwareInputPanel:
5367         ret = RSIP_OnMouseClick;
5368         break;
5369     case SH_ScrollBar_Transient:
5370         ret = false;
5371         break;
5372     case SH_Menu_SupportsSections:
5373         ret = false;
5374         break;
5375 #ifndef QT_NO_TOOLTIP
5376     case SH_ToolTip_WakeUpDelay:
5377         ret = 700;
5378         break;
5379     case SH_ToolTip_FallAsleepDelay:
5380         ret = 2000;
5381         break;
5382 #endif
5383     case SH_Widget_Animate:
5384     // TODO Qt6: move this code in the SH_Widget_Animation_Duration case
5385     // and replace false with 0 and true with 200.
5386 #if QT_CONFIG(treeview)
5387         if (qobject_cast<const QTreeView*>(widget)) {
5388             ret = false;
5389         } else
5390 #endif
5391             {
5392             ret = true;
5393         }
5394         break;
5395     case SH_Splitter_OpaqueResize:
5396         ret = true;
5397         break;
5398 #if QT_CONFIG(itemviews)
5399     case SH_ItemView_ScrollMode:
5400         ret = QAbstractItemView::ScrollPerItem;
5401         break;
5402 #endif
5403     case SH_TitleBar_ShowToolTipsOnButtons:
5404         ret = true;
5405         break;
5406     case SH_Widget_Animation_Duration:
5407         ret = styleHint(SH_Widget_Animate, opt, widget, hret) ? 200 : 0;
5408         break;
5409     case SH_ComboBox_AllowWheelScrolling:
5410         ret = true;
5411         break;
5412     case SH_SpinBox_ButtonsInsideFrame:
5413         ret = true;
5414         break;
5415     case SH_SpinBox_StepModifier:
5416         ret = Qt::ControlModifier;
5417         break;
5418     default:
5419         ret = 0;
5420         break;
5421     }
5422 
5423     return ret;
5424 }
5425 
5426 #if QT_CONFIG(imageformat_xpm)
cachedPixmapFromXPM(const char * const * xpm)5427 static QPixmap cachedPixmapFromXPM(const char * const *xpm)
5428 {
5429     QPixmap result;
5430     const QString tag = QString::asprintf("xpm:0x%p", static_cast<const void*>(xpm));
5431     if (!QPixmapCache::find(tag, &result)) {
5432         result = QPixmap(xpm);
5433         QPixmapCache::insert(tag, result);
5434     }
5435     return result;
5436 }
5437 
titleBarMenuCachedPixmapFromXPM()5438 static inline QPixmap titleBarMenuCachedPixmapFromXPM() { return cachedPixmapFromXPM(qt_menu_xpm); }
5439 #endif // QT_CONFIG(imageformat_xpm)
5440 
5441 #ifndef QT_NO_IMAGEFORMAT_PNG
clearText16IconPath()5442 static inline QString clearText16IconPath()
5443 {
5444     return QStringLiteral(":/qt-project.org/styles/commonstyle/images/cleartext-16.png");
5445 }
5446 #endif // !QT_NO_IMAGEFORMAT_PNG
5447 
5448 #if defined(Q_OS_WIN) || QT_CONFIG(imageformat_png)
clearTextIcon(bool rtl)5449 static QIcon clearTextIcon(bool rtl)
5450 {
5451     const QString directionalThemeName = rtl
5452         ? QStringLiteral("edit-clear-locationbar-ltr") : QStringLiteral("edit-clear-locationbar-rtl");
5453     if (QIcon::hasThemeIcon(directionalThemeName))
5454         return QIcon::fromTheme(directionalThemeName);
5455     const QString themeName = QStringLiteral("edit-clear");
5456     if (QIcon::hasThemeIcon(themeName))
5457         return QIcon::fromTheme(themeName);
5458 
5459     QIcon icon;
5460 #ifndef QT_NO_IMAGEFORMAT_PNG
5461     QPixmap clearText16(clearText16IconPath());
5462     Q_ASSERT(!clearText16.size().isEmpty());
5463     icon.addPixmap(clearText16);
5464     QPixmap clearText32(QStringLiteral(":/qt-project.org/styles/commonstyle/images/cleartext-32.png"));
5465     Q_ASSERT(!clearText32.size().isEmpty());
5466     icon.addPixmap(clearText32);
5467     clearText32.setDevicePixelRatio(2); // The 32x32 pixmap can also be used for 16x16/devicePixelRatio=2
5468     icon.addPixmap(clearText32);
5469 #endif // !QT_NO_IMAGEFORMAT_PNG
5470     return icon;
5471 }
5472 #endif
5473 
5474 /*! \reimp */
standardPixmap(StandardPixmap sp,const QStyleOption * option,const QWidget * widget) const5475 QPixmap QCommonStyle::standardPixmap(StandardPixmap sp, const QStyleOption *option,
5476                                      const QWidget *widget) const
5477 {
5478     const bool rtl = (option && option->direction == Qt::RightToLeft) || (!option && QGuiApplication::isRightToLeft());
5479 #ifdef QT_NO_IMAGEFORMAT_PNG
5480     Q_UNUSED(widget);
5481     Q_UNUSED(sp);
5482 #else
5483     QPixmap pixmap;
5484 
5485     if (QGuiApplication::desktopSettingsAware() && !QIcon::themeName().isEmpty()) {
5486         switch (sp) {
5487         case SP_DialogYesButton:
5488         case SP_DialogOkButton:
5489             pixmap = QIcon::fromTheme(QLatin1String("dialog-ok")).pixmap(16);
5490             break;
5491         case SP_DialogApplyButton:
5492             pixmap = QIcon::fromTheme(QLatin1String("dialog-ok-apply")).pixmap(16);
5493             break;
5494         case SP_DialogDiscardButton:
5495             pixmap = QIcon::fromTheme(QLatin1String("edit-delete")).pixmap(16);
5496             break;
5497         case SP_DialogCloseButton:
5498             pixmap = QIcon::fromTheme(QLatin1String("dialog-close")).pixmap(16);
5499             break;
5500         case SP_DirHomeIcon:
5501             pixmap = QIcon::fromTheme(QLatin1String("user-home")).pixmap(16);
5502             break;
5503         case SP_MessageBoxInformation:
5504             pixmap = QIcon::fromTheme(QLatin1String("messagebox_info")).pixmap(16);
5505             break;
5506         case SP_MessageBoxWarning:
5507             pixmap = QIcon::fromTheme(QLatin1String("messagebox_warning")).pixmap(16);
5508             break;
5509         case SP_MessageBoxCritical:
5510             pixmap = QIcon::fromTheme(QLatin1String("messagebox_critical")).pixmap(16);
5511             break;
5512         case SP_MessageBoxQuestion:
5513             pixmap = QIcon::fromTheme(QLatin1String("help")).pixmap(16);
5514             break;
5515         case SP_DialogOpenButton:
5516         case SP_DirOpenIcon:
5517             pixmap = QIcon::fromTheme(QLatin1String("folder-open")).pixmap(16);
5518             break;
5519         case SP_FileIcon:
5520             pixmap = QIcon::fromTheme(QLatin1String("text-x-generic"),
5521                                       QIcon::fromTheme(QLatin1String("empty"))).pixmap(16);
5522             break;
5523         case SP_DirClosedIcon:
5524         case SP_DirIcon:
5525                 pixmap = QIcon::fromTheme(QLatin1String("folder")).pixmap(16);
5526                 break;
5527         case SP_DriveFDIcon:
5528                 pixmap = QIcon::fromTheme(QLatin1String("media-floppy"),
5529                                           QIcon::fromTheme(QLatin1String("3floppy_unmount"))).pixmap(16);
5530                 break;
5531         case SP_ComputerIcon:
5532                 pixmap = QIcon::fromTheme(QLatin1String("computer"),
5533                                           QIcon::fromTheme(QLatin1String("system"))).pixmap(16);
5534                 break;
5535         case SP_DesktopIcon:
5536                 pixmap = QIcon::fromTheme(QLatin1String("user-desktop"),
5537                                           QIcon::fromTheme(QLatin1String("desktop"))).pixmap(16);
5538                 break;
5539         case SP_TrashIcon:
5540                 pixmap = QIcon::fromTheme(QLatin1String("user-trash"),
5541                                           QIcon::fromTheme(QLatin1String("trashcan_empty"))).pixmap(16);
5542                 break;
5543         case SP_DriveCDIcon:
5544         case SP_DriveDVDIcon:
5545                 pixmap = QIcon::fromTheme(QLatin1String("media-optical"),
5546                                           QIcon::fromTheme(QLatin1String("cdrom_unmount"))).pixmap(16);
5547                 break;
5548         case SP_DriveHDIcon:
5549                 pixmap = QIcon::fromTheme(QLatin1String("drive-harddisk"),
5550                                           QIcon::fromTheme(QLatin1String("hdd_unmount"))).pixmap(16);
5551                 break;
5552         case SP_FileDialogToParent:
5553                 pixmap = QIcon::fromTheme(QLatin1String("go-up"),
5554                                           QIcon::fromTheme(QLatin1String("up"))).pixmap(16);
5555                 break;
5556         case SP_FileDialogNewFolder:
5557                 pixmap = QIcon::fromTheme(QLatin1String("folder_new")).pixmap(16);
5558                 break;
5559         case SP_ArrowUp:
5560                 pixmap = QIcon::fromTheme(QLatin1String("go-up"),
5561                                           QIcon::fromTheme(QLatin1String("up"))).pixmap(16);
5562                 break;
5563         case SP_ArrowDown:
5564                 pixmap = QIcon::fromTheme(QLatin1String("go-down"),
5565                                           QIcon::fromTheme(QLatin1String("down"))).pixmap(16);
5566                 break;
5567         case SP_ArrowRight:
5568                 pixmap = QIcon::fromTheme(QLatin1String("go-next"),
5569                                           QIcon::fromTheme(QLatin1String("forward"))).pixmap(16);
5570                 break;
5571         case SP_ArrowLeft:
5572                 pixmap = QIcon::fromTheme(QLatin1String("go-previous"),
5573                                           QIcon::fromTheme(QLatin1String("back"))).pixmap(16);
5574                 break;
5575         case SP_FileDialogDetailedView:
5576                 pixmap = QIcon::fromTheme(QLatin1String("view_detailed")).pixmap(16);
5577                 break;
5578         case SP_FileDialogListView:
5579                 pixmap = QIcon::fromTheme(QLatin1String("view_icon")).pixmap(16);
5580                 break;
5581         case SP_BrowserReload:
5582                 pixmap = QIcon::fromTheme(QLatin1String("reload")).pixmap(16);
5583                 break;
5584         case SP_BrowserStop:
5585                 pixmap = QIcon::fromTheme(QLatin1String("process-stop")).pixmap(16);
5586                 break;
5587         case SP_MediaPlay:
5588                 pixmap = QIcon::fromTheme(QLatin1String("media-playback-start")).pixmap(16);
5589                 break;
5590         case SP_MediaPause:
5591                 pixmap = QIcon::fromTheme(QLatin1String("media-playback-pause")).pixmap(16);
5592                 break;
5593         case SP_MediaStop:
5594                 pixmap = QIcon::fromTheme(QLatin1String("media-playback-stop")).pixmap(16);
5595                 break;
5596         case SP_MediaSeekForward:
5597                 pixmap = QIcon::fromTheme(QLatin1String("media-seek-forward")).pixmap(16);
5598                 break;
5599         case SP_MediaSeekBackward:
5600                 pixmap = QIcon::fromTheme(QLatin1String("media-seek-backward")).pixmap(16);
5601                 break;
5602         case SP_MediaSkipForward:
5603                 pixmap = QIcon::fromTheme(QLatin1String("media-skip-forward")).pixmap(16);
5604                 break;
5605         case SP_MediaSkipBackward:
5606                 pixmap = QIcon::fromTheme(QLatin1String("media-skip-backward")).pixmap(16);
5607                 break;
5608         case SP_DialogResetButton:
5609                 pixmap = QIcon::fromTheme(QLatin1String("edit-clear")).pixmap(24);
5610                 break;
5611         case SP_DialogHelpButton:
5612                 pixmap = QIcon::fromTheme(QLatin1String("help-contents")).pixmap(24);
5613                 break;
5614         case SP_DialogNoButton:
5615         case SP_DialogCancelButton:
5616                 pixmap = QIcon::fromTheme(QLatin1String("dialog-cancel"),
5617                                          QIcon::fromTheme(QLatin1String("process-stop"))).pixmap(24);
5618                 break;
5619         case SP_DialogSaveButton:
5620                 pixmap = QIcon::fromTheme(QLatin1String("document-save")).pixmap(24);
5621                 break;
5622         case SP_FileLinkIcon:
5623             pixmap = QIcon::fromTheme(QLatin1String("emblem-symbolic-link")).pixmap(16);
5624             if (!pixmap.isNull()) {
5625                 QPixmap fileIcon = QIcon::fromTheme(QLatin1String("text-x-generic")).pixmap(16);
5626                 if (fileIcon.isNull())
5627                     fileIcon = QIcon::fromTheme(QLatin1String("empty")).pixmap(16);
5628                 if (!fileIcon.isNull()) {
5629                     QPainter painter(&fileIcon);
5630                     painter.drawPixmap(0, 0, 16, 16, pixmap);
5631                     return fileIcon;
5632                 }
5633             }
5634             break;
5635         case SP_DirLinkIcon:
5636                 pixmap = QIcon::fromTheme(QLatin1String("emblem-symbolic-link")).pixmap(16);
5637                 if (!pixmap.isNull()) {
5638                     QPixmap dirIcon = QIcon::fromTheme(QLatin1String("folder")).pixmap(16);
5639                     if (!dirIcon.isNull()) {
5640                         QPainter painter(&dirIcon);
5641                         painter.drawPixmap(0, 0, 16, 16, pixmap);
5642                         return dirIcon;
5643                     }
5644                 }
5645                 break;
5646         case SP_LineEditClearButton:
5647             pixmap = clearTextIcon(rtl).pixmap(16);
5648             break;
5649         default:
5650             break;
5651         }
5652     }
5653 
5654     if (!pixmap.isNull())
5655         return pixmap;
5656 #endif //QT_NO_IMAGEFORMAT_PNG
5657     switch (sp) {
5658 #ifndef QT_NO_IMAGEFORMAT_XPM
5659     case SP_ToolBarHorizontalExtensionButton:
5660         if (rtl) {
5661             QImage im(tb_extension_arrow_h_xpm);
5662             im = im.convertToFormat(QImage::Format_ARGB32).mirrored(true, false);
5663             return QPixmap::fromImage(im);
5664         }
5665         return cachedPixmapFromXPM(tb_extension_arrow_h_xpm);
5666     case SP_ToolBarVerticalExtensionButton:
5667         return cachedPixmapFromXPM(tb_extension_arrow_v_xpm);
5668     case SP_FileDialogStart:
5669         return cachedPixmapFromXPM(filedialog_start_xpm);
5670     case SP_FileDialogEnd:
5671         return cachedPixmapFromXPM(filedialog_end_xpm);
5672 #endif
5673 #ifndef QT_NO_IMAGEFORMAT_PNG
5674     case SP_CommandLink:
5675     case SP_ArrowForward:
5676         if (rtl)
5677             return proxy()->standardPixmap(SP_ArrowLeft, option, widget);
5678         return proxy()->standardPixmap(SP_ArrowRight, option, widget);
5679     case SP_ArrowBack:
5680         if (rtl)
5681             return proxy()->standardPixmap(SP_ArrowRight, option, widget);
5682         return proxy()->standardPixmap(SP_ArrowLeft, option, widget);
5683     case SP_ArrowLeft:
5684         return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/left-16.png"));
5685     case SP_ArrowRight:
5686         return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/right-16.png"));
5687     case SP_ArrowUp:
5688         return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/up-16.png"));
5689     case SP_ArrowDown:
5690         return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/down-16.png"));
5691     case SP_FileDialogToParent:
5692         return proxy()->standardPixmap(SP_ArrowUp, option, widget);
5693     case SP_FileDialogNewFolder:
5694         return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/newdirectory-16.png"));
5695     case SP_FileDialogDetailedView:
5696         return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/viewdetailed-16.png"));
5697     case SP_FileDialogInfoView:
5698         return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/fileinfo-16.png"));
5699     case SP_FileDialogContentsView:
5700         return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/filecontents-16.png"));
5701     case SP_FileDialogListView:
5702         return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/viewlist-16.png"));
5703     case SP_FileDialogBack:
5704         return proxy()->standardPixmap(SP_ArrowBack, option, widget);
5705     case SP_DriveHDIcon:
5706         return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/harddrive-16.png"));
5707     case SP_TrashIcon:
5708         return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/trash-16.png"));
5709     case SP_DriveFDIcon:
5710         return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/floppy-16.png"));
5711     case SP_DriveNetIcon:
5712         return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/networkdrive-16.png"));
5713     case SP_DesktopIcon:
5714         return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/desktop-16.png"));
5715     case SP_ComputerIcon:
5716         return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/computer-16.png"));
5717     case SP_DriveCDIcon:
5718         return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/cdr-16.png"));
5719     case SP_DriveDVDIcon:
5720         return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/dvd-16.png"));
5721     case SP_DirHomeIcon:
5722     case SP_DirOpenIcon:
5723         return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/diropen-16.png"));
5724     case SP_DirIcon:
5725     case SP_DirClosedIcon:
5726         return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/dirclosed-16.png"));
5727     case SP_DirLinkIcon:
5728         return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/dirlink-16.png"));
5729     case SP_FileIcon:
5730         return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/file-16.png"));
5731     case SP_FileLinkIcon:
5732         return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/filelink-16.png"));
5733     case SP_DialogOkButton:
5734         return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-ok-16.png"));
5735     case SP_DialogCancelButton:
5736         return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-cancel-16.png"));
5737     case SP_DialogHelpButton:
5738         return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-help-16.png"));
5739     case SP_DialogOpenButton:
5740         return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-open-16.png"));
5741     case SP_DialogSaveButton:
5742         return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-save-16.png"));
5743     case SP_DialogCloseButton:
5744         return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-close-16.png"));
5745     case SP_DialogApplyButton:
5746         return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-apply-16.png"));
5747     case SP_DialogResetButton:
5748         return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-clear-16.png"));
5749     case SP_DialogDiscardButton:
5750         return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-delete-16.png"));
5751     case SP_DialogYesButton:
5752         return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-yes-16.png"));
5753     case SP_DialogNoButton:
5754         return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-no-16.png"));
5755     case SP_BrowserReload:
5756         return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/refresh-24.png"));
5757     case SP_BrowserStop:
5758         return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/stop-24.png"));
5759     case SP_MediaPlay:
5760         return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/media-play-32.png"));
5761     case SP_MediaPause:
5762         return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/media-pause-32.png"));
5763     case SP_MediaStop:
5764         return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/media-stop-32.png"));
5765     case SP_MediaSeekForward:
5766         return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/media-seek-forward-32.png"));
5767     case SP_MediaSeekBackward:
5768         return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/media-seek-backward-32.png"));
5769     case SP_MediaSkipForward:
5770         return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/media-skip-forward-32.png"));
5771     case SP_MediaSkipBackward:
5772         return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/media-skip-backward-32.png"));
5773     case SP_MediaVolume:
5774         return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/media-volume-16.png"));
5775     case SP_MediaVolumeMuted:
5776         return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/media-volume-muted-16.png"));
5777     case SP_LineEditClearButton:
5778         return QPixmap(clearText16IconPath());
5779 #endif // QT_NO_IMAGEFORMAT_PNG
5780     default:
5781         break;
5782     }
5783 
5784 #ifndef QT_NO_IMAGEFORMAT_XPM
5785     switch (sp) {
5786     case SP_TitleBarMenuButton:
5787         return titleBarMenuCachedPixmapFromXPM();
5788     case SP_TitleBarShadeButton:
5789         return cachedPixmapFromXPM(qt_shade_xpm);
5790     case SP_TitleBarUnshadeButton:
5791         return cachedPixmapFromXPM(qt_unshade_xpm);
5792     case SP_TitleBarNormalButton:
5793         return cachedPixmapFromXPM(qt_normalizeup_xpm);
5794     case SP_TitleBarMinButton:
5795         return cachedPixmapFromXPM(qt_minimize_xpm);
5796     case SP_TitleBarMaxButton:
5797         return cachedPixmapFromXPM(qt_maximize_xpm);
5798     case SP_TitleBarCloseButton:
5799         return cachedPixmapFromXPM(qt_close_xpm);
5800     case SP_TitleBarContextHelpButton:
5801         return cachedPixmapFromXPM(qt_help_xpm);
5802     case SP_DockWidgetCloseButton:
5803         return cachedPixmapFromXPM(dock_widget_close_xpm);
5804     case SP_MessageBoxInformation:
5805         return cachedPixmapFromXPM(information_xpm);
5806     case SP_MessageBoxWarning:
5807         return cachedPixmapFromXPM(warning_xpm);
5808     case SP_MessageBoxCritical:
5809         return cachedPixmapFromXPM(critical_xpm);
5810     case SP_MessageBoxQuestion:
5811         return cachedPixmapFromXPM(question_xpm);
5812     default:
5813         break;
5814     }
5815 #endif //QT_NO_IMAGEFORMAT_XPM
5816 
5817 #if !QT_CONFIG(imageformat_png) && !QT_CONFIG(imageformat_xpm) && !QT_CONFIG(imageformat_png)
5818     Q_UNUSED(rtl);
5819 #endif
5820 
5821     return QPixmap();
5822 }
5823 
5824 #if QT_CONFIG(imageformat_png)
iconResourcePrefix()5825 static inline QString iconResourcePrefix() { return QStringLiteral(":/qt-project.org/styles/commonstyle/images/"); }
iconPngSuffix()5826 static inline QString iconPngSuffix() { return QStringLiteral(".png"); }
5827 
addIconFiles(const QString & prefix,const int sizes[],size_t count,QIcon & icon)5828 static void addIconFiles(const QString &prefix, const int sizes[], size_t count, QIcon &icon)
5829 {
5830     for (size_t i = 0; i < count; ++i)
5831         icon.addFile(prefix + QString::number(sizes[i]) + iconPngSuffix());
5832 }
5833 
5834 static const int dockTitleIconSizes[] = {10, 16, 20, 32, 48, 64};
5835 static const int titleBarSizes[] = {16, 32, 48};
5836 static const int toolBarExtHSizes[] = {8, 16, 32};
5837 static const int toolBarExtVSizes[] = {5, 10, 20};
5838 #endif // imageformat_png
5839 
5840 /*!
5841     \internal
5842 */
standardIcon(StandardPixmap standardIcon,const QStyleOption * option,const QWidget * widget) const5843 QIcon QCommonStyle::standardIcon(StandardPixmap standardIcon, const QStyleOption *option,
5844                                  const QWidget *widget) const
5845 {
5846     QIcon icon;
5847     const bool rtl = (option && option->direction == Qt::RightToLeft) || (!option && QGuiApplication::isRightToLeft());
5848 
5849 #ifdef Q_OS_WIN
5850     switch (standardIcon) {
5851     case SP_DriveCDIcon:
5852     case SP_DriveDVDIcon:
5853     case SP_DriveNetIcon:
5854     case SP_DriveHDIcon:
5855     case SP_DriveFDIcon:
5856     case SP_FileIcon:
5857     case SP_FileLinkIcon:
5858     case SP_DesktopIcon:
5859     case SP_ComputerIcon:
5860     case SP_VistaShield:
5861     case SP_MessageBoxInformation:
5862     case SP_MessageBoxWarning:
5863     case SP_MessageBoxCritical:
5864     case SP_MessageBoxQuestion:
5865         if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) {
5866             QPlatformTheme::StandardPixmap sp = static_cast<QPlatformTheme::StandardPixmap>(standardIcon);
5867             for (int size = 16 ; size <= 32 ; size += 16) {
5868                 QPixmap pixmap = theme->standardPixmap(sp, QSizeF(size, size));
5869                 icon.addPixmap(pixmap, QIcon::Normal);
5870             }
5871         }
5872         break;
5873     case SP_DirIcon:
5874     case SP_DirLinkIcon:
5875         if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) {
5876             QPlatformTheme::StandardPixmap spOff = static_cast<QPlatformTheme::StandardPixmap>(standardIcon);
5877             QPlatformTheme::StandardPixmap spOn = standardIcon == SP_DirIcon ? QPlatformTheme::DirOpenIcon :
5878                                                                                  QPlatformTheme::DirLinkOpenIcon;
5879             for (int size = 16 ; size <= 32 ; size += 16) {
5880                 QSizeF pixSize(size, size);
5881                 QPixmap pixmap = theme->standardPixmap(spOff, pixSize);
5882                 icon.addPixmap(pixmap, QIcon::Normal, QIcon::Off);
5883                 pixmap = theme->standardPixmap(spOn, pixSize);
5884                 icon.addPixmap(pixmap, QIcon::Normal, QIcon::On);
5885             }
5886         }
5887         break;
5888     case SP_LineEditClearButton:
5889         icon = clearTextIcon(rtl);
5890         break;
5891     default:
5892         break;
5893     }
5894     if (!icon.isNull())
5895         return icon;
5896 
5897 #endif
5898 
5899     if (QGuiApplication::desktopSettingsAware() && !QIcon::themeName().isEmpty()) {
5900         switch (standardIcon) {
5901         case SP_DirHomeIcon:
5902                 icon = QIcon::fromTheme(QLatin1String("user-home"));
5903                 break;
5904         case SP_MessageBoxInformation:
5905                 icon = QIcon::fromTheme(QLatin1String("dialog-information"));
5906                 break;
5907         case SP_MessageBoxWarning:
5908                 icon = QIcon::fromTheme(QLatin1String("dialog-warning"));
5909                 break;
5910         case SP_MessageBoxCritical:
5911                 icon = QIcon::fromTheme(QLatin1String("dialog-error"));
5912                 break;
5913         case SP_MessageBoxQuestion:
5914                 icon = QIcon::fromTheme(QLatin1String("dialog-question"));
5915                 break;
5916         case SP_DialogOpenButton:
5917         case SP_DirOpenIcon:
5918                 icon = QIcon::fromTheme(QLatin1String("folder-open"));
5919                 break;
5920         case SP_DialogSaveButton:
5921                 icon = QIcon::fromTheme(QLatin1String("document-save"));
5922                 break;
5923         case SP_DialogApplyButton:
5924                 icon = QIcon::fromTheme(QLatin1String("dialog-ok-apply"));
5925                 break;
5926         case SP_DialogYesButton:
5927         case SP_DialogOkButton:
5928                 icon = QIcon::fromTheme(QLatin1String("dialog-ok"));
5929                 break;
5930         case SP_DialogDiscardButton:
5931                 icon = QIcon::fromTheme(QLatin1String("edit-delete"));
5932                 break;
5933         case SP_DialogResetButton:
5934                 icon = QIcon::fromTheme(QLatin1String("edit-clear"));
5935                 break;
5936         case SP_DialogHelpButton:
5937                 icon = QIcon::fromTheme(QLatin1String("help-contents"));
5938                 break;
5939         case SP_FileIcon:
5940                 icon = QIcon::fromTheme(QLatin1String("text-x-generic"));
5941                 break;
5942         case SP_DirClosedIcon:
5943         case SP_DirIcon:
5944                 icon = QIcon::fromTheme(QLatin1String("folder"));
5945                 break;
5946         case SP_DriveFDIcon:
5947                 icon = QIcon::fromTheme(QLatin1String("floppy_unmount"));
5948                 break;
5949         case SP_ComputerIcon:
5950                 icon = QIcon::fromTheme(QLatin1String("computer"),
5951                                         QIcon::fromTheme(QLatin1String("system")));
5952                 break;
5953         case SP_DesktopIcon:
5954                 icon = QIcon::fromTheme(QLatin1String("user-desktop"));
5955                 break;
5956         case SP_TrashIcon:
5957                 icon = QIcon::fromTheme(QLatin1String("user-trash"));
5958                 break;
5959         case SP_DriveCDIcon:
5960         case SP_DriveDVDIcon:
5961                 icon = QIcon::fromTheme(QLatin1String("media-optical"));
5962                 break;
5963         case SP_DriveHDIcon:
5964                 icon = QIcon::fromTheme(QLatin1String("drive-harddisk"));
5965                 break;
5966         case SP_FileDialogToParent:
5967                 icon = QIcon::fromTheme(QLatin1String("go-up"));
5968                 break;
5969         case SP_FileDialogNewFolder:
5970                 icon = QIcon::fromTheme(QLatin1String("folder-new"));
5971                 break;
5972         case SP_ArrowUp:
5973                 icon = QIcon::fromTheme(QLatin1String("go-up"));
5974                 break;
5975         case SP_ArrowDown:
5976                 icon = QIcon::fromTheme(QLatin1String("go-down"));
5977                 break;
5978         case SP_ArrowRight:
5979                 icon = QIcon::fromTheme(QLatin1String("go-next"));
5980                 break;
5981         case SP_ArrowLeft:
5982                 icon = QIcon::fromTheme(QLatin1String("go-previous"));
5983                 break;
5984         case SP_DialogNoButton:
5985         case SP_DialogCancelButton:
5986                 icon = QIcon::fromTheme(QLatin1String("dialog-cancel"),
5987                                         QIcon::fromTheme(QLatin1String("process-stop")));
5988                 break;
5989         case SP_DialogCloseButton:
5990                 icon = QIcon::fromTheme(QLatin1String("window-close"));
5991                 break;
5992         case SP_FileDialogDetailedView:
5993                 icon = QIcon::fromTheme(QLatin1String("view-list-details"));
5994                 break;
5995         case SP_FileDialogListView:
5996                 icon = QIcon::fromTheme(QLatin1String("view-list-icons"));
5997                 break;
5998         case SP_BrowserReload:
5999                 icon = QIcon::fromTheme(QLatin1String("view-refresh"));
6000                 break;
6001         case SP_BrowserStop:
6002                 icon = QIcon::fromTheme(QLatin1String("process-stop"));
6003                 break;
6004         case SP_MediaPlay:
6005                 icon = QIcon::fromTheme(QLatin1String("media-playback-start"));
6006                 break;
6007         case SP_MediaPause:
6008                 icon = QIcon::fromTheme(QLatin1String("media-playback-pause"));
6009                 break;
6010         case SP_MediaStop:
6011                 icon = QIcon::fromTheme(QLatin1String("media-playback-stop"));
6012                 break;
6013         case SP_MediaSeekForward:
6014                 icon = QIcon::fromTheme(QLatin1String("media-seek-forward"));
6015                 break;
6016         case SP_MediaSeekBackward:
6017                 icon = QIcon::fromTheme(QLatin1String("media-seek-backward"));
6018                 break;
6019         case SP_MediaSkipForward:
6020                 icon = QIcon::fromTheme(QLatin1String("media-skip-forward"));
6021                 break;
6022         case SP_MediaSkipBackward:
6023                 icon = QIcon::fromTheme(QLatin1String("media-skip-backward"));
6024                 break;
6025         case SP_MediaVolume:
6026                 icon = QIcon::fromTheme(QLatin1String("audio-volume-medium"));
6027                 break;
6028         case SP_MediaVolumeMuted:
6029                 icon = QIcon::fromTheme(QLatin1String("audio-volume-muted"));
6030                 break;
6031         case SP_ArrowForward:
6032             if (rtl)
6033                 return QCommonStyle::standardIcon(SP_ArrowLeft, option, widget);
6034             return QCommonStyle::standardIcon(SP_ArrowRight, option, widget);
6035         case SP_ArrowBack:
6036             if (rtl)
6037                 return QCommonStyle::standardIcon(SP_ArrowRight, option, widget);
6038             return QCommonStyle::standardIcon(SP_ArrowLeft, option, widget);
6039         case SP_FileLinkIcon:
6040             {
6041                 QIcon linkIcon = QIcon::fromTheme(QLatin1String("emblem-symbolic-link"));
6042                 if (!linkIcon.isNull()) {
6043                     QIcon baseIcon = QCommonStyle::standardIcon(SP_FileIcon, option, widget);
6044                     const QList<QSize> sizes = baseIcon.availableSizes(QIcon::Normal, QIcon::Off);
6045                     for (int i = 0 ; i < sizes.size() ; ++i) {
6046                         int size = sizes[i].width();
6047                         QPixmap basePixmap = baseIcon.pixmap(qt_getWindow(widget), QSize(size, size));
6048                         QPixmap linkPixmap = linkIcon.pixmap(qt_getWindow(widget), QSize(size / 2, size / 2));
6049                         QPainter painter(&basePixmap);
6050                         painter.drawPixmap(size/2, size/2, linkPixmap);
6051                         icon.addPixmap(basePixmap);
6052                     }
6053                 }
6054             }
6055             break;
6056         case SP_DirLinkIcon:
6057             {
6058                 QIcon linkIcon = QIcon::fromTheme(QLatin1String("emblem-symbolic-link"));
6059                 if (!linkIcon.isNull()) {
6060                     QIcon baseIcon = QCommonStyle::standardIcon(SP_DirIcon, option, widget);
6061                     const QList<QSize> sizes = baseIcon.availableSizes(QIcon::Normal, QIcon::Off);
6062                     for (int i = 0 ; i < sizes.size() ; ++i) {
6063                         int size = sizes[i].width();
6064                         QPixmap basePixmap = baseIcon.pixmap(qt_getWindow(widget), QSize(size, size));
6065                         QPixmap linkPixmap = linkIcon.pixmap(qt_getWindow(widget), QSize(size / 2, size / 2));
6066                         QPainter painter(&basePixmap);
6067                         painter.drawPixmap(size/2, size/2, linkPixmap);
6068                         icon.addPixmap(basePixmap);
6069                     }
6070                 }
6071         }
6072         break;
6073         default:
6074             break;
6075         }
6076     } // if (QGuiApplication::desktopSettingsAware() && !QIcon::themeName().isEmpty())
6077 
6078     if (!icon.isNull())
6079         return icon;
6080 
6081 #if defined(Q_OS_MAC)
6082     if (QGuiApplication::desktopSettingsAware()) {
6083         switch (standardIcon) {
6084         case SP_DirIcon: {
6085             // A rather special case
6086             QIcon closeIcon = QCommonStyle::standardIcon(SP_DirClosedIcon, option, widget);
6087             QIcon openIcon = QCommonStyle::standardIcon(SP_DirOpenIcon, option, widget);
6088             closeIcon.addPixmap(openIcon.pixmap(16, 16), QIcon::Normal, QIcon::On);
6089             closeIcon.addPixmap(openIcon.pixmap(32, 32), QIcon::Normal, QIcon::On);
6090             closeIcon.addPixmap(openIcon.pixmap(64, 64), QIcon::Normal, QIcon::On);
6091             closeIcon.addPixmap(openIcon.pixmap(128, 128), QIcon::Normal, QIcon::On);
6092             return closeIcon;
6093         }
6094 
6095         case SP_TitleBarNormalButton:
6096         case SP_TitleBarCloseButton: {
6097             QIcon titleBarIcon;
6098             if (standardIcon == SP_TitleBarCloseButton) {
6099                 titleBarIcon.addFile(QLatin1String(":/qt-project.org/styles/macstyle/images/closedock-16.png"));
6100                 titleBarIcon.addFile(QLatin1String(":/qt-project.org/styles/macstyle/images/closedock-down-16.png"), QSize(16, 16), QIcon::Normal, QIcon::On);
6101             } else {
6102                 titleBarIcon.addFile(QLatin1String(":/qt-project.org/styles/macstyle/images/dockdock-16.png"));
6103                 titleBarIcon.addFile(QLatin1String(":/qt-project.org/styles/macstyle/images/dockdock-down-16.png"), QSize(16, 16), QIcon::Normal, QIcon::On);
6104             }
6105             return titleBarIcon;
6106         }
6107 
6108         case SP_MessageBoxQuestion:
6109         case SP_MessageBoxInformation:
6110         case SP_MessageBoxWarning:
6111         case SP_MessageBoxCritical:
6112         case SP_DesktopIcon:
6113         case SP_TrashIcon:
6114         case SP_ComputerIcon:
6115         case SP_DriveFDIcon:
6116         case SP_DriveHDIcon:
6117         case SP_DriveCDIcon:
6118         case SP_DriveDVDIcon:
6119         case SP_DriveNetIcon:
6120         case SP_DirOpenIcon:
6121         case SP_DirClosedIcon:
6122         case SP_DirLinkIcon:
6123         case SP_FileLinkIcon:
6124         case SP_FileIcon:
6125             if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) {
6126                 QPlatformTheme::StandardPixmap sp = static_cast<QPlatformTheme::StandardPixmap>(standardIcon);
6127                 QIcon retIcon;
6128                 const QList<QSize> sizes = theme->themeHint(QPlatformTheme::IconPixmapSizes).value<QList<QSize> >();
6129                 for (const QSize &size : sizes) {
6130                     QPixmap mainIcon;
6131                     const QString cacheKey = QLatin1String("qt_mac_constructQIconFromIconRef") + QString::number(standardIcon) + QString::number(size.width());
6132                     if (standardIcon >= QStyle::SP_CustomBase) {
6133                         mainIcon = theme->standardPixmap(sp, QSizeF(size));
6134                     } else if (QPixmapCache::find(cacheKey, &mainIcon) == false) {
6135                         mainIcon = theme->standardPixmap(sp, QSizeF(size));
6136                         QPixmapCache::insert(cacheKey, mainIcon);
6137                     }
6138 
6139                     retIcon.addPixmap(mainIcon);
6140                 }
6141                 if (!retIcon.isNull())
6142                     return retIcon;
6143             }
6144 
6145         default:
6146             break;
6147         }
6148     } // if (QGuiApplication::desktopSettingsAware())
6149 #endif // Q_OS_MAC
6150 
6151     switch (standardIcon) {
6152 #ifndef QT_NO_IMAGEFORMAT_PNG
6153     case SP_TitleBarMinButton:
6154         addIconFiles(iconResourcePrefix() + QStringLiteral("titlebar-min-"),
6155                      titleBarSizes, sizeof(titleBarSizes)/sizeof(titleBarSizes[0]), icon);
6156         break;
6157     case SP_TitleBarMaxButton:
6158         addIconFiles(iconResourcePrefix() + QStringLiteral("titlebar-max-"),
6159                      titleBarSizes, sizeof(titleBarSizes)/sizeof(titleBarSizes[0]), icon);
6160         break;
6161     case SP_TitleBarShadeButton:
6162         addIconFiles(iconResourcePrefix() + QStringLiteral("titlebar-shade-"),
6163                      titleBarSizes, sizeof(titleBarSizes)/sizeof(titleBarSizes[0]), icon);
6164 
6165         break;
6166     case SP_TitleBarUnshadeButton:
6167         addIconFiles(iconResourcePrefix() + QStringLiteral("titlebar-unshade-"),
6168                      titleBarSizes, sizeof(titleBarSizes)/sizeof(titleBarSizes[0]), icon);
6169         break;
6170     case SP_TitleBarContextHelpButton:
6171         addIconFiles(iconResourcePrefix() + QStringLiteral("titlebar-contexthelp-"),
6172                      titleBarSizes, sizeof(titleBarSizes)/sizeof(titleBarSizes[0]), icon);
6173         break;
6174      case SP_FileDialogNewFolder:
6175         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/newdirectory-16.png"), QSize(16, 16));
6176         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/newdirectory-32.png"), QSize(32, 32));
6177         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/newdirectory-128.png"), QSize(128, 128));
6178         break;
6179     case SP_FileDialogBack:
6180         return QCommonStyle::standardIcon(SP_ArrowBack, option, widget);
6181     case SP_FileDialogToParent:
6182         return QCommonStyle::standardIcon(SP_ArrowUp, option, widget);
6183     case SP_FileDialogDetailedView:
6184         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/viewdetailed-16.png"), QSize(16, 16));
6185         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/viewdetailed-32.png"), QSize(32, 32));
6186         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/viewdetailed-128.png"), QSize(128, 128));
6187         break;
6188     case SP_FileDialogInfoView:
6189         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/fileinfo-16.png"), QSize(16, 16));
6190         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/fileinfo-32.png"), QSize(32, 32));
6191         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/fileinfo-128.png"), QSize(128, 128));
6192         break;
6193     case SP_FileDialogContentsView:
6194         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/filecontents-16.png"), QSize(16, 16));
6195         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/filecontents-32.png"), QSize(32, 32));
6196         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/filecontents-128.png"), QSize(128, 128));
6197         break;
6198     case SP_FileDialogListView:
6199         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/viewlist-16.png"), QSize(16, 16));
6200         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/viewlist-32.png"), QSize(32, 32));
6201         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/viewlist-128.png"), QSize(128, 128));
6202         break;
6203     case SP_DialogOkButton:
6204         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-ok-16.png"), QSize(16, 16));
6205         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-ok-32.png"), QSize(32, 32));
6206         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-ok-128.png"), QSize(128, 128));
6207         break;
6208     case SP_DialogCancelButton:
6209         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-cancel-16.png"), QSize(16, 16));
6210         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-cancel-32.png"), QSize(32, 32));
6211         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-cancel-128.png"), QSize(128, 128));
6212         break;
6213     case SP_DialogHelpButton:
6214         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-help-16.png"), QSize(16, 16));
6215         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-help-32.png"), QSize(32, 32));
6216         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-help-128.png"), QSize(128, 128));
6217         break;
6218     case SP_DialogOpenButton:
6219         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-open-16.png"), QSize(16, 16));
6220         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-open-32.png"), QSize(32, 32));
6221         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-open-128.png"), QSize(128, 128));
6222         break;
6223     case SP_DialogSaveButton:
6224         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-save-16.png"), QSize(16, 16));
6225         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-save-32.png"), QSize(32, 32));
6226         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-save-128.png"), QSize(128, 128));
6227         break;
6228     case SP_DialogCloseButton:
6229         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-close-16.png"), QSize(16, 16));
6230         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-close-32.png"), QSize(32, 32));
6231         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-close-128.png"), QSize(128, 128));
6232         break;
6233     case SP_DialogApplyButton:
6234         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-apply-16.png"), QSize(16, 16));
6235         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-apply-32.png"), QSize(32, 32));
6236         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-apply-128.png"), QSize(128, 128));
6237         break;
6238     case SP_DialogResetButton:
6239         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-clear-16.png"), QSize(16, 16));
6240         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-clear-32.png"), QSize(32, 32));
6241         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-clear-128.png"), QSize(128, 128));
6242         break;
6243     case SP_DialogDiscardButton:
6244         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-delete-16.png"), QSize(16, 16));
6245         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-delete-32.png"), QSize(32, 32));
6246         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-delete-128.png"), QSize(128, 128));
6247         break;
6248     case SP_DialogYesButton:
6249         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-yes-16.png"), QSize(16, 16));
6250         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-yes-32.png"), QSize(32, 32));
6251         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-yes-128.png"), QSize(128, 128));
6252         break;
6253     case SP_DialogNoButton:
6254         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-no-16.png"), QSize(16, 16));
6255         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-no-32.png"), QSize(32, 32));
6256         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-no-128.png"), QSize(128, 128));
6257         break;
6258     case SP_ArrowForward:
6259         if (rtl)
6260             return QCommonStyle::standardIcon(SP_ArrowLeft, option, widget);
6261         return QCommonStyle::standardIcon(SP_ArrowRight, option, widget);
6262     case SP_ArrowBack:
6263         if (rtl)
6264             return QCommonStyle::standardIcon(SP_ArrowRight, option, widget);
6265         return QCommonStyle::standardIcon(SP_ArrowLeft, option, widget);
6266     case SP_ArrowLeft:
6267         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/left-16.png"), QSize(16, 16));
6268         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/left-32.png"), QSize(32, 32));
6269         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/left-128.png"), QSize(128, 128));
6270         break;
6271     case SP_ArrowRight:
6272         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/right-16.png"), QSize(16, 16));
6273         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/right-32.png"), QSize(32, 32));
6274         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/right-128.png"), QSize(128, 128));
6275         break;
6276     case SP_ArrowUp:
6277         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/up-16.png"), QSize(16, 16));
6278         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/up-32.png"), QSize(32, 32));
6279         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/up-128.png"), QSize(128, 128));
6280         break;
6281     case SP_ArrowDown:
6282         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/down-16.png"), QSize(16, 16));
6283         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/down-32.png"), QSize(32, 32));
6284         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/down-128.png"), QSize(128, 128));
6285         break;
6286    case SP_DirHomeIcon:
6287    case SP_DirIcon:
6288         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/dirclosed-16.png"),
6289                      QSize(), QIcon::Normal, QIcon::Off);
6290         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/diropen-16.png"),
6291                      QSize(), QIcon::Normal, QIcon::On);
6292         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/dirclosed-32.png"),
6293                      QSize(32, 32), QIcon::Normal, QIcon::Off);
6294         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/diropen-32.png"),
6295                      QSize(32, 32), QIcon::Normal, QIcon::On);
6296         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/dirclosed-128.png"),
6297                      QSize(128, 128), QIcon::Normal, QIcon::Off);
6298         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/diropen-128.png"),
6299                      QSize(128, 128), QIcon::Normal, QIcon::On);
6300         break;
6301     case SP_DriveCDIcon:
6302         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/cdr-16.png"), QSize(16, 16));
6303         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/cdr-32.png"), QSize(32, 32));
6304         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/cdr-128.png"), QSize(128, 128));
6305         break;
6306     case SP_DriveDVDIcon:
6307         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/dvd-16.png"), QSize(16, 16));
6308         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/dvd-32.png"), QSize(32, 32));
6309         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/dvd-128.png"), QSize(128, 128));
6310         break;
6311     case SP_FileIcon:
6312         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/file-16.png"), QSize(16, 16));
6313         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/file-32.png"), QSize(32, 32));
6314         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/file-128.png"), QSize(128, 128));
6315         break;
6316     case SP_FileLinkIcon:
6317         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/filelink-16.png"), QSize(16, 16));
6318         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/filelink-32.png"), QSize(32, 32));
6319         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/filelink-128.png"), QSize(128, 128));
6320         break;
6321     case SP_TrashIcon:
6322         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/trash-16.png"), QSize(16, 16));
6323         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/trash-32.png"), QSize(32, 32));
6324         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/trash-128.png"), QSize(128, 128));
6325         break;
6326     case SP_BrowserReload:
6327         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/refresh-24.png"), QSize(24, 24));
6328         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/refresh-32.png"), QSize(32, 32));
6329         break;
6330     case SP_BrowserStop:
6331         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/stop-24.png"), QSize(24, 24));
6332         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/stop-32.png"), QSize(32, 32));
6333         break;
6334     case SP_MediaPlay:
6335         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/media-play-16.png"), QSize(16, 16));
6336         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/media-play-32.png"), QSize(32, 32));
6337         break;
6338     case SP_MediaPause:
6339         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/media-pause-16.png"), QSize(16, 16));
6340         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/media-pause-32.png"), QSize(32, 32));
6341         break;
6342     case SP_MediaStop:
6343         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/media-stop-16.png"), QSize(16, 16));
6344         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/media-stop-32.png"), QSize(32, 32));
6345         break;
6346     case SP_MediaSeekForward:
6347         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/media-seek-forward-16.png"), QSize(16, 16));
6348         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/media-seek-forward-32.png"), QSize(32, 32));
6349         break;
6350     case SP_MediaSeekBackward:
6351         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/media-seek-backward-16.png"), QSize(16, 16));
6352         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/media-seek-backward-32.png"), QSize(32, 32));
6353         break;
6354     case SP_MediaSkipForward:
6355         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/media-skip-forward-16.png"), QSize(16, 16));
6356         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/media-skip-forward-32.png"), QSize(32, 32));
6357         break;
6358     case SP_MediaSkipBackward:
6359         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/media-skip-backward-16.png"), QSize(16, 16));
6360         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/media-skip-backward-32.png"), QSize(32, 32));
6361         break;
6362     case SP_MediaVolume:
6363         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/media-volume-16.png"), QSize(16, 16));
6364         break;
6365     case SP_MediaVolumeMuted:
6366         icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/media-volume-muted-16.png"), QSize(16, 16));
6367         break;
6368     case SP_TitleBarCloseButton:
6369         addIconFiles(iconResourcePrefix() + QStringLiteral("closedock-"),
6370                      dockTitleIconSizes, sizeof(dockTitleIconSizes)/sizeof(dockTitleIconSizes[0]), icon);
6371         break;
6372     case SP_TitleBarMenuButton:
6373 #  ifndef QT_NO_IMAGEFORMAT_XPM
6374         icon.addPixmap(titleBarMenuCachedPixmapFromXPM());
6375 #  endif
6376         icon.addFile(QLatin1String(":/qt-project.org/qmessagebox/images/qtlogo-64.png"));
6377         break;
6378     case SP_TitleBarNormalButton:
6379         addIconFiles(iconResourcePrefix() + QStringLiteral("normalizedockup-"),
6380                      dockTitleIconSizes, sizeof(dockTitleIconSizes)/sizeof(dockTitleIconSizes[0]), icon);
6381         break;
6382     case SP_ToolBarHorizontalExtensionButton: {
6383         QString prefix = iconResourcePrefix() + QStringLiteral("toolbar-ext-h-");
6384         if (rtl)
6385             prefix += QStringLiteral("rtl-");
6386         addIconFiles(prefix, toolBarExtHSizes, sizeof(toolBarExtHSizes)/sizeof(toolBarExtHSizes[0]), icon);
6387     }
6388         break;
6389     case SP_ToolBarVerticalExtensionButton:
6390         addIconFiles(iconResourcePrefix() + QStringLiteral("toolbar-ext-v-"),
6391                      toolBarExtVSizes, sizeof(toolBarExtVSizes)/sizeof(toolBarExtVSizes[0]), icon);
6392         break;
6393 #endif // QT_NO_IMAGEFORMAT_PNG
6394     default:
6395         icon.addPixmap(proxy()->standardPixmap(standardIcon, option, widget));
6396         break;
6397     }
6398     return icon;
6399 }
6400 
qt_intensity(uint r,uint g,uint b)6401 static inline uint qt_intensity(uint r, uint g, uint b)
6402 {
6403     // 30% red, 59% green, 11% blue
6404     return (77 * r + 150 * g + 28 * b) / 255;
6405 }
6406 
6407 /*! \reimp */
generatedIconPixmap(QIcon::Mode iconMode,const QPixmap & pixmap,const QStyleOption * opt) const6408 QPixmap QCommonStyle::generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap,
6409                                           const QStyleOption *opt) const
6410 {
6411     switch (iconMode) {
6412     case QIcon::Disabled: {
6413         QImage im = pixmap.toImage().convertToFormat(QImage::Format_ARGB32);
6414 
6415         // Create a colortable based on the background (black -> bg -> white)
6416         QColor bg = opt->palette.color(QPalette::Disabled, QPalette::Window);
6417         int red = bg.red();
6418         int green = bg.green();
6419         int blue = bg.blue();
6420         uchar reds[256], greens[256], blues[256];
6421         for (int i=0; i<128; ++i) {
6422             reds[i]   = uchar((red   * (i<<1)) >> 8);
6423             greens[i] = uchar((green * (i<<1)) >> 8);
6424             blues[i]  = uchar((blue  * (i<<1)) >> 8);
6425         }
6426         for (int i=0; i<128; ++i) {
6427             reds[i+128]   = uchar(qMin(red   + (i << 1), 255));
6428             greens[i+128] = uchar(qMin(green + (i << 1), 255));
6429             blues[i+128]  = uchar(qMin(blue  + (i << 1), 255));
6430         }
6431 
6432         int intensity = qt_intensity(red, green, blue);
6433         const int factor = 191;
6434 
6435         // High intensity colors needs dark shifting in the color table, while
6436         // low intensity colors needs light shifting. This is to increase the
6437         // perceived contrast.
6438         if ((red - factor > green && red - factor > blue)
6439             || (green - factor > red && green - factor > blue)
6440             || (blue - factor > red && blue - factor > green))
6441             intensity = qMin(255, intensity + 91);
6442         else if (intensity <= 128)
6443             intensity -= 51;
6444 
6445         for (int y=0; y<im.height(); ++y) {
6446             QRgb *scanLine = (QRgb*)im.scanLine(y);
6447             for (int x=0; x<im.width(); ++x) {
6448                 QRgb pixel = *scanLine;
6449                 // Calculate color table index, taking intensity adjustment
6450                 // and a magic offset into account.
6451                 uint ci = uint(qGray(pixel)/3 + (130 - intensity / 3));
6452                 *scanLine = qRgba(reds[ci], greens[ci], blues[ci], qAlpha(pixel));
6453                 ++scanLine;
6454             }
6455         }
6456 
6457         return QPixmap::fromImage(im);
6458     }
6459     case QIcon::Selected: {
6460         QImage img = pixmap.toImage().convertToFormat(QImage::Format_ARGB32_Premultiplied);
6461         QColor color = opt->palette.color(QPalette::Normal, QPalette::Highlight);
6462         color.setAlphaF(qreal(0.3));
6463         QPainter painter(&img);
6464         painter.setCompositionMode(QPainter::CompositionMode_SourceAtop);
6465         painter.fillRect(0, 0, img.width(), img.height(), color);
6466         painter.end();
6467         return QPixmap::fromImage(img); }
6468     case QIcon::Active:
6469         return pixmap;
6470     default:
6471         break;
6472     }
6473     return pixmap;
6474 }
6475 
6476 /*!
6477   \reimp
6478 */
layoutSpacing(QSizePolicy::ControlType,QSizePolicy::ControlType,Qt::Orientation,const QStyleOption *,const QWidget *) const6479 int QCommonStyle::layoutSpacing(QSizePolicy::ControlType /* control1 */, QSizePolicy::ControlType /* control2 */,
6480                           Qt::Orientation /* orientation */, const QStyleOption * /* option */,
6481                           const QWidget * /* widget */) const
6482 {
6483     return -1;
6484 }
6485 
6486 /*!
6487   \reimp
6488 */
polish(QPalette & pal)6489 void QCommonStyle::polish(QPalette &pal)
6490 {
6491     QStyle::polish(pal);
6492 }
6493 
6494 /*!
6495     \reimp
6496  */
polish(QWidget * widget)6497 void QCommonStyle::polish(QWidget *widget)
6498 {
6499     QStyle::polish(widget);
6500 }
6501 
6502 /*!
6503     \reimp
6504  */
unpolish(QWidget * widget)6505 void QCommonStyle::unpolish(QWidget *widget)
6506 {
6507     QStyle::unpolish(widget);
6508 }
6509 
6510 /*!
6511   \reimp
6512 */
polish(QApplication * app)6513 void QCommonStyle::polish(QApplication *app)
6514 {
6515     QStyle::polish(app);
6516 }
6517 
6518 /*!
6519     \reimp
6520  */
unpolish(QApplication * application)6521 void QCommonStyle::unpolish(QApplication *application)
6522 {
6523     Q_D(const QCommonStyle);
6524     d->tabBarcloseButtonIcon = QIcon();
6525     QStyle::unpolish(application);
6526 }
6527 
6528 
6529 QT_END_NAMESPACE
6530 
6531 #include "moc_qcommonstyle.cpp"
6532