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