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

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