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

source code of qtdeclarative/src/quicknativestyle/qstyle/qquickcommonstyle.cpp