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