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