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
122QT_BEGIN_NAMESPACE
123
124static qreal qt_getDevicePixelRatio(const QWidget *widget)
125{
126 return widget ? widget->devicePixelRatio() : qApp->devicePixelRatio();
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*/
156QCommonStyle::QCommonStyle()
157 : QStyle(*new QCommonStylePrivate)
158{ }
159
160/*! \internal
161*/
162QCommonStyle::QCommonStyle(QCommonStylePrivate &dd)
163 : QStyle(dd)
164{ }
165
166/*!
167 Destroys the style.
168*/
169QCommonStyle::~QCommonStyle()
170{ }
171
172
173/*!
174 \reimp
175*/
176void 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 QList<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->state & QStyle::State_Horizontal);
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(QSize(size, size), p->device()->devicePixelRatio(), 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()->devicePixelRatio();
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)
820static 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
846static 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
874QString 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
955QSize 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
1016void 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*/
1048void 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)
1178QString 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(u'\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 */
1203void 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 */
1269QList<const QObject*> QCommonStylePrivate::animationTargets() const
1270{
1271 return animations.keys();
1272}
1273
1274/*! \internal */
1275QStyleAnimation * QCommonStylePrivate::animation(const QObject *target) const
1276{
1277 return animations.value(target);
1278}
1279
1280/*! \internal */
1281void 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 */
1291void 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 */
1301void 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*/
1313void 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(button->iconSize, p->device()->devicePixelRatio(), 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(btn->iconSize, p->device()->devicePixelRatio(), 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(QSize(iconExtent, iconExtent), p->device()->devicePixelRatio(), (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->state & QStyle::State_Horizontal);
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->state & QStyle::State_Horizontal);
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(QSize(iconExtent, iconExtent), p->device()->devicePixelRatio(), (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(toolbutton->rect.size().boundedTo(toolbutton->iconSize), p->device()->devicePixelRatio(),
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(QSize(iconExtent, iconExtent), p->device()->devicePixelRatio(),
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(tab->iconSize, p->device()->devicePixelRatio(),
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(cb->iconSize, p->device()->devicePixelRatio(), 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, cb->textAlignment),
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*/
2435QRect 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(btn->iconSize, qt_getDevicePixelRatio(widget), 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(btn->iconSize, qt_getDevicePixelRatio(widget), 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->state & QStyle::State_Horizontal);
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 = proxy()->pixelMetric(QStyle::PM_TabBarScrollButtonWidth, nullptr, widget);
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 = proxy()->pixelMetric(QStyle::PM_TabBarScrollButtonWidth, nullptr, widget);
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
3192template <int N>
3193struct StaticPolygonF
3194{
3195 QPointF data[N];
3196
3197 constexpr int size() const { return N; }
3198 constexpr const QPointF *cbegin() const { return data; }
3199 constexpr const QPointF &operator[](int idx) const { return data[idx]; }
3200};
3201
3202static 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*/
3242void 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(QSize(10, 10), p->device()->devicePixelRatio());
3558 else
3559 pm = proxy()->standardIcon(SP_TitleBarCloseButton, &tool, widget).pixmap(QSize(10, 10), p->device()->devicePixelRatio());
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(QSize(10, 10), p->device()->devicePixelRatio());
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(QSize(10, 10), p->device()->devicePixelRatio());
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(QSize(10, 10), p->device()->devicePixelRatio());
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(QSize(10, 10), p->device()->devicePixelRatio());
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(QSize(10, 10), p->device()->devicePixelRatio());
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(QSize(10, 10), p->device()->devicePixelRatio());
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(QSize(iconSize, iconSize), p->device()->devicePixelRatio());
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(buttonIconSize, p->device()->devicePixelRatio());
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(buttonIconSize, p->device()->devicePixelRatio());
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(buttonIconSize, p->device()->devicePixelRatio());
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*/
3924QStyle::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*/
4061QRect 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 int y = fw + spinbox->rect.y();
4196 int x, lx, rx;
4197 x = spinbox->rect.x() + spinbox->rect.width() - fw - bs.width();
4198 lx = fw;
4199 rx = x - fw;
4200 switch (sc) {
4201 case SC_SpinBoxUp:
4202 if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons)
4203 return QRect();
4204 ret = QRect(x, y, bs.width(), bs.height());
4205 break;
4206 case SC_SpinBoxDown:
4207 if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons)
4208 return QRect();
4209
4210 ret = QRect(x, y + bs.height(), bs.width(), bs.height());
4211 break;
4212 case SC_SpinBoxEditField:
4213 if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons) {
4214 ret = QRect(lx, fw, spinbox->rect.width() - 2*fw, spinbox->rect.height() - 2*fw);
4215 } else {
4216 ret = QRect(lx, fw, rx, spinbox->rect.height() - 2*fw);
4217 }
4218 break;
4219 case SC_SpinBoxFrame:
4220 ret = spinbox->rect;
4221 default:
4222 break;
4223 }
4224 ret = visualRect(spinbox->direction, spinbox->rect, ret);
4225 }
4226 break;
4227#endif // Qt_NO_SPINBOX
4228#if QT_CONFIG(toolbutton)
4229 case CC_ToolButton:
4230 if (const QStyleOptionToolButton *tb = qstyleoption_cast<const QStyleOptionToolButton *>(opt)) {
4231 int mbi = proxy()->pixelMetric(PM_MenuButtonIndicator, tb, widget);
4232 ret = tb->rect;
4233 switch (sc) {
4234 case SC_ToolButton:
4235 if ((tb->features
4236 & (QStyleOptionToolButton::MenuButtonPopup | QStyleOptionToolButton::PopupDelay))
4237 == QStyleOptionToolButton::MenuButtonPopup)
4238 ret.adjust(0, 0, -mbi, 0);
4239 break;
4240 case SC_ToolButtonMenu:
4241 if ((tb->features
4242 & (QStyleOptionToolButton::MenuButtonPopup | QStyleOptionToolButton::PopupDelay))
4243 == QStyleOptionToolButton::MenuButtonPopup)
4244 ret.adjust(ret.width() - mbi, 0, 0, 0);
4245 break;
4246 default:
4247 break;
4248 }
4249 ret = visualRect(tb->direction, tb->rect, ret);
4250 }
4251 break;
4252#endif // QT_CONFIG(toolbutton)
4253#if QT_CONFIG(combobox)
4254 case CC_ComboBox:
4255 if (const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(opt)) {
4256 const qreal dpi = QStyleHelper::dpi(opt);
4257 const int x = cb->rect.x(), y = cb->rect.y(), wi = cb->rect.width(), he = cb->rect.height();
4258 const int margin = cb->frame ? qRound(QStyleHelper::dpiScaled(3, dpi)) : 0;
4259 const int bmarg = cb->frame ? qRound(QStyleHelper::dpiScaled(2, dpi)) : 0;
4260 const int xpos = x + wi - bmarg - qRound(QStyleHelper::dpiScaled(16, dpi));
4261
4262
4263 switch (sc) {
4264 case SC_ComboBoxFrame:
4265 ret = cb->rect;
4266 break;
4267 case SC_ComboBoxArrow:
4268 ret.setRect(xpos, y + bmarg, qRound(QStyleHelper::dpiScaled(16, opt)), he - 2*bmarg);
4269 break;
4270 case SC_ComboBoxEditField:
4271 ret.setRect(x + margin, y + margin, wi - 2 * margin - qRound(QStyleHelper::dpiScaled(16, dpi)), he - 2 * margin);
4272 break;
4273 case SC_ComboBoxListBoxPopup:
4274 ret = cb->rect;
4275 break;
4276 default:
4277 break;
4278 }
4279 ret = visualRect(cb->direction, cb->rect, ret);
4280 }
4281 break;
4282#endif // QT_CONFIG(combobox)
4283 case CC_TitleBar:
4284 if (const QStyleOptionTitleBar *tb = qstyleoption_cast<const QStyleOptionTitleBar *>(opt)) {
4285 const int controlMargin = 2;
4286 const int controlHeight = tb->rect.height() - controlMargin *2;
4287 const int delta = controlHeight + controlMargin;
4288 int offset = 0;
4289
4290 bool isMinimized = tb->titleBarState & Qt::WindowMinimized;
4291 bool isMaximized = tb->titleBarState & Qt::WindowMaximized;
4292
4293 switch (sc) {
4294 case SC_TitleBarLabel:
4295 if (tb->titleBarFlags & (Qt::WindowTitleHint | Qt::WindowSystemMenuHint)) {
4296 ret = tb->rect;
4297 if (tb->titleBarFlags & Qt::WindowSystemMenuHint)
4298 ret.adjust(delta, 0, -delta, 0);
4299 if (tb->titleBarFlags & Qt::WindowMinimizeButtonHint)
4300 ret.adjust(0, 0, -delta, 0);
4301 if (tb->titleBarFlags & Qt::WindowMaximizeButtonHint)
4302 ret.adjust(0, 0, -delta, 0);
4303 if (tb->titleBarFlags & Qt::WindowShadeButtonHint)
4304 ret.adjust(0, 0, -delta, 0);
4305 if (tb->titleBarFlags & Qt::WindowContextHelpButtonHint)
4306 ret.adjust(0, 0, -delta, 0);
4307 }
4308 break;
4309 case SC_TitleBarContextHelpButton:
4310 if (tb->titleBarFlags & Qt::WindowContextHelpButtonHint)
4311 offset += delta;
4312 Q_FALLTHROUGH();
4313 case SC_TitleBarMinButton:
4314 if (!isMinimized && (tb->titleBarFlags & Qt::WindowMinimizeButtonHint))
4315 offset += delta;
4316 else if (sc == SC_TitleBarMinButton)
4317 break;
4318 Q_FALLTHROUGH();
4319 case SC_TitleBarNormalButton:
4320 if (isMinimized && (tb->titleBarFlags & Qt::WindowMinimizeButtonHint))
4321 offset += delta;
4322 else if (isMaximized && (tb->titleBarFlags & Qt::WindowMaximizeButtonHint))
4323 offset += delta;
4324 else if (sc == SC_TitleBarNormalButton)
4325 break;
4326 Q_FALLTHROUGH();
4327 case SC_TitleBarMaxButton:
4328 if (!isMaximized && (tb->titleBarFlags & Qt::WindowMaximizeButtonHint))
4329 offset += delta;
4330 else if (sc == SC_TitleBarMaxButton)
4331 break;
4332 Q_FALLTHROUGH();
4333 case SC_TitleBarShadeButton:
4334 if (!isMinimized && (tb->titleBarFlags & Qt::WindowShadeButtonHint))
4335 offset += delta;
4336 else if (sc == SC_TitleBarShadeButton)
4337 break;
4338 Q_FALLTHROUGH();
4339 case SC_TitleBarUnshadeButton:
4340 if (isMinimized && (tb->titleBarFlags & Qt::WindowShadeButtonHint))
4341 offset += delta;
4342 else if (sc == SC_TitleBarUnshadeButton)
4343 break;
4344 Q_FALLTHROUGH();
4345 case SC_TitleBarCloseButton:
4346 if (tb->titleBarFlags & Qt::WindowSystemMenuHint)
4347 offset += delta;
4348 else if (sc == SC_TitleBarCloseButton)
4349 break;
4350 ret.setRect(tb->rect.right() - offset, tb->rect.top() + controlMargin,
4351 controlHeight, controlHeight);
4352 break;
4353 case SC_TitleBarSysMenu:
4354 if (tb->titleBarFlags & Qt::WindowSystemMenuHint) {
4355 ret.setRect(tb->rect.left() + controlMargin, tb->rect.top() + controlMargin,
4356 controlHeight, controlHeight);
4357 }
4358 break;
4359 default:
4360 break;
4361 }
4362 ret = visualRect(tb->direction, tb->rect, ret);
4363 }
4364 break;
4365#if QT_CONFIG(groupbox)
4366 case CC_GroupBox: {
4367 if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast<const QStyleOptionGroupBox *>(opt)) {
4368 switch (sc) {
4369 case SC_GroupBoxFrame:
4370 case SC_GroupBoxContents: {
4371 int topMargin = 0;
4372 int topHeight = 0;
4373 int verticalAlignment = proxy()->styleHint(SH_GroupBox_TextLabelVerticalAlignment, groupBox, widget);
4374 bool hasCheckBox = groupBox->subControls & QStyle::SC_GroupBoxCheckBox;
4375 if (groupBox->text.size() || hasCheckBox) {
4376 int checkBoxHeight = hasCheckBox ? proxy()->pixelMetric(PM_IndicatorHeight, groupBox, widget) : 0;
4377 topHeight = qMax(groupBox->fontMetrics.height(), checkBoxHeight);
4378 if (verticalAlignment & Qt::AlignVCenter)
4379 topMargin = topHeight / 2;
4380 else if (verticalAlignment & Qt::AlignTop)
4381 topMargin = topHeight;
4382 }
4383
4384 QRect frameRect = groupBox->rect;
4385 frameRect.setTop(topMargin);
4386
4387 if (sc == SC_GroupBoxFrame) {
4388 ret = frameRect;
4389 break;
4390 }
4391
4392 int frameWidth = 0;
4393 if ((groupBox->features & QStyleOptionFrame::Flat) == 0)
4394 frameWidth = proxy()->pixelMetric(PM_DefaultFrameWidth, groupBox, widget);
4395 ret = frameRect.adjusted(frameWidth, frameWidth + topHeight - topMargin,
4396 -frameWidth, -frameWidth);
4397 break;
4398 }
4399 case SC_GroupBoxCheckBox:
4400 case SC_GroupBoxLabel: {
4401 QFontMetrics fontMetrics = groupBox->fontMetrics;
4402 int th = fontMetrics.height();
4403 int tw = fontMetrics.size(Qt::TextShowMnemonic, groupBox->text + QLatin1Char(' ')).width();
4404 int marg = (groupBox->features & QStyleOptionFrame::Flat) ? 0 : 8;
4405 ret = groupBox->rect.adjusted(marg, 0, -marg, 0);
4406
4407 int indicatorWidth = proxy()->pixelMetric(PM_IndicatorWidth, opt, widget);
4408 int indicatorHeight = proxy()->pixelMetric(PM_IndicatorHeight, opt, widget);
4409 int indicatorSpace = proxy()->pixelMetric(PM_CheckBoxLabelSpacing, opt, widget) - 1;
4410 bool hasCheckBox = groupBox->subControls & QStyle::SC_GroupBoxCheckBox;
4411 int checkBoxWidth = hasCheckBox ? (indicatorWidth + indicatorSpace) : 0;
4412 int checkBoxHeight = hasCheckBox ? indicatorHeight : 0;
4413
4414 int h = qMax(th, checkBoxHeight);
4415 ret.setHeight(h);
4416
4417 // Adjusted rect for label + indicatorWidth + indicatorSpace
4418 QRect totalRect = alignedRect(groupBox->direction, groupBox->textAlignment,
4419 QSize(tw + checkBoxWidth, h), ret);
4420
4421 // Adjust totalRect if checkbox is set
4422 if (hasCheckBox) {
4423 bool ltr = groupBox->direction == Qt::LeftToRight;
4424 int left = 0;
4425 // Adjust for check box
4426 if (sc == SC_GroupBoxCheckBox) {
4427 left = ltr ? totalRect.left() : (totalRect.right() - indicatorWidth);
4428 int top = totalRect.top() + (h - checkBoxHeight) / 2;
4429 totalRect.setRect(left, top, indicatorWidth, indicatorHeight);
4430 // Adjust for label
4431 } else {
4432 left = ltr ? (totalRect.left() + checkBoxWidth - 2) : totalRect.left();
4433 int top = totalRect.top() + (h - th) / 2;
4434 totalRect.setRect(left, top, totalRect.width() - checkBoxWidth, th);
4435 }
4436 }
4437 ret = totalRect;
4438 break;
4439 }
4440 default:
4441 break;
4442 }
4443 }
4444 break;
4445 }
4446#endif // QT_CONFIG(groupbox)
4447#if QT_CONFIG(mdiarea)
4448 case CC_MdiControls:
4449 {
4450 int numSubControls = 0;
4451 if (opt->subControls & SC_MdiCloseButton)
4452 ++numSubControls;
4453 if (opt->subControls & SC_MdiMinButton)
4454 ++numSubControls;
4455 if (opt->subControls & SC_MdiNormalButton)
4456 ++numSubControls;
4457 if (numSubControls == 0)
4458 break;
4459
4460 int buttonWidth = opt->rect.width() / numSubControls - 1;
4461 int offset = 0;
4462 switch (sc) {
4463 case SC_MdiCloseButton:
4464 // Only one sub control, no offset needed.
4465 if (numSubControls == 1)
4466 break;
4467 offset += buttonWidth + 2;
4468 Q_FALLTHROUGH();
4469 case SC_MdiNormalButton:
4470 // No offset needed if
4471 // 1) There's only one sub control
4472 // 2) We have a close button and a normal button (offset already added in SC_MdiClose)
4473 if (numSubControls == 1 || (numSubControls == 2 && !(opt->subControls & SC_MdiMinButton)))
4474 break;
4475 if (opt->subControls & SC_MdiNormalButton)
4476 offset += buttonWidth;
4477 break;
4478 default:
4479 break;
4480 }
4481
4482 // Subtract one pixel if we only have one sub control. At this point
4483 // buttonWidth is the actual width + 1 pixel margin, but we don't want the
4484 // margin when there are no other controllers.
4485 if (numSubControls == 1)
4486 --buttonWidth;
4487 ret = QRect(offset, 0, buttonWidth, opt->rect.height());
4488 break;
4489 }
4490#endif // QT_CONFIG(mdiarea)
4491 default:
4492 qWarning("QCommonStyle::subControlRect: Case %d not handled", cc);
4493 }
4494#if !QT_CONFIG(slider) && !QT_CONFIG(spinbox) && !QT_CONFIG(toolbutton) && !QT_CONFIG(groupbox)
4495 Q_UNUSED(widget);
4496#endif
4497 return ret;
4498}
4499
4500/*! \reimp */
4501int QCommonStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const QWidget *widget) const
4502{
4503 int ret;
4504
4505 switch (m) {
4506 case PM_FocusFrameVMargin:
4507 case PM_FocusFrameHMargin:
4508 ret = 2;
4509 break;
4510 case PM_MenuBarVMargin:
4511 case PM_MenuBarHMargin:
4512 ret = 0;
4513 break;
4514 case PM_DialogButtonsSeparator:
4515 ret = int(QStyleHelper::dpiScaled(5, opt));
4516 break;
4517 case PM_DialogButtonsButtonWidth:
4518 ret = int(QStyleHelper::dpiScaled(70, opt));
4519 break;
4520 case PM_DialogButtonsButtonHeight:
4521 ret = int(QStyleHelper::dpiScaled(30, opt));
4522 break;
4523 case PM_TitleBarHeight: {
4524 if (const QStyleOptionTitleBar *tb = qstyleoption_cast<const QStyleOptionTitleBar *>(opt)) {
4525 if ((tb->titleBarFlags & Qt::WindowType_Mask) == Qt::Tool) {
4526 ret = qMax(widget ? widget->fontMetrics().height() : opt->fontMetrics.height(), 16);
4527#if QT_CONFIG(dockwidget)
4528 } else if (qobject_cast<const QDockWidget*>(widget)) {
4529 ret = qMax(widget->fontMetrics().height(), int(QStyleHelper::dpiScaled(13, opt)));
4530#endif
4531 } else {
4532 ret = qMax(widget ? widget->fontMetrics().height() : opt->fontMetrics.height(), 18);
4533 }
4534 } else {
4535 ret = int(QStyleHelper::dpiScaled(18., opt));
4536 }
4537
4538 break; }
4539 case PM_TitleBarButtonSize:
4540 ret = int(QStyleHelper::dpiScaled(16., opt));
4541 break;
4542 case PM_TitleBarButtonIconSize:
4543 ret = int(QStyleHelper::dpiScaled(16., opt));
4544 break;
4545
4546 case PM_ScrollBarSliderMin:
4547 ret = int(QStyleHelper::dpiScaled(9., opt));
4548 break;
4549
4550 case PM_ButtonMargin:
4551 ret = int(QStyleHelper::dpiScaled(6., opt));
4552 break;
4553
4554 case PM_DockWidgetTitleBarButtonMargin:
4555 ret = int(QStyleHelper::dpiScaled(2., opt));
4556 break;
4557
4558 case PM_ButtonDefaultIndicator:
4559 ret = 0;
4560 break;
4561
4562 case PM_MenuButtonIndicator:
4563 ret = int(QStyleHelper::dpiScaled(12, opt));
4564 break;
4565
4566 case PM_ButtonShiftHorizontal:
4567 case PM_ButtonShiftVertical:
4568
4569 case PM_DefaultFrameWidth:
4570 ret = 2;
4571 break;
4572
4573 case PM_ComboBoxFrameWidth:
4574 case PM_SpinBoxFrameWidth:
4575 case PM_MenuPanelWidth:
4576 case PM_TabBarBaseOverlap:
4577 case PM_TabBarBaseHeight:
4578 ret = proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget);
4579 break;
4580
4581 case PM_MdiSubWindowFrameWidth:
4582 ret = int(QStyleHelper::dpiScaled(4, opt));
4583 break;
4584
4585 case PM_MdiSubWindowMinimizedWidth:
4586 ret = int(QStyleHelper::dpiScaled(196, opt));
4587 break;
4588
4589#if QT_CONFIG(scrollbar)
4590 case PM_ScrollBarExtent:
4591 if (qstyleoption_cast<const QStyleOptionSlider *>(opt))
4592 ret = 16;
4593 else
4594 ret = int(QStyleHelper::dpiScaled(16, opt));
4595 break;
4596#endif
4597 case PM_MaximumDragDistance:
4598 ret = QGuiApplicationPrivate::platformTheme()->themeHint(QPlatformTheme::MaximumScrollBarDragDistance).toInt();
4599 break;
4600
4601#if QT_CONFIG(slider)
4602 case PM_SliderThickness:
4603 ret = int(QStyleHelper::dpiScaled(16, opt));
4604 break;
4605
4606 case PM_SliderTickmarkOffset:
4607 if (const QStyleOptionSlider *sl = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
4608 int space = (sl->orientation == Qt::Horizontal) ? sl->rect.height()
4609 : sl->rect.width();
4610 int thickness = proxy()->pixelMetric(PM_SliderControlThickness, sl, widget);
4611 int ticks = sl->tickPosition;
4612
4613 if (ticks == QSlider::TicksBothSides)
4614 ret = (space - thickness) / 2;
4615 else if (ticks == QSlider::TicksAbove)
4616 ret = space - thickness;
4617 else
4618 ret = 0;
4619 } else {
4620 ret = 0;
4621 }
4622 break;
4623
4624 case PM_SliderSpaceAvailable:
4625 if (const QStyleOptionSlider *sl = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
4626 if (sl->orientation == Qt::Horizontal)
4627 ret = sl->rect.width() - proxy()->pixelMetric(PM_SliderLength, sl, widget);
4628 else
4629 ret = sl->rect.height() - proxy()->pixelMetric(PM_SliderLength, sl, widget);
4630 } else {
4631 ret = 0;
4632 }
4633 break;
4634#endif // QT_CONFIG(slider)
4635#if QT_CONFIG(dockwidget)
4636 case PM_DockWidgetSeparatorExtent:
4637 ret = int(QStyleHelper::dpiScaled(6, opt));
4638 break;
4639
4640 case PM_DockWidgetHandleExtent:
4641 ret = int(QStyleHelper::dpiScaled(8, opt));
4642 break;
4643 case PM_DockWidgetTitleMargin:
4644 ret = 0;
4645 break;
4646 case PM_DockWidgetFrameWidth:
4647 ret = 1;
4648 break;
4649#endif // QT_CONFIG(dockwidget)
4650
4651 case PM_SpinBoxSliderHeight:
4652 case PM_MenuBarPanelWidth:
4653 ret = 2;
4654 break;
4655
4656 case PM_MenuBarItemSpacing:
4657 ret = 0;
4658 break;
4659
4660#if QT_CONFIG(toolbar)
4661 case PM_ToolBarFrameWidth:
4662 ret = 1;
4663 break;
4664
4665 case PM_ToolBarItemMargin:
4666 ret = 0;
4667 break;
4668
4669 case PM_ToolBarItemSpacing:
4670 ret = int(QStyleHelper::dpiScaled(4, opt));
4671 break;
4672
4673 case PM_ToolBarHandleExtent:
4674 ret = int(QStyleHelper::dpiScaled(8, opt));
4675 break;
4676
4677 case PM_ToolBarSeparatorExtent:
4678 ret = int(QStyleHelper::dpiScaled(6, opt));
4679 break;
4680
4681 case PM_ToolBarExtensionExtent:
4682 ret = int(QStyleHelper::dpiScaled(12, opt));
4683 break;
4684#endif // QT_CONFIG(toolbar)
4685
4686#if QT_CONFIG(tabbar)
4687 case PM_TabBarTabOverlap:
4688 ret = 3;
4689 break;
4690
4691 case PM_TabBarTabHSpace:
4692 ret = int(QStyleHelper::dpiScaled(24, opt));
4693 break;
4694
4695 case PM_TabBarTabShiftHorizontal:
4696 ret = 0;
4697 break;
4698
4699 case PM_TabBarTabShiftVertical:
4700 ret = 2;
4701 break;
4702
4703 case PM_TabBarTabVSpace: {
4704 const QStyleOptionTab *tb = qstyleoption_cast<const QStyleOptionTab *>(opt);
4705 if (tb && (tb->shape == QTabBar::RoundedNorth || tb->shape == QTabBar::RoundedSouth
4706 || tb->shape == QTabBar::RoundedWest || tb->shape == QTabBar::RoundedEast))
4707 ret = 8;
4708 else
4709 if(tb && (tb->shape == QTabBar::TriangularWest || tb->shape == QTabBar::TriangularEast))
4710 ret = 3;
4711 else
4712 ret = 2;
4713 break; }
4714#endif
4715
4716 case PM_ProgressBarChunkWidth:
4717 ret = 9;
4718 break;
4719
4720 case PM_IndicatorWidth:
4721 ret = int(QStyleHelper::dpiScaled(13, opt));
4722 break;
4723
4724 case PM_IndicatorHeight:
4725 ret = int(QStyleHelper::dpiScaled(13, opt));
4726 break;
4727
4728 case PM_ExclusiveIndicatorWidth:
4729 ret = int(QStyleHelper::dpiScaled(12, opt));
4730 break;
4731
4732 case PM_ExclusiveIndicatorHeight:
4733 ret = int(QStyleHelper::dpiScaled(12, opt));
4734 break;
4735
4736 case PM_MenuTearoffHeight:
4737 ret = int(QStyleHelper::dpiScaled(10, opt));
4738 break;
4739
4740 case PM_MenuScrollerHeight:
4741 ret = int(QStyleHelper::dpiScaled(10, opt));
4742 break;
4743
4744 case PM_MenuDesktopFrameWidth:
4745 case PM_MenuHMargin:
4746 case PM_MenuVMargin:
4747 ret = 0;
4748 break;
4749
4750 case PM_HeaderMargin:
4751 ret = int(QStyleHelper::dpiScaled(4, opt));
4752 break;
4753 case PM_HeaderMarkSize:
4754 ret = int(QStyleHelper::dpiScaled(16, opt));
4755 break;
4756 case PM_HeaderGripMargin:
4757 ret = int(QStyleHelper::dpiScaled(4, opt));
4758 break;
4759 case PM_HeaderDefaultSectionSizeHorizontal:
4760 ret = int(QStyleHelper::dpiScaled(100, opt));
4761 break;
4762 case PM_HeaderDefaultSectionSizeVertical:
4763 ret = int(QStyleHelper::dpiScaled(30, opt));
4764 break;
4765 case PM_TabBarScrollButtonWidth:
4766 ret = int(QStyleHelper::dpiScaled(16, opt));
4767 break;
4768 case PM_LayoutLeftMargin:
4769 case PM_LayoutTopMargin:
4770 case PM_LayoutRightMargin:
4771 case PM_LayoutBottomMargin:
4772 {
4773 bool isWindow = false;
4774 if (opt) {
4775 isWindow = (opt->state & State_Window);
4776 } else if (widget) {
4777 isWindow = widget->isWindow();
4778 }
4779 ret = int(QStyleHelper::dpiScaled(isWindow ? 11 : 9, opt));
4780 }
4781 break;
4782 case PM_LayoutHorizontalSpacing:
4783 case PM_LayoutVerticalSpacing:
4784 ret = int(QStyleHelper::dpiScaled(6, opt));
4785 break;
4786
4787 case PM_ToolBarIconSize:
4788 ret = 0;
4789 if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme())
4790 ret = theme->themeHint(QPlatformTheme::ToolBarIconSize).toInt();
4791 if (ret <= 0)
4792 ret = int(QStyleHelper::dpiScaled(24, opt));
4793 break;
4794
4795 case PM_TabBarIconSize:
4796 ret = proxy()->pixelMetric(PM_SmallIconSize, opt, widget);
4797 break;
4798 case PM_ListViewIconSize:
4799#if QT_CONFIG(filedialog)
4800 if (qobject_cast<const QSidebar *>(widget))
4801 ret = int(QStyleHelper::dpiScaled(24., opt));
4802 else
4803#endif
4804 ret = proxy()->pixelMetric(PM_SmallIconSize, opt, widget);
4805 break;
4806
4807 case PM_ButtonIconSize:
4808 case PM_SmallIconSize:
4809 ret = int(QStyleHelper::dpiScaled(16, opt));
4810 break;
4811 case PM_IconViewIconSize:
4812 ret = proxy()->pixelMetric(PM_LargeIconSize, opt, widget);
4813 break;
4814
4815 case PM_LargeIconSize:
4816 ret = int(QStyleHelper::dpiScaled(32, opt));
4817 break;
4818
4819 case PM_ToolTipLabelFrameWidth:
4820 ret = 1;
4821 break;
4822 case PM_CheckBoxLabelSpacing:
4823 case PM_RadioButtonLabelSpacing:
4824 ret = int(QStyleHelper::dpiScaled(6, opt));
4825 break;
4826 case PM_SizeGripSize:
4827 ret = int(QStyleHelper::dpiScaled(13, opt));
4828 break;
4829 case PM_MessageBoxIconSize:
4830#ifdef Q_OS_MAC
4831 if (QGuiApplication::desktopSettingsAware()) {
4832 ret = 64; // No DPI scaling, it's handled elsewhere.
4833 } else
4834#endif
4835 {
4836 ret = int(QStyleHelper::dpiScaled(32, opt));
4837 }
4838 break;
4839 case PM_TextCursorWidth:
4840 ret = QGuiApplicationPrivate::platformTheme()->themeHint(QPlatformTheme::TextCursorWidth).toInt();
4841 break;
4842 case PM_TabBar_ScrollButtonOverlap:
4843 ret = 1;
4844 break;
4845 case PM_TabCloseIndicatorWidth:
4846 case PM_TabCloseIndicatorHeight:
4847 ret = int(QStyleHelper::dpiScaled(16, opt));
4848 break;
4849 case PM_ScrollView_ScrollBarSpacing:
4850 ret = 2 * proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget);
4851 break;
4852 case PM_ScrollView_ScrollBarOverlap:
4853 ret = 0;
4854 break;
4855 case PM_SubMenuOverlap:
4856 ret = -proxy()->pixelMetric(QStyle::PM_MenuPanelWidth, opt, widget);
4857 break;
4858 case PM_TreeViewIndentation:
4859 ret = int(QStyleHelper::dpiScaled(20, opt));
4860 break;
4861 default:
4862 ret = 0;
4863 break;
4864 }
4865
4866 return ret;
4867}
4868
4869/*!
4870 \reimp
4871*/
4872QSize QCommonStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
4873 const QSize &csz, const QWidget *widget) const
4874{
4875 Q_D(const QCommonStyle);
4876 QSize sz(csz);
4877 switch (ct) {
4878 case CT_PushButton:
4879 if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
4880 int w = csz.width(),
4881 h = csz.height(),
4882 bm = proxy()->pixelMetric(PM_ButtonMargin, btn, widget),
4883 fw = proxy()->pixelMetric(PM_DefaultFrameWidth, btn, widget) * 2;
4884 w += bm + fw;
4885 h += bm + fw;
4886 if (btn->features & QStyleOptionButton::AutoDefaultButton){
4887 int dbw = proxy()->pixelMetric(PM_ButtonDefaultIndicator, btn, widget) * 2;
4888 w += dbw;
4889 h += dbw;
4890 }
4891 sz = QSize(w, h);
4892 }
4893 break;
4894 case CT_RadioButton:
4895 case CT_CheckBox:
4896 if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
4897 bool isRadio = (ct == CT_RadioButton);
4898
4899 int w = proxy()->pixelMetric(isRadio ? PM_ExclusiveIndicatorWidth
4900 : PM_IndicatorWidth, btn, widget);
4901 int h = proxy()->pixelMetric(isRadio ? PM_ExclusiveIndicatorHeight
4902 : PM_IndicatorHeight, btn, widget);
4903
4904 int margins = 0;
4905 // we add 4 pixels for label margins
4906 if (!btn->icon.isNull() || !btn->text.isEmpty())
4907 margins = 4 + proxy()->pixelMetric(isRadio ? PM_RadioButtonLabelSpacing
4908 : PM_CheckBoxLabelSpacing, opt, widget);
4909 sz += QSize(w + margins, 4);
4910 sz.setHeight(qMax(sz.height(), h));
4911 }
4912 break;
4913#if QT_CONFIG(menu)
4914 case CT_MenuItem:
4915 if (const QStyleOptionMenuItem *mi = qstyleoption_cast<const QStyleOptionMenuItem *>(opt)) {
4916 bool checkable = mi->menuHasCheckableItems;
4917 int maxpmw = mi->maxIconWidth;
4918 int w = sz.width(), h = sz.height();
4919 if (mi->menuItemType == QStyleOptionMenuItem::Separator) {
4920 w = 10;
4921 h = 2;
4922 } else {
4923 h = mi->fontMetrics.height() + 8;
4924 if (!mi->icon.isNull()) {
4925 int iconExtent = proxy()->pixelMetric(PM_SmallIconSize, opt);
4926 h = qMax(h, mi->icon.actualSize(QSize(iconExtent, iconExtent)).height() + 4);
4927 }
4928 }
4929 if (mi->text.contains(QLatin1Char('\t')))
4930 w += 12;
4931 if (maxpmw > 0)
4932 w += maxpmw + 6;
4933 if (checkable && maxpmw < 20)
4934 w += 20 - maxpmw;
4935 if (checkable || maxpmw > 0)
4936 w += 2;
4937 w += 12;
4938 sz = QSize(w, h);
4939 }
4940 break;
4941#endif // QT_CONFIG(menu)
4942#if QT_CONFIG(toolbutton)
4943 case CT_ToolButton:
4944 sz = QSize(sz.width() + 6, sz.height() + 5);
4945 break;
4946#endif // QT_CONFIG(toolbutton)
4947#if QT_CONFIG(combobox)
4948 case CT_ComboBox:
4949 if (const QStyleOptionComboBox *cmb = qstyleoption_cast<const QStyleOptionComboBox *>(opt)) {
4950 int fw = cmb->frame ? proxy()->pixelMetric(PM_ComboBoxFrameWidth, opt, widget) * 2 : 0;
4951 const int textMargins = 2*(proxy()->pixelMetric(PM_FocusFrameHMargin, opt) + 1);
4952 // QItemDelegate::sizeHint expands the textMargins two times, thus the 2*textMargins...
4953 int other = qMax(23, 2*textMargins + proxy()->pixelMetric(QStyle::PM_ScrollBarExtent, opt, widget));
4954 sz = QSize(sz.width() + fw + other, sz.height() + fw);
4955 }
4956 break;
4957#endif // QT_CONFIG(combobox)
4958 case CT_HeaderSection:
4959 if (const QStyleOptionHeader *hdr = qstyleoption_cast<const QStyleOptionHeader *>(opt)) {
4960 bool nullIcon = hdr->icon.isNull();
4961 int margin = proxy()->pixelMetric(QStyle::PM_HeaderMargin, hdr, widget);
4962 int iconSize = nullIcon ? 0 : proxy()->pixelMetric(QStyle::PM_SmallIconSize, hdr, widget);
4963 QSize txt = hdr->fontMetrics.size(0, hdr->text);
4964 sz.setHeight(margin + qMax(iconSize, txt.height()) + margin);
4965 sz.setWidth((nullIcon ? 0 : margin) + iconSize
4966 + (hdr->text.isNull() ? 0 : margin) + txt.width() + margin);
4967 if (hdr->sortIndicator != QStyleOptionHeader::None) {
4968 int margin = proxy()->pixelMetric(QStyle::PM_HeaderMargin, hdr, widget);
4969 if (hdr->orientation == Qt::Horizontal)
4970 sz.rwidth() += sz.height() + margin;
4971 else
4972 sz.rheight() += sz.width() + margin;
4973 }
4974 }
4975 break;
4976 case CT_TabWidget:
4977 sz += QSize(4, 4);
4978 break;
4979 case CT_LineEdit:
4980 if (const QStyleOptionFrame *f = qstyleoption_cast<const QStyleOptionFrame *>(opt))
4981 sz += QSize(2*f->lineWidth, 2*f->lineWidth);
4982 break;
4983#if QT_CONFIG(groupbox)
4984 case CT_GroupBox:
4985 if (const QStyleOptionGroupBox *styleOpt = qstyleoption_cast<const QStyleOptionGroupBox *>(opt))
4986 sz += QSize(styleOpt->features.testFlag(QStyleOptionFrame::Flat) ? 0 : 16, 0);
4987 break;
4988#endif // QT_CONFIG(groupbox)
4989 case CT_MdiControls:
4990 if (const QStyleOptionComplex *styleOpt = qstyleoption_cast<const QStyleOptionComplex *>(opt)) {
4991 const int buttonSize = proxy()->pixelMetric(PM_TitleBarButtonSize, styleOpt, widget);
4992 int width = 1;
4993 if (styleOpt->subControls & SC_MdiMinButton)
4994 width += buttonSize + 1;
4995 if (styleOpt->subControls & SC_MdiNormalButton)
4996 width += buttonSize + 1;
4997 if (styleOpt->subControls & SC_MdiCloseButton)
4998 width += buttonSize + 1;
4999 sz = QSize(width, buttonSize);
5000 } else {
5001 const int buttonSize = proxy()->pixelMetric(PM_TitleBarButtonSize, opt, widget);
5002 sz = QSize(1 + 3 * (buttonSize + 1), buttonSize);
5003 }
5004 break;
5005#if QT_CONFIG(itemviews)
5006 case CT_ItemViewItem:
5007 if (const QStyleOptionViewItem *vopt = qstyleoption_cast<const QStyleOptionViewItem *>(opt)) {
5008 QRect decorationRect, displayRect, checkRect;
5009 d->viewItemLayout(vopt, &checkRect, &decorationRect, &displayRect, true);
5010 sz = (decorationRect|displayRect|checkRect).size();
5011 if (decorationRect.isValid() && sz.height() == decorationRect.height())
5012 sz.rheight() += 2; // Prevent icons from overlapping.
5013 }
5014 break;
5015#else
5016 Q_UNUSED(d);
5017#endif // QT_CONFIG(itemviews)
5018#if QT_CONFIG(spinbox)
5019 case CT_SpinBox:
5020 if (const QStyleOptionSpinBox *vopt = qstyleoption_cast<const QStyleOptionSpinBox *>(opt)) {
5021 // Add button + frame widths
5022 const qreal dpi = QStyleHelper::dpi(opt);
5023 const bool hasButtons = (vopt->buttonSymbols != QAbstractSpinBox::NoButtons);
5024 const int buttonWidth = hasButtons ? qRound(QStyleHelper::dpiScaled(16, dpi)) : 0;
5025 const int fw = vopt->frame ? proxy()->pixelMetric(PM_SpinBoxFrameWidth, vopt, widget) : 0;
5026 sz += QSize(buttonWidth + 2*fw, 2*fw);
5027 }
5028 break;
5029#endif
5030 case CT_ScrollBar:
5031 case CT_MenuBar:
5032 case CT_Menu:
5033 case CT_MenuBarItem:
5034 case CT_Slider:
5035 case CT_ProgressBar:
5036 case CT_TabBarTab:
5037 // just return the contentsSize for now
5038 Q_FALLTHROUGH();
5039 default:
5040 break;
5041 }
5042 return sz;
5043}
5044
5045
5046/*! \reimp */
5047int QCommonStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget *widget,
5048 QStyleHintReturn *hret) const
5049{
5050 int ret = 0;
5051
5052 switch (sh) {
5053 case SH_Menu_KeyboardSearch:
5054 ret = false;
5055 break;
5056 case SH_Slider_AbsoluteSetButtons:
5057 ret = Qt::MiddleButton;
5058 break;
5059 case SH_Slider_PageSetButtons:
5060 ret = Qt::LeftButton;
5061 break;
5062 case SH_ScrollBar_ContextMenu:
5063 ret = true;
5064 break;
5065#if QT_CONFIG(dialogbuttonbox)
5066 case SH_DialogButtons_DefaultButton: // This value not used anywhere.
5067 ret = QDialogButtonBox::AcceptRole;
5068 break;
5069#endif
5070#if QT_CONFIG(groupbox)
5071 case SH_GroupBox_TextLabelVerticalAlignment:
5072 ret = Qt::AlignVCenter;
5073 break;
5074
5075 case SH_GroupBox_TextLabelColor:
5076 ret = opt ? int(opt->palette.color(QPalette::Text).rgba()) : 0;
5077 break;
5078#endif // QT_CONFIG(groupbox)
5079
5080 case SH_ListViewExpand_SelectMouseType:
5081 case SH_TabBar_SelectMouseType:
5082 ret = QEvent::MouseButtonPress;
5083 break;
5084
5085
5086 case SH_TabBar_Alignment:
5087 ret = Qt::AlignLeft;
5088 break;
5089
5090 case SH_Header_ArrowAlignment:
5091 ret = Qt::AlignRight | Qt::AlignVCenter;
5092 break;
5093
5094 case SH_TitleBar_AutoRaise:
5095 ret = false;
5096 break;
5097
5098 case SH_Menu_SubMenuPopupDelay:
5099 ret = 256;
5100 break;
5101
5102 case SH_Menu_SloppySubMenus:
5103 ret = true;
5104 break;
5105
5106 case SH_Menu_SubMenuUniDirection:
5107 ret = false;
5108 break;
5109 case SH_Menu_SubMenuUniDirectionFailCount:
5110 ret = 1;
5111 break;
5112 case SH_Menu_SubMenuSloppySelectOtherActions:
5113 ret = true;
5114 break;
5115 case SH_Menu_SubMenuSloppyCloseTimeout:
5116 ret = 1000;
5117 break;
5118 case SH_Menu_SubMenuResetWhenReenteringParent:
5119 ret = false;
5120 break;
5121 case SH_Menu_SubMenuDontStartSloppyOnLeave:
5122 ret = false;
5123 break;
5124
5125 case SH_ProgressDialog_TextLabelAlignment:
5126 ret = Qt::AlignCenter;
5127 break;
5128
5129 case SH_BlinkCursorWhenTextSelected:
5130#if defined(Q_OS_DARWIN)
5131 ret = 0;
5132#else
5133 ret = 1;
5134#endif
5135 break;
5136
5137 case SH_Table_GridLineColor:
5138 if (opt)
5139 ret = opt->palette.color(QPalette::Mid).rgba();
5140 else
5141 ret = -1;
5142 break;
5143 case SH_LineEdit_PasswordCharacter: {
5144 const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme();
5145 const QPlatformTheme::ThemeHint hintType = QPlatformTheme::PasswordMaskCharacter;
5146 const QVariant hint = theme ? theme->themeHint(hintType) : QPlatformTheme::defaultThemeHint(hintType);
5147 ret = hint.toChar().unicode();
5148 break;
5149 }
5150 case SH_LineEdit_PasswordMaskDelay:
5151 ret = QGuiApplicationPrivate::platformTheme()->themeHint(QPlatformTheme::PasswordMaskDelay).toInt();
5152 break;
5153 case SH_ToolBox_SelectedPageTitleBold:
5154 ret = 1;
5155 break;
5156
5157 case SH_UnderlineShortcut:
5158 ret = 1;
5159 break;
5160
5161 case SH_SpinBox_ClickAutoRepeatRate:
5162 ret = 150;
5163 break;
5164
5165 case SH_SpinBox_ClickAutoRepeatThreshold:
5166 ret = 500;
5167 break;
5168
5169 case SH_SpinBox_KeyPressAutoRepeatRate:
5170 ret = 75;
5171 break;
5172
5173 case SH_Menu_SelectionWrap:
5174 ret = true;
5175 break;
5176
5177 case SH_Menu_FillScreenWithScroll:
5178 ret = true;
5179 break;
5180
5181 case SH_ToolTipLabel_Opacity:
5182 ret = 255;
5183 break;
5184
5185 case SH_Button_FocusPolicy:
5186 ret = Qt::StrongFocus;
5187 break;
5188
5189 case SH_MessageBox_UseBorderForButtonSpacing:
5190 ret = 0;
5191 break;
5192
5193 case SH_ToolButton_PopupDelay:
5194 ret = 600;
5195 break;
5196
5197 case SH_FocusFrame_Mask:
5198 ret = 1;
5199 if (widget) {
5200 if(QStyleHintReturnMask *mask = qstyleoption_cast<QStyleHintReturnMask*>(hret)) {
5201 mask->region = widget->rect();
5202 const int vmargin = proxy()->pixelMetric(QStyle::PM_FocusFrameVMargin, opt);
5203 const int hmargin = proxy()->pixelMetric(QStyle::PM_FocusFrameHMargin, opt);
5204 mask->region -= QRect(widget->rect().adjusted(hmargin, vmargin, -hmargin, -vmargin));
5205 }
5206 }
5207 break;
5208#if QT_CONFIG(rubberband)
5209 case SH_RubberBand_Mask:
5210 if (const QStyleOptionRubberBand *rbOpt = qstyleoption_cast<const QStyleOptionRubberBand *>(opt)) {
5211 ret = 0;
5212 if (rbOpt->shape == QRubberBand::Rectangle) {
5213 ret = true;
5214 if(QStyleHintReturnMask *mask = qstyleoption_cast<QStyleHintReturnMask*>(hret)) {
5215 mask->region = opt->rect;
5216 const int margin = proxy()->pixelMetric(PM_DefaultFrameWidth, opt) * 2;
5217 mask->region -= opt->rect.adjusted(margin, margin, -margin, -margin);
5218 }
5219 }
5220 }
5221 break;
5222#endif // QT_CONFIG(rubberband)
5223 case SH_SpinControls_DisableOnBounds:
5224 ret = 1;
5225 break;
5226
5227 case SH_Dial_BackgroundRole:
5228 ret = QPalette::Window;
5229 break;
5230
5231 case SH_ComboBox_LayoutDirection:
5232 ret = opt ? opt->direction : Qt::LeftToRight;
5233 break;
5234
5235 case SH_ItemView_EllipsisLocation:
5236 ret = Qt::AlignTrailing;
5237 break;
5238
5239 case SH_ItemView_ShowDecorationSelected:
5240 ret = false;
5241 break;
5242
5243 case SH_ItemView_ActivateItemOnSingleClick:
5244 ret = 0;
5245 if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme())
5246 ret = theme->themeHint(QPlatformTheme::ItemViewActivateItemOnSingleClick).toBool() ? 1 : 0;
5247 break;
5248 case SH_TitleBar_ModifyNotification:
5249 ret = true;
5250 break;
5251 case SH_ScrollBar_RollBetweenButtons:
5252 ret = false;
5253 break;
5254 case SH_TabBar_ElideMode:
5255 ret = Qt::ElideNone;
5256 break;
5257#if QT_CONFIG(dialogbuttonbox)
5258 case SH_DialogButtonLayout:
5259 ret = QDialogButtonBox::WinLayout;
5260 if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme())
5261 ret = theme->themeHint(QPlatformTheme::DialogButtonBoxLayout).toInt();
5262 break;
5263#endif
5264 case SH_ComboBox_PopupFrameStyle:
5265 ret = QFrame::StyledPanel | QFrame::Plain;
5266 break;
5267 case SH_MessageBox_TextInteractionFlags:
5268 ret = Qt::LinksAccessibleByMouse;
5269 break;
5270 case SH_DialogButtonBox_ButtonsHaveIcons:
5271 ret = 0;
5272 if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme())
5273 ret = theme->themeHint(QPlatformTheme::DialogButtonBoxButtonsHaveIcons).toBool() ? 1 : 0;
5274 break;
5275 case SH_MessageBox_CenterButtons:
5276 ret = true;
5277 break;
5278 case SH_ItemView_MovementWithoutUpdatingSelection:
5279 ret = true;
5280 break;
5281 case SH_FocusFrame_AboveWidget:
5282 ret = false;
5283 break;
5284#if QT_CONFIG(tabwidget)
5285 case SH_TabWidget_DefaultTabPosition:
5286 ret = QTabWidget::North;
5287 break;
5288#endif
5289 case SH_ToolBar_Movable:
5290 ret = true;
5291 break;
5292 case SH_TextControl_FocusIndicatorTextCharFormat:
5293 ret = true;
5294 if (QStyleHintReturnVariant *vret = qstyleoption_cast<QStyleHintReturnVariant*>(hret)) {
5295 QPen outline(opt->palette.color(QPalette::Text), 1, Qt::DotLine);
5296 QTextCharFormat fmt;
5297 fmt.setProperty(QTextFormat::OutlinePen, outline);
5298 vret->variant = fmt;
5299 }
5300 break;
5301#if QT_CONFIG(wizard)
5302 case SH_WizardStyle:
5303 ret = QWizard::ClassicStyle;
5304 break;
5305#endif
5306#if QT_CONFIG(formlayout)
5307 case SH_FormLayoutWrapPolicy:
5308 ret = QFormLayout::DontWrapRows;
5309 break;
5310 case SH_FormLayoutFieldGrowthPolicy:
5311 ret = QFormLayout::AllNonFixedFieldsGrow;
5312 break;
5313#endif
5314 case SH_FormLayoutFormAlignment:
5315 ret = Qt::AlignLeft | Qt::AlignTop;
5316 break;
5317 case SH_FormLayoutLabelAlignment:
5318 ret = Qt::AlignLeft;
5319 break;
5320 case SH_ItemView_ArrowKeysNavigateIntoChildren:
5321 ret = false;
5322 break;
5323 case SH_ItemView_DrawDelegateFrame:
5324 ret = 0;
5325 break;
5326#if QT_CONFIG(tabbar)
5327 case SH_TabBar_CloseButtonPosition:
5328 ret = QTabBar::RightSide;
5329 break;
5330 case SH_TabBar_ChangeCurrentDelay:
5331 ret = 500;
5332 break;
5333#endif
5334 case SH_DockWidget_ButtonsHaveFrame:
5335 ret = true;
5336 break;
5337 case SH_ToolButtonStyle:
5338 ret = 0;
5339 if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme())
5340 ret = theme->themeHint(QPlatformTheme::ToolButtonStyle).toInt();
5341 break;
5342 case SH_RequestSoftwareInputPanel:
5343 ret = RSIP_OnMouseClick;
5344 break;
5345 case SH_ScrollBar_Transient:
5346 ret = false;
5347 break;
5348 case SH_Menu_SupportsSections:
5349 ret = false;
5350 break;
5351#if QT_CONFIG(tooltip)
5352 case SH_ToolTip_WakeUpDelay:
5353 ret = 700;
5354 break;
5355 case SH_ToolTip_FallAsleepDelay:
5356 ret = 2000;
5357 break;
5358#endif
5359 case SH_Widget_Animate:
5360 // TODO Qt6: move this code in the SH_Widget_Animation_Duration case
5361 // and replace false with 0 and true with 200.
5362#if QT_CONFIG(treeview)
5363 if (qobject_cast<const QTreeView*>(widget)) {
5364 ret = false;
5365 } else
5366#endif
5367 {
5368 ret = true;
5369 }
5370 break;
5371 case SH_Splitter_OpaqueResize:
5372 ret = true;
5373 break;
5374#if QT_CONFIG(itemviews)
5375 case SH_ItemView_ScrollMode:
5376 ret = QAbstractItemView::ScrollPerItem;
5377 break;
5378#endif
5379 case SH_TitleBar_ShowToolTipsOnButtons:
5380 ret = true;
5381 break;
5382 case SH_Widget_Animation_Duration:
5383 ret = styleHint(SH_Widget_Animate, opt, widget, hret) ? 200 : 0;
5384 break;
5385 case SH_ComboBox_AllowWheelScrolling:
5386 ret = true;
5387 break;
5388 case SH_SpinBox_ButtonsInsideFrame:
5389 ret = true;
5390 break;
5391 case SH_SpinBox_StepModifier:
5392 ret = Qt::ControlModifier;
5393 break;
5394 default:
5395 ret = 0;
5396 break;
5397 }
5398
5399 return ret;
5400}
5401
5402#if QT_CONFIG(imageformat_xpm)
5403static QPixmap cachedPixmapFromXPM(const char * const *xpm)
5404{
5405 QPixmap result;
5406 const QString tag = QString::asprintf("xpm:0x%p", static_cast<const void*>(xpm));
5407 if (!QPixmapCache::find(tag, &result)) {
5408 result = QPixmap(xpm);
5409 QPixmapCache::insert(tag, result);
5410 }
5411 return result;
5412}
5413
5414static inline QPixmap titleBarMenuCachedPixmapFromXPM() { return cachedPixmapFromXPM(qt_menu_xpm); }
5415#endif // QT_CONFIG(imageformat_xpm)
5416
5417#ifndef QT_NO_IMAGEFORMAT_PNG
5418static inline QString clearText16IconPath()
5419{
5420 return QStringLiteral(":/qt-project.org/styles/commonstyle/images/cleartext-16.png");
5421}
5422#endif // !QT_NO_IMAGEFORMAT_PNG
5423
5424#if defined(Q_OS_WIN) || QT_CONFIG(imageformat_png)
5425static QIcon clearTextIcon(bool rtl)
5426{
5427 const QString directionalThemeName = rtl
5428 ? QStringLiteral("edit-clear-locationbar-ltr") : QStringLiteral("edit-clear-locationbar-rtl");
5429 if (QIcon::hasThemeIcon(directionalThemeName))
5430 return QIcon::fromTheme(directionalThemeName);
5431 const QString themeName = QStringLiteral("edit-clear");
5432 if (QIcon::hasThemeIcon(themeName))
5433 return QIcon::fromTheme(themeName);
5434
5435 QIcon icon;
5436#ifndef QT_NO_IMAGEFORMAT_PNG
5437 QPixmap clearText16(clearText16IconPath());
5438 Q_ASSERT(!clearText16.size().isEmpty());
5439 icon.addPixmap(clearText16);
5440 QPixmap clearText32(QStringLiteral(":/qt-project.org/styles/commonstyle/images/cleartext-32.png"));
5441 Q_ASSERT(!clearText32.size().isEmpty());
5442 icon.addPixmap(clearText32);
5443 clearText32.setDevicePixelRatio(2); // The 32x32 pixmap can also be used for 16x16/devicePixelRatio=2
5444 icon.addPixmap(clearText32);
5445#endif // !QT_NO_IMAGEFORMAT_PNG
5446 return icon;
5447}
5448#endif
5449
5450/*! \reimp */
5451QPixmap QCommonStyle::standardPixmap(StandardPixmap sp, const QStyleOption *option,
5452 const QWidget *widget) const
5453{
5454 const bool rtl = (option && option->direction == Qt::RightToLeft) || (!option && QGuiApplication::isRightToLeft());
5455#ifdef QT_NO_IMAGEFORMAT_PNG
5456 Q_UNUSED(widget);
5457 Q_UNUSED(sp);
5458#else
5459 QPixmap pixmap;
5460
5461 if (QGuiApplication::desktopSettingsAware() && !QIcon::themeName().isEmpty()) {
5462 switch (sp) {
5463 case SP_DialogYesButton:
5464 case SP_DialogOkButton:
5465 pixmap = QIcon::fromTheme(QLatin1String("dialog-ok")).pixmap(16);
5466 break;
5467 case SP_DialogApplyButton:
5468 pixmap = QIcon::fromTheme(QLatin1String("dialog-ok-apply")).pixmap(16);
5469 break;
5470 case SP_DialogDiscardButton:
5471 pixmap = QIcon::fromTheme(QLatin1String("edit-delete")).pixmap(16);
5472 break;
5473 case SP_DialogCloseButton:
5474 pixmap = QIcon::fromTheme(QLatin1String("dialog-close")).pixmap(16);
5475 break;
5476 case SP_DirHomeIcon:
5477 pixmap = QIcon::fromTheme(QLatin1String("user-home")).pixmap(16);
5478 break;
5479 case SP_MessageBoxInformation:
5480 pixmap = QIcon::fromTheme(QLatin1String("messagebox_info")).pixmap(16);
5481 break;
5482 case SP_MessageBoxWarning:
5483 pixmap = QIcon::fromTheme(QLatin1String("messagebox_warning")).pixmap(16);
5484 break;
5485 case SP_MessageBoxCritical:
5486 pixmap = QIcon::fromTheme(QLatin1String("messagebox_critical")).pixmap(16);
5487 break;
5488 case SP_MessageBoxQuestion:
5489 pixmap = QIcon::fromTheme(QLatin1String("help")).pixmap(16);
5490 break;
5491 case SP_DialogOpenButton:
5492 case SP_DirOpenIcon:
5493 pixmap = QIcon::fromTheme(QLatin1String("folder-open")).pixmap(16);
5494 break;
5495 case SP_FileIcon:
5496 pixmap = QIcon::fromTheme(QLatin1String("text-x-generic"),
5497 QIcon::fromTheme(QLatin1String("empty"))).pixmap(16);
5498 break;
5499 case SP_DirClosedIcon:
5500 case SP_DirIcon:
5501 pixmap = QIcon::fromTheme(QLatin1String("folder")).pixmap(16);
5502 break;
5503 case SP_DriveFDIcon:
5504 pixmap = QIcon::fromTheme(QLatin1String("media-floppy"),
5505 QIcon::fromTheme(QLatin1String("3floppy_unmount"))).pixmap(16);
5506 break;
5507 case SP_ComputerIcon:
5508 pixmap = QIcon::fromTheme(QLatin1String("computer"),
5509 QIcon::fromTheme(QLatin1String("system"))).pixmap(16);
5510 break;
5511 case SP_DesktopIcon:
5512 pixmap = QIcon::fromTheme(QLatin1String("user-desktop"),
5513 QIcon::fromTheme(QLatin1String("desktop"))).pixmap(16);
5514 break;
5515 case SP_TrashIcon:
5516 pixmap = QIcon::fromTheme(QLatin1String("user-trash"),
5517 QIcon::fromTheme(QLatin1String("trashcan_empty"))).pixmap(16);
5518 break;
5519 case SP_DriveCDIcon:
5520 case SP_DriveDVDIcon:
5521 pixmap = QIcon::fromTheme(QLatin1String("media-optical"),
5522 QIcon::fromTheme(QLatin1String("cdrom_unmount"))).pixmap(16);
5523 break;
5524 case SP_DriveHDIcon:
5525 pixmap = QIcon::fromTheme(QLatin1String("drive-harddisk"),
5526 QIcon::fromTheme(QLatin1String("hdd_unmount"))).pixmap(16);
5527 break;
5528 case SP_FileDialogToParent:
5529 pixmap = QIcon::fromTheme(QLatin1String("go-up"),
5530 QIcon::fromTheme(QLatin1String("up"))).pixmap(16);
5531 break;
5532 case SP_FileDialogNewFolder:
5533 pixmap = QIcon::fromTheme(QLatin1String("folder_new")).pixmap(16);
5534 break;
5535 case SP_ArrowUp:
5536 pixmap = QIcon::fromTheme(QLatin1String("go-up"),
5537 QIcon::fromTheme(QLatin1String("up"))).pixmap(16);
5538 break;
5539 case SP_ArrowDown:
5540 pixmap = QIcon::fromTheme(QLatin1String("go-down"),
5541 QIcon::fromTheme(QLatin1String("down"))).pixmap(16);
5542 break;
5543 case SP_ArrowRight:
5544 pixmap = QIcon::fromTheme(QLatin1String("go-next"),
5545 QIcon::fromTheme(QLatin1String("forward"))).pixmap(16);
5546 break;
5547 case SP_ArrowLeft:
5548 pixmap = QIcon::fromTheme(QLatin1String("go-previous"),
5549 QIcon::fromTheme(QLatin1String("back"))).pixmap(16);
5550 break;
5551 case SP_FileDialogDetailedView:
5552 pixmap = QIcon::fromTheme(QLatin1String("view_detailed")).pixmap(16);
5553 break;
5554 case SP_FileDialogListView:
5555 pixmap = QIcon::fromTheme(QLatin1String("view_icon")).pixmap(16);
5556 break;
5557 case SP_BrowserReload:
5558 pixmap = QIcon::fromTheme(QLatin1String("reload")).pixmap(16);
5559 break;
5560 case SP_BrowserStop:
5561 pixmap = QIcon::fromTheme(QLatin1String("process-stop")).pixmap(16);
5562 break;
5563 case SP_MediaPlay:
5564 pixmap = QIcon::fromTheme(QLatin1String("media-playback-start")).pixmap(16);
5565 break;
5566 case SP_MediaPause:
5567 pixmap = QIcon::fromTheme(QLatin1String("media-playback-pause")).pixmap(16);
5568 break;
5569 case SP_MediaStop:
5570 pixmap = QIcon::fromTheme(QLatin1String("media-playback-stop")).pixmap(16);
5571 break;
5572 case SP_MediaSeekForward:
5573 pixmap = QIcon::fromTheme(QLatin1String("media-seek-forward")).pixmap(16);
5574 break;
5575 case SP_MediaSeekBackward:
5576 pixmap = QIcon::fromTheme(QLatin1String("media-seek-backward")).pixmap(16);
5577 break;
5578 case SP_MediaSkipForward:
5579 pixmap = QIcon::fromTheme(QLatin1String("media-skip-forward")).pixmap(16);
5580 break;
5581 case SP_MediaSkipBackward:
5582 pixmap = QIcon::fromTheme(QLatin1String("media-skip-backward")).pixmap(16);
5583 break;
5584 case SP_DialogResetButton:
5585 pixmap = QIcon::fromTheme(QLatin1String("edit-clear")).pixmap(24);
5586 break;
5587 case SP_DialogHelpButton:
5588 pixmap = QIcon::fromTheme(QLatin1String("help-contents")).pixmap(24);
5589 break;
5590 case SP_DialogNoButton:
5591 case SP_DialogCancelButton:
5592 pixmap = QIcon::fromTheme(QLatin1String("dialog-cancel"),
5593 QIcon::fromTheme(QLatin1String("process-stop"))).pixmap(24);
5594 break;
5595 case SP_DialogSaveButton:
5596 pixmap = QIcon::fromTheme(QLatin1String("document-save")).pixmap(24);
5597 break;
5598 case SP_FileLinkIcon:
5599 pixmap = QIcon::fromTheme(QLatin1String("emblem-symbolic-link")).pixmap(16);
5600 if (!pixmap.isNull()) {
5601 QPixmap fileIcon = QIcon::fromTheme(QLatin1String("text-x-generic")).pixmap(16);
5602 if (fileIcon.isNull())
5603 fileIcon = QIcon::fromTheme(QLatin1String("empty")).pixmap(16);
5604 if (!fileIcon.isNull()) {
5605 QPainter painter(&fileIcon);
5606 painter.drawPixmap(0, 0, 16, 16, pixmap);
5607 return fileIcon;
5608 }
5609 }
5610 break;
5611 case SP_DirLinkIcon:
5612 pixmap = QIcon::fromTheme(QLatin1String("emblem-symbolic-link")).pixmap(16);
5613 if (!pixmap.isNull()) {
5614 QPixmap dirIcon = QIcon::fromTheme(QLatin1String("folder")).pixmap(16);
5615 if (!dirIcon.isNull()) {
5616 QPainter painter(&dirIcon);
5617 painter.drawPixmap(0, 0, 16, 16, pixmap);
5618 return dirIcon;
5619 }
5620 }
5621 break;
5622 case SP_LineEditClearButton:
5623 pixmap = clearTextIcon(rtl).pixmap(16);
5624 break;
5625 default:
5626 break;
5627 }
5628 }
5629
5630 if (!pixmap.isNull())
5631 return pixmap;
5632#endif //QT_NO_IMAGEFORMAT_PNG
5633 switch (sp) {
5634#ifndef QT_NO_IMAGEFORMAT_XPM
5635 case SP_ToolBarHorizontalExtensionButton:
5636 if (rtl) {
5637 QImage im(tb_extension_arrow_h_xpm);
5638 im = im.convertToFormat(QImage::Format_ARGB32).mirrored(true, false);
5639 return QPixmap::fromImage(im);
5640 }
5641 return cachedPixmapFromXPM(tb_extension_arrow_h_xpm);
5642 case SP_ToolBarVerticalExtensionButton:
5643 return cachedPixmapFromXPM(tb_extension_arrow_v_xpm);
5644 case SP_FileDialogStart:
5645 return cachedPixmapFromXPM(filedialog_start_xpm);
5646 case SP_FileDialogEnd:
5647 return cachedPixmapFromXPM(filedialog_end_xpm);
5648#endif
5649#ifndef QT_NO_IMAGEFORMAT_PNG
5650 case SP_CommandLink:
5651 case SP_ArrowForward:
5652 if (rtl)
5653 return proxy()->standardPixmap(SP_ArrowLeft, option, widget);
5654 return proxy()->standardPixmap(SP_ArrowRight, option, widget);
5655 case SP_ArrowBack:
5656 if (rtl)
5657 return proxy()->standardPixmap(SP_ArrowRight, option, widget);
5658 return proxy()->standardPixmap(SP_ArrowLeft, option, widget);
5659 case SP_ArrowLeft:
5660 return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/left-16.png"));
5661 case SP_ArrowRight:
5662 return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/right-16.png"));
5663 case SP_ArrowUp:
5664 return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/up-16.png"));
5665 case SP_ArrowDown:
5666 return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/down-16.png"));
5667 case SP_FileDialogToParent:
5668 return proxy()->standardPixmap(SP_ArrowUp, option, widget);
5669 case SP_FileDialogNewFolder:
5670 return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/newdirectory-16.png"));
5671 case SP_FileDialogDetailedView:
5672 return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/viewdetailed-16.png"));
5673 case SP_FileDialogInfoView:
5674 return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/fileinfo-16.png"));
5675 case SP_FileDialogContentsView:
5676 return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/filecontents-16.png"));
5677 case SP_FileDialogListView:
5678 return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/viewlist-16.png"));
5679 case SP_FileDialogBack:
5680 return proxy()->standardPixmap(SP_ArrowBack, option, widget);
5681 case SP_DriveHDIcon:
5682 return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/harddrive-16.png"));
5683 case SP_TrashIcon:
5684 return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/trash-16.png"));
5685 case SP_DriveFDIcon:
5686 return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/floppy-16.png"));
5687 case SP_DriveNetIcon:
5688 return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/networkdrive-16.png"));
5689 case SP_DesktopIcon:
5690 return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/desktop-16.png"));
5691 case SP_ComputerIcon:
5692 return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/computer-16.png"));
5693 case SP_DriveCDIcon:
5694 return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/cdr-16.png"));
5695 case SP_DriveDVDIcon:
5696 return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/dvd-16.png"));
5697 case SP_DirHomeIcon:
5698 case SP_DirOpenIcon:
5699 return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/diropen-16.png"));
5700 case SP_DirIcon:
5701 case SP_DirClosedIcon:
5702 return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/dirclosed-16.png"));
5703 case SP_DirLinkIcon:
5704 return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/dirlink-16.png"));
5705 case SP_FileIcon:
5706 return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/file-16.png"));
5707 case SP_FileLinkIcon:
5708 return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/filelink-16.png"));
5709 case SP_DialogOkButton:
5710 return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-ok-16.png"));
5711 case SP_DialogCancelButton:
5712 return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-cancel-16.png"));
5713 case SP_DialogHelpButton:
5714 return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-help-16.png"));
5715 case SP_DialogOpenButton:
5716 return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-open-16.png"));
5717 case SP_DialogSaveButton:
5718 return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-save-16.png"));
5719 case SP_DialogCloseButton:
5720 return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-close-16.png"));
5721 case SP_DialogApplyButton:
5722 return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-apply-16.png"));
5723 case SP_DialogResetButton:
5724 return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-clear-16.png"));
5725 case SP_DialogDiscardButton:
5726 return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-delete-16.png"));
5727 case SP_DialogYesButton:
5728 return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-yes-16.png"));
5729 case SP_DialogNoButton:
5730 return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-no-16.png"));
5731 case SP_BrowserReload:
5732 return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/refresh-24.png"));
5733 case SP_BrowserStop:
5734 return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/stop-24.png"));
5735 case SP_MediaPlay:
5736 return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/media-play-32.png"));
5737 case SP_MediaPause:
5738 return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/media-pause-32.png"));
5739 case SP_MediaStop:
5740 return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/media-stop-32.png"));
5741 case SP_MediaSeekForward:
5742 return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/media-seek-forward-32.png"));
5743 case SP_MediaSeekBackward:
5744 return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/media-seek-backward-32.png"));
5745 case SP_MediaSkipForward:
5746 return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/media-skip-forward-32.png"));
5747 case SP_MediaSkipBackward:
5748 return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/media-skip-backward-32.png"));
5749 case SP_MediaVolume:
5750 return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/media-volume-16.png"));
5751 case SP_MediaVolumeMuted:
5752 return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/media-volume-muted-16.png"));
5753 case SP_LineEditClearButton:
5754 return QPixmap(clearText16IconPath());
5755#endif // QT_NO_IMAGEFORMAT_PNG
5756 default:
5757 break;
5758 }
5759
5760#ifndef QT_NO_IMAGEFORMAT_XPM
5761 switch (sp) {
5762 case SP_TitleBarMenuButton:
5763 return titleBarMenuCachedPixmapFromXPM();
5764 case SP_TitleBarShadeButton:
5765 return cachedPixmapFromXPM(qt_shade_xpm);
5766 case SP_TitleBarUnshadeButton:
5767 return cachedPixmapFromXPM(qt_unshade_xpm);
5768 case SP_TitleBarNormalButton:
5769 return cachedPixmapFromXPM(qt_normalizeup_xpm);
5770 case SP_TitleBarMinButton:
5771 return cachedPixmapFromXPM(qt_minimize_xpm);
5772 case SP_TitleBarMaxButton:
5773 return cachedPixmapFromXPM(qt_maximize_xpm);
5774 case SP_TitleBarCloseButton:
5775 return cachedPixmapFromXPM(qt_close_xpm);
5776 case SP_TitleBarContextHelpButton:
5777 return cachedPixmapFromXPM(qt_help_xpm);
5778 case SP_DockWidgetCloseButton:
5779 return cachedPixmapFromXPM(dock_widget_close_xpm);
5780 case SP_MessageBoxInformation:
5781 return cachedPixmapFromXPM(information_xpm);
5782 case SP_MessageBoxWarning:
5783 return cachedPixmapFromXPM(warning_xpm);
5784 case SP_MessageBoxCritical:
5785 return cachedPixmapFromXPM(critical_xpm);
5786 case SP_MessageBoxQuestion:
5787 return cachedPixmapFromXPM(question_xpm);
5788 default:
5789 break;
5790 }
5791#endif //QT_NO_IMAGEFORMAT_XPM
5792
5793#if !QT_CONFIG(imageformat_png) && !QT_CONFIG(imageformat_xpm) && !QT_CONFIG(imageformat_png)
5794 Q_UNUSED(rtl);
5795#endif
5796
5797 return QPixmap();
5798}
5799
5800#if QT_CONFIG(imageformat_png)
5801static inline QString iconResourcePrefix() { return QStringLiteral(":/qt-project.org/styles/commonstyle/images/"); }
5802static inline QString iconPngSuffix() { return QStringLiteral(".png"); }
5803
5804static void addIconFiles(const QString &prefix, const int sizes[], size_t count, QIcon &icon)
5805{
5806 for (size_t i = 0; i < count; ++i)
5807 icon.addFile(prefix + QString::number(sizes[i]) + iconPngSuffix());
5808}
5809
5810static const int dockTitleIconSizes[] = {10, 16, 20, 32, 48, 64};
5811static const int titleBarSizes[] = {16, 32, 48};
5812static const int toolBarExtHSizes[] = {8, 16, 32};
5813static const int toolBarExtVSizes[] = {5, 10, 20};
5814#endif // imageformat_png
5815
5816/*!
5817 \internal
5818*/
5819QIcon QCommonStyle::standardIcon(StandardPixmap standardIcon, const QStyleOption *option,
5820 const QWidget *widget) const
5821{
5822 QIcon icon;
5823 const bool rtl = (option && option->direction == Qt::RightToLeft) || (!option && QGuiApplication::isRightToLeft());
5824
5825#ifdef Q_OS_WIN
5826 switch (standardIcon) {
5827 case SP_DriveCDIcon:
5828 case SP_DriveDVDIcon:
5829 case SP_DriveNetIcon:
5830 case SP_DriveHDIcon:
5831 case SP_DriveFDIcon:
5832 case SP_FileIcon:
5833 case SP_FileLinkIcon:
5834 case SP_DesktopIcon:
5835 case SP_ComputerIcon:
5836 case SP_VistaShield:
5837 case SP_MessageBoxInformation:
5838 case SP_MessageBoxWarning:
5839 case SP_MessageBoxCritical:
5840 case SP_MessageBoxQuestion:
5841 if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) {
5842 QPlatformTheme::StandardPixmap sp = static_cast<QPlatformTheme::StandardPixmap>(standardIcon);
5843 for (int size = 16 ; size <= 32 ; size += 16) {
5844 QPixmap pixmap = theme->standardPixmap(sp, QSizeF(size, size));
5845 icon.addPixmap(pixmap, QIcon::Normal);
5846 }
5847 }
5848 break;
5849 case SP_DirIcon:
5850 case SP_DirLinkIcon:
5851 if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) {
5852 QPlatformTheme::StandardPixmap spOff = static_cast<QPlatformTheme::StandardPixmap>(standardIcon);
5853 QPlatformTheme::StandardPixmap spOn = standardIcon == SP_DirIcon ? QPlatformTheme::DirOpenIcon :
5854 QPlatformTheme::DirLinkOpenIcon;
5855 for (int size = 16 ; size <= 32 ; size += 16) {
5856 QSizeF pixSize(size, size);
5857 QPixmap pixmap = theme->standardPixmap(spOff, pixSize);
5858 icon.addPixmap(pixmap, QIcon::Normal, QIcon::Off);
5859 pixmap = theme->standardPixmap(spOn, pixSize);
5860 icon.addPixmap(pixmap, QIcon::Normal, QIcon::On);
5861 }
5862 }
5863 break;
5864 case SP_LineEditClearButton:
5865 icon = clearTextIcon(rtl);
5866 break;
5867 default:
5868 break;
5869 }
5870 if (!icon.isNull())
5871 return icon;
5872
5873#endif
5874
5875 if (QGuiApplication::desktopSettingsAware() && !QIcon::themeName().isEmpty()) {
5876 switch (standardIcon) {
5877 case SP_DirHomeIcon:
5878 icon = QIcon::fromTheme(QLatin1String("user-home"));
5879 break;
5880 case SP_MessageBoxInformation:
5881 icon = QIcon::fromTheme(QLatin1String("dialog-information"));
5882 break;
5883 case SP_MessageBoxWarning:
5884 icon = QIcon::fromTheme(QLatin1String("dialog-warning"));
5885 break;
5886 case SP_MessageBoxCritical:
5887 icon = QIcon::fromTheme(QLatin1String("dialog-error"));
5888 break;
5889 case SP_MessageBoxQuestion:
5890 icon = QIcon::fromTheme(QLatin1String("dialog-question"));
5891 break;
5892 case SP_DialogOpenButton:
5893 case SP_DirOpenIcon:
5894 icon = QIcon::fromTheme(QLatin1String("folder-open"));
5895 break;
5896 case SP_DialogSaveButton:
5897 icon = QIcon::fromTheme(QLatin1String("document-save"));
5898 break;
5899 case SP_DialogApplyButton:
5900 icon = QIcon::fromTheme(QLatin1String("dialog-ok-apply"));
5901 break;
5902 case SP_DialogYesButton:
5903 case SP_DialogOkButton:
5904 icon = QIcon::fromTheme(QLatin1String("dialog-ok"));
5905 break;
5906 case SP_DialogDiscardButton:
5907 icon = QIcon::fromTheme(QLatin1String("edit-delete"));
5908 break;
5909 case SP_DialogResetButton:
5910 icon = QIcon::fromTheme(QLatin1String("edit-clear"));
5911 break;
5912 case SP_DialogHelpButton:
5913 icon = QIcon::fromTheme(QLatin1String("help-contents"));
5914 break;
5915 case SP_FileIcon:
5916 icon = QIcon::fromTheme(QLatin1String("text-x-generic"));
5917 break;
5918 case SP_DirClosedIcon:
5919 case SP_DirIcon:
5920 icon = QIcon::fromTheme(QLatin1String("folder"));
5921 break;
5922 case SP_DriveFDIcon:
5923 icon = QIcon::fromTheme(QLatin1String("floppy_unmount"));
5924 break;
5925 case SP_ComputerIcon:
5926 icon = QIcon::fromTheme(QLatin1String("computer"),
5927 QIcon::fromTheme(QLatin1String("system")));
5928 break;
5929 case SP_DesktopIcon:
5930 icon = QIcon::fromTheme(QLatin1String("user-desktop"));
5931 break;
5932 case SP_TrashIcon:
5933 icon = QIcon::fromTheme(QLatin1String("user-trash"));
5934 break;
5935 case SP_DriveCDIcon:
5936 case SP_DriveDVDIcon:
5937 icon = QIcon::fromTheme(QLatin1String("media-optical"));
5938 break;
5939 case SP_DriveHDIcon:
5940 icon = QIcon::fromTheme(QLatin1String("drive-harddisk"));
5941 break;
5942 case SP_FileDialogToParent:
5943 icon = QIcon::fromTheme(QLatin1String("go-up"));
5944 break;
5945 case SP_FileDialogNewFolder:
5946 icon = QIcon::fromTheme(QLatin1String("folder-new"));
5947 break;
5948 case SP_ArrowUp:
5949 icon = QIcon::fromTheme(QLatin1String("go-up"));
5950 break;
5951 case SP_ArrowDown:
5952 icon = QIcon::fromTheme(QLatin1String("go-down"));
5953 break;
5954 case SP_ArrowRight:
5955 icon = QIcon::fromTheme(QLatin1String("go-next"));
5956 break;
5957 case SP_ArrowLeft:
5958 icon = QIcon::fromTheme(QLatin1String("go-previous"));
5959 break;
5960 case SP_DialogNoButton:
5961 case SP_DialogCancelButton:
5962 icon = QIcon::fromTheme(QLatin1String("dialog-cancel"),
5963 QIcon::fromTheme(QLatin1String("process-stop")));
5964 break;
5965 case SP_DialogCloseButton:
5966 icon = QIcon::fromTheme(QLatin1String("window-close"));
5967 break;
5968 case SP_FileDialogDetailedView:
5969 icon = QIcon::fromTheme(QLatin1String("view-list-details"));
5970 break;
5971 case SP_FileDialogListView:
5972 icon = QIcon::fromTheme(QLatin1String("view-list-icons"));
5973 break;
5974 case SP_BrowserReload:
5975 icon = QIcon::fromTheme(QLatin1String("view-refresh"));
5976 break;
5977 case SP_BrowserStop:
5978 icon = QIcon::fromTheme(QLatin1String("process-stop"));
5979 break;
5980 case SP_MediaPlay:
5981 icon = QIcon::fromTheme(QLatin1String("media-playback-start"));
5982 break;
5983 case SP_MediaPause:
5984 icon = QIcon::fromTheme(QLatin1String("media-playback-pause"));
5985 break;
5986 case SP_MediaStop:
5987 icon = QIcon::fromTheme(QLatin1String("media-playback-stop"));
5988 break;
5989 case SP_MediaSeekForward:
5990 icon = QIcon::fromTheme(QLatin1String("media-seek-forward"));
5991 break;
5992 case SP_MediaSeekBackward:
5993 icon = QIcon::fromTheme(QLatin1String("media-seek-backward"));
5994 break;
5995 case SP_MediaSkipForward:
5996 icon = QIcon::fromTheme(QLatin1String("media-skip-forward"));
5997 break;
5998 case SP_MediaSkipBackward:
5999 icon = QIcon::fromTheme(QLatin1String("media-skip-backward"));
6000 break;
6001 case SP_MediaVolume:
6002 icon = QIcon::fromTheme(QLatin1String("audio-volume-medium"));
6003 break;
6004 case SP_MediaVolumeMuted:
6005 icon = QIcon::fromTheme(QLatin1String("audio-volume-muted"));
6006 break;
6007 case SP_ArrowForward:
6008 if (rtl)
6009 return QCommonStyle::standardIcon(SP_ArrowLeft, option, widget);
6010 return QCommonStyle::standardIcon(SP_ArrowRight, option, widget);
6011 case SP_ArrowBack:
6012 if (rtl)
6013 return QCommonStyle::standardIcon(SP_ArrowRight, option, widget);
6014 return QCommonStyle::standardIcon(SP_ArrowLeft, option, widget);
6015 case SP_FileLinkIcon:
6016 {
6017 QIcon linkIcon = QIcon::fromTheme(QLatin1String("emblem-symbolic-link"));
6018 if (!linkIcon.isNull()) {
6019 QIcon baseIcon = QCommonStyle::standardIcon(SP_FileIcon, option, widget);
6020 const QList<QSize> sizes = baseIcon.availableSizes(QIcon::Normal, QIcon::Off);
6021 for (int i = 0 ; i < sizes.size() ; ++i) {
6022 int size = sizes[i].width();
6023 QPixmap basePixmap = baseIcon.pixmap(QSize(size, size), qt_getDevicePixelRatio(widget));
6024 QPixmap linkPixmap = linkIcon.pixmap(QSize(size / 2, size / 2), qt_getDevicePixelRatio(widget));
6025 QPainter painter(&basePixmap);
6026 painter.drawPixmap(size/2, size/2, linkPixmap);
6027 icon.addPixmap(basePixmap);
6028 }
6029 }
6030 }
6031 break;
6032 case SP_DirLinkIcon:
6033 {
6034 QIcon linkIcon = QIcon::fromTheme(QLatin1String("emblem-symbolic-link"));
6035 if (!linkIcon.isNull()) {
6036 QIcon baseIcon = QCommonStyle::standardIcon(SP_DirIcon, option, widget);
6037 const QList<QSize> sizes = baseIcon.availableSizes(QIcon::Normal, QIcon::Off);
6038 for (int i = 0 ; i < sizes.size() ; ++i) {
6039 int size = sizes[i].width();
6040 QPixmap basePixmap = baseIcon.pixmap(QSize(size, size), qt_getDevicePixelRatio(widget));
6041 QPixmap linkPixmap = linkIcon.pixmap(QSize(size / 2, size / 2), qt_getDevicePixelRatio(widget));
6042 QPainter painter(&basePixmap);
6043 painter.drawPixmap(size/2, size/2, linkPixmap);
6044 icon.addPixmap(basePixmap);
6045 }
6046 }
6047 }
6048 break;
6049 default:
6050 break;
6051 }
6052 } // if (QGuiApplication::desktopSettingsAware() && !QIcon::themeName().isEmpty())
6053
6054 if (!icon.isNull())
6055 return icon;
6056
6057#if defined(Q_OS_MAC)
6058 if (QGuiApplication::desktopSettingsAware()) {
6059 switch (standardIcon) {
6060 case SP_DirIcon: {
6061 // A rather special case
6062 QIcon closeIcon = QCommonStyle::standardIcon(SP_DirClosedIcon, option, widget);
6063 QIcon openIcon = QCommonStyle::standardIcon(SP_DirOpenIcon, option, widget);
6064 closeIcon.addPixmap(openIcon.pixmap(16, 16), QIcon::Normal, QIcon::On);
6065 closeIcon.addPixmap(openIcon.pixmap(32, 32), QIcon::Normal, QIcon::On);
6066 closeIcon.addPixmap(openIcon.pixmap(64, 64), QIcon::Normal, QIcon::On);
6067 closeIcon.addPixmap(openIcon.pixmap(128, 128), QIcon::Normal, QIcon::On);
6068 return closeIcon;
6069 }
6070
6071 case SP_TitleBarNormalButton:
6072 case SP_TitleBarCloseButton: {
6073 QIcon titleBarIcon;
6074 if (standardIcon == SP_TitleBarCloseButton) {
6075 titleBarIcon.addFile(QLatin1String(":/qt-project.org/styles/macstyle/images/closedock-16.png"));
6076 titleBarIcon.addFile(QLatin1String(":/qt-project.org/styles/macstyle/images/closedock-down-16.png"), QSize(16, 16), QIcon::Normal, QIcon::On);
6077 } else {
6078 titleBarIcon.addFile(QLatin1String(":/qt-project.org/styles/macstyle/images/dockdock-16.png"));
6079 titleBarIcon.addFile(QLatin1String(":/qt-project.org/styles/macstyle/images/dockdock-down-16.png"), QSize(16, 16), QIcon::Normal, QIcon::On);
6080 }
6081 return titleBarIcon;
6082 }
6083
6084 case SP_MessageBoxQuestion:
6085 case SP_MessageBoxInformation:
6086 case SP_MessageBoxWarning:
6087 case SP_MessageBoxCritical:
6088 case SP_DesktopIcon:
6089 case SP_TrashIcon:
6090 case SP_ComputerIcon:
6091 case SP_DriveFDIcon:
6092 case SP_DriveHDIcon:
6093 case SP_DriveCDIcon:
6094 case SP_DriveDVDIcon:
6095 case SP_DriveNetIcon:
6096 case SP_DirOpenIcon:
6097 case SP_DirClosedIcon:
6098 case SP_DirLinkIcon:
6099 case SP_FileLinkIcon:
6100 case SP_FileIcon:
6101 if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) {
6102 QPlatformTheme::StandardPixmap sp = static_cast<QPlatformTheme::StandardPixmap>(standardIcon);
6103 QIcon retIcon;
6104 const QList<QSize> sizes = theme->themeHint(QPlatformTheme::IconPixmapSizes).value<QList<QSize> >();
6105 for (const QSize &size : sizes) {
6106 QPixmap mainIcon;
6107 const QString cacheKey = QLatin1String("qt_mac_constructQIconFromIconRef") + QString::number(standardIcon) + QString::number(size.width());
6108 if (standardIcon >= QStyle::SP_CustomBase) {
6109 mainIcon = theme->standardPixmap(sp, QSizeF(size));
6110 } else if (QPixmapCache::find(cacheKey, &mainIcon) == false) {
6111 mainIcon = theme->standardPixmap(sp, QSizeF(size));
6112 QPixmapCache::insert(cacheKey, mainIcon);
6113 }
6114
6115 retIcon.addPixmap(mainIcon);
6116 }
6117 if (!retIcon.isNull())
6118 return retIcon;
6119 }
6120
6121 default:
6122 break;
6123 }
6124 } // if (QGuiApplication::desktopSettingsAware())
6125#endif // Q_OS_MAC
6126
6127 switch (standardIcon) {
6128#ifndef QT_NO_IMAGEFORMAT_PNG
6129 case SP_TitleBarMinButton:
6130 addIconFiles(iconResourcePrefix() + QStringLiteral("titlebar-min-"),
6131 titleBarSizes, sizeof(titleBarSizes)/sizeof(titleBarSizes[0]), icon);
6132 break;
6133 case SP_TitleBarMaxButton:
6134 addIconFiles(iconResourcePrefix() + QStringLiteral("titlebar-max-"),
6135 titleBarSizes, sizeof(titleBarSizes)/sizeof(titleBarSizes[0]), icon);
6136 break;
6137 case SP_TitleBarShadeButton:
6138 addIconFiles(iconResourcePrefix() + QStringLiteral("titlebar-shade-"),
6139 titleBarSizes, sizeof(titleBarSizes)/sizeof(titleBarSizes[0]), icon);
6140
6141 break;
6142 case SP_TitleBarUnshadeButton:
6143 addIconFiles(iconResourcePrefix() + QStringLiteral("titlebar-unshade-"),
6144 titleBarSizes, sizeof(titleBarSizes)/sizeof(titleBarSizes[0]), icon);
6145 break;
6146 case SP_TitleBarContextHelpButton:
6147 addIconFiles(iconResourcePrefix() + QStringLiteral("titlebar-contexthelp-"),
6148 titleBarSizes, sizeof(titleBarSizes)/sizeof(titleBarSizes[0]), icon);
6149 break;
6150 case SP_FileDialogNewFolder:
6151 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/newdirectory-16.png"), QSize(16, 16));
6152 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/newdirectory-32.png"), QSize(32, 32));
6153 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/newdirectory-128.png"), QSize(128, 128));
6154 break;
6155 case SP_FileDialogBack:
6156 return QCommonStyle::standardIcon(SP_ArrowBack, option, widget);
6157 case SP_FileDialogToParent:
6158 return QCommonStyle::standardIcon(SP_ArrowUp, option, widget);
6159 case SP_FileDialogDetailedView:
6160 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/viewdetailed-16.png"), QSize(16, 16));
6161 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/viewdetailed-32.png"), QSize(32, 32));
6162 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/viewdetailed-128.png"), QSize(128, 128));
6163 break;
6164 case SP_FileDialogInfoView:
6165 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/fileinfo-16.png"), QSize(16, 16));
6166 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/fileinfo-32.png"), QSize(32, 32));
6167 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/fileinfo-128.png"), QSize(128, 128));
6168 break;
6169 case SP_FileDialogContentsView:
6170 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/filecontents-16.png"), QSize(16, 16));
6171 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/filecontents-32.png"), QSize(32, 32));
6172 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/filecontents-128.png"), QSize(128, 128));
6173 break;
6174 case SP_FileDialogListView:
6175 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/viewlist-16.png"), QSize(16, 16));
6176 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/viewlist-32.png"), QSize(32, 32));
6177 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/viewlist-128.png"), QSize(128, 128));
6178 break;
6179 case SP_DialogOkButton:
6180 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-ok-16.png"), QSize(16, 16));
6181 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-ok-32.png"), QSize(32, 32));
6182 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-ok-128.png"), QSize(128, 128));
6183 break;
6184 case SP_DialogCancelButton:
6185 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-cancel-16.png"), QSize(16, 16));
6186 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-cancel-32.png"), QSize(32, 32));
6187 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-cancel-128.png"), QSize(128, 128));
6188 break;
6189 case SP_DialogHelpButton:
6190 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-help-16.png"), QSize(16, 16));
6191 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-help-32.png"), QSize(32, 32));
6192 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-help-128.png"), QSize(128, 128));
6193 break;
6194 case SP_DialogOpenButton:
6195 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-open-16.png"), QSize(16, 16));
6196 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-open-32.png"), QSize(32, 32));
6197 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-open-128.png"), QSize(128, 128));
6198 break;
6199 case SP_DialogSaveButton:
6200 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-save-16.png"), QSize(16, 16));
6201 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-save-32.png"), QSize(32, 32));
6202 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-save-128.png"), QSize(128, 128));
6203 break;
6204 case SP_DialogCloseButton:
6205 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-close-16.png"), QSize(16, 16));
6206 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-close-32.png"), QSize(32, 32));
6207 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-close-128.png"), QSize(128, 128));
6208 break;
6209 case SP_DialogApplyButton:
6210 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-apply-16.png"), QSize(16, 16));
6211 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-apply-32.png"), QSize(32, 32));
6212 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-apply-128.png"), QSize(128, 128));
6213 break;
6214 case SP_DialogResetButton:
6215 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-clear-16.png"), QSize(16, 16));
6216 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-clear-32.png"), QSize(32, 32));
6217 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-clear-128.png"), QSize(128, 128));
6218 break;
6219 case SP_DialogDiscardButton:
6220 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-delete-16.png"), QSize(16, 16));
6221 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-delete-32.png"), QSize(32, 32));
6222 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-delete-128.png"), QSize(128, 128));
6223 break;
6224 case SP_DialogYesButton:
6225 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-yes-16.png"), QSize(16, 16));
6226 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-yes-32.png"), QSize(32, 32));
6227 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-yes-128.png"), QSize(128, 128));
6228 break;
6229 case SP_DialogNoButton:
6230 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-no-16.png"), QSize(16, 16));
6231 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-no-32.png"), QSize(32, 32));
6232 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/standardbutton-no-128.png"), QSize(128, 128));
6233 break;
6234 case SP_ArrowForward:
6235 if (rtl)
6236 return QCommonStyle::standardIcon(SP_ArrowLeft, option, widget);
6237 return QCommonStyle::standardIcon(SP_ArrowRight, option, widget);
6238 case SP_ArrowBack:
6239 if (rtl)
6240 return QCommonStyle::standardIcon(SP_ArrowRight, option, widget);
6241 return QCommonStyle::standardIcon(SP_ArrowLeft, option, widget);
6242 case SP_ArrowLeft:
6243 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/left-16.png"), QSize(16, 16));
6244 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/left-32.png"), QSize(32, 32));
6245 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/left-128.png"), QSize(128, 128));
6246 break;
6247 case SP_ArrowRight:
6248 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/right-16.png"), QSize(16, 16));
6249 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/right-32.png"), QSize(32, 32));
6250 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/right-128.png"), QSize(128, 128));
6251 break;
6252 case SP_ArrowUp:
6253 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/up-16.png"), QSize(16, 16));
6254 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/up-32.png"), QSize(32, 32));
6255 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/up-128.png"), QSize(128, 128));
6256 break;
6257 case SP_ArrowDown:
6258 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/down-16.png"), QSize(16, 16));
6259 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/down-32.png"), QSize(32, 32));
6260 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/down-128.png"), QSize(128, 128));
6261 break;
6262 case SP_DirHomeIcon:
6263 case SP_DirIcon:
6264 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/dirclosed-16.png"),
6265 QSize(), QIcon::Normal, QIcon::Off);
6266 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/diropen-16.png"),
6267 QSize(), QIcon::Normal, QIcon::On);
6268 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/dirclosed-32.png"),
6269 QSize(32, 32), QIcon::Normal, QIcon::Off);
6270 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/diropen-32.png"),
6271 QSize(32, 32), QIcon::Normal, QIcon::On);
6272 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/dirclosed-128.png"),
6273 QSize(128, 128), QIcon::Normal, QIcon::Off);
6274 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/diropen-128.png"),
6275 QSize(128, 128), QIcon::Normal, QIcon::On);
6276 break;
6277 case SP_DriveCDIcon:
6278 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/cdr-16.png"), QSize(16, 16));
6279 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/cdr-32.png"), QSize(32, 32));
6280 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/cdr-128.png"), QSize(128, 128));
6281 break;
6282 case SP_DriveDVDIcon:
6283 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/dvd-16.png"), QSize(16, 16));
6284 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/dvd-32.png"), QSize(32, 32));
6285 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/dvd-128.png"), QSize(128, 128));
6286 break;
6287 case SP_FileIcon:
6288 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/file-16.png"), QSize(16, 16));
6289 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/file-32.png"), QSize(32, 32));
6290 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/file-128.png"), QSize(128, 128));
6291 break;
6292 case SP_FileLinkIcon:
6293 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/filelink-16.png"), QSize(16, 16));
6294 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/filelink-32.png"), QSize(32, 32));
6295 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/filelink-128.png"), QSize(128, 128));
6296 break;
6297 case SP_TrashIcon:
6298 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/trash-16.png"), QSize(16, 16));
6299 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/trash-32.png"), QSize(32, 32));
6300 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/trash-128.png"), QSize(128, 128));
6301 break;
6302 case SP_BrowserReload:
6303 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/refresh-24.png"), QSize(24, 24));
6304 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/refresh-32.png"), QSize(32, 32));
6305 break;
6306 case SP_BrowserStop:
6307 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/stop-24.png"), QSize(24, 24));
6308 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/stop-32.png"), QSize(32, 32));
6309 break;
6310 case SP_MediaPlay:
6311 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/media-play-16.png"), QSize(16, 16));
6312 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/media-play-32.png"), QSize(32, 32));
6313 break;
6314 case SP_MediaPause:
6315 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/media-pause-16.png"), QSize(16, 16));
6316 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/media-pause-32.png"), QSize(32, 32));
6317 break;
6318 case SP_MediaStop:
6319 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/media-stop-16.png"), QSize(16, 16));
6320 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/media-stop-32.png"), QSize(32, 32));
6321 break;
6322 case SP_MediaSeekForward:
6323 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/media-seek-forward-16.png"), QSize(16, 16));
6324 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/media-seek-forward-32.png"), QSize(32, 32));
6325 break;
6326 case SP_MediaSeekBackward:
6327 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/media-seek-backward-16.png"), QSize(16, 16));
6328 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/media-seek-backward-32.png"), QSize(32, 32));
6329 break;
6330 case SP_MediaSkipForward:
6331 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/media-skip-forward-16.png"), QSize(16, 16));
6332 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/media-skip-forward-32.png"), QSize(32, 32));
6333 break;
6334 case SP_MediaSkipBackward:
6335 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/media-skip-backward-16.png"), QSize(16, 16));
6336 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/media-skip-backward-32.png"), QSize(32, 32));
6337 break;
6338 case SP_MediaVolume:
6339 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/media-volume-16.png"), QSize(16, 16));
6340 break;
6341 case SP_MediaVolumeMuted:
6342 icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/media-volume-muted-16.png"), QSize(16, 16));
6343 break;
6344 case SP_TitleBarCloseButton:
6345 addIconFiles(iconResourcePrefix() + QStringLiteral("closedock-"),
6346 dockTitleIconSizes, sizeof(dockTitleIconSizes)/sizeof(dockTitleIconSizes[0]), icon);
6347 break;
6348 case SP_TitleBarMenuButton:
6349# ifndef QT_NO_IMAGEFORMAT_XPM
6350 icon.addPixmap(titleBarMenuCachedPixmapFromXPM());
6351# endif
6352 icon.addFile(QLatin1String(":/qt-project.org/qmessagebox/images/qtlogo-64.png"));
6353 break;
6354 case SP_TitleBarNormalButton:
6355 addIconFiles(iconResourcePrefix() + QStringLiteral("normalizedockup-"),
6356 dockTitleIconSizes, sizeof(dockTitleIconSizes)/sizeof(dockTitleIconSizes[0]), icon);
6357 break;
6358 case SP_ToolBarHorizontalExtensionButton: {
6359 QString prefix = iconResourcePrefix() + QStringLiteral("toolbar-ext-h-");
6360 if (rtl)
6361 prefix += QStringLiteral("rtl-");
6362 addIconFiles(prefix, toolBarExtHSizes, sizeof(toolBarExtHSizes)/sizeof(toolBarExtHSizes[0]), icon);
6363 }
6364 break;
6365 case SP_ToolBarVerticalExtensionButton:
6366 addIconFiles(iconResourcePrefix() + QStringLiteral("toolbar-ext-v-"),
6367 toolBarExtVSizes, sizeof(toolBarExtVSizes)/sizeof(toolBarExtVSizes[0]), icon);
6368 break;
6369#endif // QT_NO_IMAGEFORMAT_PNG
6370 default:
6371 icon.addPixmap(proxy()->standardPixmap(standardIcon, option, widget));
6372 break;
6373 }
6374 return icon;
6375}
6376
6377static inline uint qt_intensity(uint r, uint g, uint b)
6378{
6379 // 30% red, 59% green, 11% blue
6380 return (77 * r + 150 * g + 28 * b) / 255;
6381}
6382
6383/*! \reimp */
6384QPixmap QCommonStyle::generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap,
6385 const QStyleOption *opt) const
6386{
6387 switch (iconMode) {
6388 case QIcon::Disabled: {
6389 QImage im = pixmap.toImage().convertToFormat(QImage::Format_ARGB32);
6390
6391 // Create a colortable based on the background (black -> bg -> white)
6392 QColor bg = opt->palette.color(QPalette::Disabled, QPalette::Window);
6393 int red = bg.red();
6394 int green = bg.green();
6395 int blue = bg.blue();
6396 uchar reds[256], greens[256], blues[256];
6397 for (int i=0; i<128; ++i) {
6398 reds[i] = uchar((red * (i<<1)) >> 8);
6399 greens[i] = uchar((green * (i<<1)) >> 8);
6400 blues[i] = uchar((blue * (i<<1)) >> 8);
6401 }
6402 for (int i=0; i<128; ++i) {
6403 reds[i+128] = uchar(qMin(red + (i << 1), 255));
6404 greens[i+128] = uchar(qMin(green + (i << 1), 255));
6405 blues[i+128] = uchar(qMin(blue + (i << 1), 255));
6406 }
6407
6408 int intensity = qt_intensity(red, green, blue);
6409 const int factor = 191;
6410
6411 // High intensity colors needs dark shifting in the color table, while
6412 // low intensity colors needs light shifting. This is to increase the
6413 // perceived contrast.
6414 if ((red - factor > green && red - factor > blue)
6415 || (green - factor > red && green - factor > blue)
6416 || (blue - factor > red && blue - factor > green))
6417 intensity = qMin(255, intensity + 91);
6418 else if (intensity <= 128)
6419 intensity -= 51;
6420
6421 for (int y=0; y<im.height(); ++y) {
6422 QRgb *scanLine = (QRgb*)im.scanLine(y);
6423 for (int x=0; x<im.width(); ++x) {
6424 QRgb pixel = *scanLine;
6425 // Calculate color table index, taking intensity adjustment
6426 // and a magic offset into account.
6427 uint ci = uint(qGray(pixel)/3 + (130 - intensity / 3));
6428 *scanLine = qRgba(reds[ci], greens[ci], blues[ci], qAlpha(pixel));
6429 ++scanLine;
6430 }
6431 }
6432
6433 return QPixmap::fromImage(im);
6434 }
6435 case QIcon::Selected: {
6436 QImage img = pixmap.toImage().convertToFormat(QImage::Format_ARGB32_Premultiplied);
6437 QColor color = opt->palette.color(QPalette::Normal, QPalette::Highlight);
6438 color.setAlphaF(0.3f);
6439 QPainter painter(&img);
6440 painter.setCompositionMode(QPainter::CompositionMode_SourceAtop);
6441 painter.fillRect(0, 0, img.width(), img.height(), color);
6442 painter.end();
6443 return QPixmap::fromImage(img); }
6444 case QIcon::Active:
6445 return pixmap;
6446 default:
6447 break;
6448 }
6449 return pixmap;
6450}
6451
6452/*!
6453 \reimp
6454*/
6455int QCommonStyle::layoutSpacing(QSizePolicy::ControlType /* control1 */, QSizePolicy::ControlType /* control2 */,
6456 Qt::Orientation /* orientation */, const QStyleOption * /* option */,
6457 const QWidget * /* widget */) const
6458{
6459 return -1;
6460}
6461
6462/*!
6463 \reimp
6464*/
6465void QCommonStyle::polish(QPalette &pal)
6466{
6467 QStyle::polish(pal);
6468}
6469
6470/*!
6471 \reimp
6472 */
6473void QCommonStyle::polish(QWidget *widget)
6474{
6475 QStyle::polish(widget);
6476}
6477
6478/*!
6479 \reimp
6480 */
6481void QCommonStyle::unpolish(QWidget *widget)
6482{
6483 QStyle::unpolish(widget);
6484}
6485
6486/*!
6487 \reimp
6488*/
6489void QCommonStyle::polish(QApplication *app)
6490{
6491 QStyle::polish(app);
6492}
6493
6494/*!
6495 \reimp
6496 */
6497void QCommonStyle::unpolish(QApplication *application)
6498{
6499 Q_D(const QCommonStyle);
6500 d->tabBarcloseButtonIcon = QIcon();
6501 QStyle::unpolish(application);
6502}
6503
6504
6505QT_END_NAMESPACE
6506
6507#include "moc_qcommonstyle.cpp"
6508