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