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

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