1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtWidgets module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qfusionstyle_p.h"
41#include "qfusionstyle_p_p.h"
42
43#if QT_CONFIG(style_fusion) || defined(QT_PLUGIN)
44#include "qcommonstyle_p.h"
45#if QT_CONFIG(combobox)
46#include <qcombobox.h>
47#endif
48#if QT_CONFIG(pushbutton)
49#include <qpushbutton.h>
50#endif
51#if QT_CONFIG(abstractbutton)
52#include <qabstractbutton.h>
53#endif
54#include <qpainter.h>
55#include <qdir.h>
56#include <qstyleoption.h>
57#include <qapplication.h>
58#if QT_CONFIG(mainwindow)
59#include <qmainwindow.h>
60#endif
61#include <qfont.h>
62#if QT_CONFIG(groupbox)
63#include <qgroupbox.h>
64#endif
65#include <qpixmapcache.h>
66#if QT_CONFIG(scrollbar)
67#include <qscrollbar.h>
68#endif
69#if QT_CONFIG(spinbox)
70#include <qspinbox.h>
71#endif
72#if QT_CONFIG(abstractslider)
73#include <qabstractslider.h>
74#endif
75#if QT_CONFIG(slider)
76#include <qslider.h>
77#endif
78#if QT_CONFIG(splitter)
79#include <qsplitter.h>
80#endif
81#if QT_CONFIG(progressbar)
82#include <qprogressbar.h>
83#endif
84#if QT_CONFIG(wizard)
85#include <qwizard.h>
86#endif
87#include <qdrawutil.h>
88#include <private/qstylehelper_p.h>
89#include <private/qdrawhelper_p.h>
90#include <private/qapplication_p.h>
91
92QT_BEGIN_NAMESPACE
93
94using namespace QStyleHelper;
95
96enum Direction {
97 TopDown,
98 FromLeft,
99 BottomUp,
100 FromRight
101};
102
103// from windows style
104static const int windowsItemFrame = 2; // menu item frame width
105static const int windowsItemHMargin = 3; // menu item hor text margin
106static const int windowsItemVMargin = 8; // menu item ver text margin
107static const int windowsRightBorder = 15; // right border on windows
108
109static const int groupBoxBottomMargin = 0; // space below the groupbox
110static const int groupBoxTopMargin = 3;
111
112#if QT_CONFIG(imageformat_xpm)
113/* XPM */
114static const char * const dock_widget_close_xpm[] = {
115 "11 13 7 1",
116 " c None",
117 ". c #D5CFCB",
118 "+ c #8F8B88",
119 "@ c #6C6A67",
120 "# c #ABA6A3",
121 "$ c #B5B0AC",
122 "% c #A4A09D",
123 " ",
124 " +@@@@@@@+ ",
125 "+# #+",
126 "@ $@ @$ @",
127 "@ @@@ @@@ @",
128 "@ @@@@@ @",
129 "@ @@@ @",
130 "@ @@@@@ @",
131 "@ @@@ @@@ @",
132 "@ $@ @$ @",
133 "+% #+",
134 " +@@@@@@@+ ",
135 " "};
136
137static const char * const dock_widget_restore_xpm[] = {
138 "11 13 7 1",
139 " c None",
140 ". c #D5CFCB",
141 "+ c #8F8B88",
142 "@ c #6C6A67",
143 "# c #ABA6A3",
144 "$ c #B5B0AC",
145 "% c #A4A09D",
146 " ",
147 " +@@@@@@@+ ",
148 "+# #+",
149 "@ #@@@# @",
150 "@ @ @ @",
151 "@ #@@@# @ @",
152 "@ @ @ @ @",
153 "@ @ @@@ @",
154 "@ @ @ @",
155 "@ #@@@# @",
156 "+% #+",
157 " +@@@@@@@+ ",
158 " "};
159
160static const char * const workspace_minimize[] = {
161 "11 13 7 1",
162 " c None",
163 ". c #D5CFCB",
164 "+ c #8F8B88",
165 "@ c #6C6A67",
166 "# c #ABA6A3",
167 "$ c #B5B0AC",
168 "% c #A4A09D",
169 " ",
170 " +@@@@@@@+ ",
171 "+# #+",
172 "@ @",
173 "@ @",
174 "@ @",
175 "@ @@@@@@@ @",
176 "@ @@@@@@@ @",
177 "@ @",
178 "@ @",
179 "+% #+",
180 " +@@@@@@@+ ",
181 " "};
182
183
184static const char * const qt_titlebar_context_help[] = {
185 "10 10 3 1",
186 " c None",
187 "# c #000000",
188 "+ c #444444",
189 " +####+ ",
190 " ### ### ",
191 " ## ## ",
192 " +##+ ",
193 " +## ",
194 " ## ",
195 " ## ",
196 " ",
197 " ## ",
198 " ## "};
199#endif // QT_CONFIG(imageformat_xpm)
200
201static QColor mergedColors(const QColor &colorA, const QColor &colorB, int factor = 50)
202{
203 const int maxFactor = 100;
204 QColor tmp = colorA;
205 tmp.setRed((tmp.red() * factor) / maxFactor + (colorB.red() * (maxFactor - factor)) / maxFactor);
206 tmp.setGreen((tmp.green() * factor) / maxFactor + (colorB.green() * (maxFactor - factor)) / maxFactor);
207 tmp.setBlue((tmp.blue() * factor) / maxFactor + (colorB.blue() * (maxFactor - factor)) / maxFactor);
208 return tmp;
209}
210
211// The default button and handle gradient
212static QLinearGradient qt_fusion_gradient(const QRect &rect, const QBrush &baseColor, Direction direction = TopDown)
213{
214 int x = rect.center().x();
215 int y = rect.center().y();
216 QLinearGradient gradient;
217 switch (direction) {
218 case FromLeft:
219 gradient = QLinearGradient(rect.left(), y, rect.right(), y);
220 break;
221 case FromRight:
222 gradient = QLinearGradient(rect.right(), y, rect.left(), y);
223 break;
224 case BottomUp:
225 gradient = QLinearGradient(x, rect.bottom(), x, rect.top());
226 break;
227 case TopDown:
228 default:
229 gradient = QLinearGradient(x, rect.top(), x, rect.bottom());
230 break;
231 }
232 if (baseColor.gradient())
233 gradient.setStops(baseColor.gradient()->stops());
234 else {
235 QColor gradientStartColor = baseColor.color().lighter(124);
236 QColor gradientStopColor = baseColor.color().lighter(102);
237 gradient.setColorAt(0, gradientStartColor);
238 gradient.setColorAt(1, gradientStopColor);
239 // Uncomment for adding shiny shading
240 // QColor midColor1 = mergedColors(gradientStartColor, gradientStopColor, 55);
241 // QColor midColor2 = mergedColors(gradientStartColor, gradientStopColor, 45);
242 // gradient.setColorAt(0.5, midColor1);
243 // gradient.setColorAt(0.501, midColor2);
244 }
245 return gradient;
246}
247
248static void qt_fusion_draw_arrow(Qt::ArrowType type, QPainter *painter, const QStyleOption *option, const QRect &rect, const QColor &color)
249{
250 if (rect.isEmpty())
251 return;
252
253 const int arrowWidth = QStyleHelper::dpiScaled(14);
254 const int arrowHeight = QStyleHelper::dpiScaled(8);
255
256 const int arrowMax = qMin(arrowHeight, arrowWidth);
257 const int rectMax = qMin(rect.height(), rect.width());
258 const int size = qMin(arrowMax, rectMax);
259
260 QPixmap cachePixmap;
261 QString cacheKey = QStyleHelper::uniqueName(QLatin1String("fusion-arrow"), option, rect.size())
262 % HexString<uint>(type)
263 % HexString<uint>(color.rgba());
264 if (!QPixmapCache::find(cacheKey, &cachePixmap)) {
265 cachePixmap = styleCachePixmap(rect.size());
266 cachePixmap.fill(Qt::transparent);
267 QPainter cachePainter(&cachePixmap);
268
269 QRectF arrowRect;
270 arrowRect.setWidth(size);
271 arrowRect.setHeight(arrowHeight * size / arrowWidth);
272 if (type == Qt::LeftArrow || type == Qt::RightArrow)
273 arrowRect = arrowRect.transposed();
274 arrowRect.moveTo((rect.width() - arrowRect.width()) / 2.0,
275 (rect.height() - arrowRect.height()) / 2.0);
276
277 QPolygonF triangle;
278 triangle.reserve(3);
279 switch (type) {
280 case Qt::DownArrow:
281 triangle << arrowRect.topLeft() << arrowRect.topRight() << QPointF(arrowRect.center().x(), arrowRect.bottom());
282 break;
283 case Qt::RightArrow:
284 triangle << arrowRect.topLeft() << arrowRect.bottomLeft() << QPointF(arrowRect.right(), arrowRect.center().y());
285 break;
286 case Qt::LeftArrow:
287 triangle << arrowRect.topRight() << arrowRect.bottomRight() << QPointF(arrowRect.left(), arrowRect.center().y());
288 break;
289 default:
290 triangle << arrowRect.bottomLeft() << arrowRect.bottomRight() << QPointF(arrowRect.center().x(), arrowRect.top());
291 break;
292 }
293
294 cachePainter.setPen(Qt::NoPen);
295 cachePainter.setBrush(color);
296 cachePainter.setRenderHint(QPainter::Antialiasing);
297 cachePainter.drawPolygon(triangle);
298
299 QPixmapCache::insert(cacheKey, cachePixmap);
300 }
301
302 painter->drawPixmap(rect, cachePixmap);
303}
304
305static void qt_fusion_draw_mdibutton(QPainter *painter, const QStyleOptionTitleBar *option, const QRect &tmp, bool hover, bool sunken)
306{
307 QColor dark;
308 dark.setHsv(option->palette.button().color().hue(),
309 qMin(255, (int)(option->palette.button().color().saturation())),
310 qMin(255, (int)(option->palette.button().color().value()*0.7)));
311
312 QColor highlight = option->palette.highlight().color();
313
314 bool active = (option->titleBarState & QStyle::State_Active);
315 QColor titleBarHighlight(255, 255, 255, 60);
316
317 if (sunken)
318 painter->fillRect(tmp.adjusted(1, 1, -1, -1), option->palette.highlight().color().darker(120));
319 else if (hover)
320 painter->fillRect(tmp.adjusted(1, 1, -1, -1), QColor(255, 255, 255, 20));
321
322 QColor mdiButtonGradientStartColor;
323 QColor mdiButtonGradientStopColor;
324
325 mdiButtonGradientStartColor = QColor(0, 0, 0, 40);
326 mdiButtonGradientStopColor = QColor(255, 255, 255, 60);
327
328 if (sunken)
329 titleBarHighlight = highlight.darker(130);
330
331 QLinearGradient gradient(tmp.center().x(), tmp.top(), tmp.center().x(), tmp.bottom());
332 gradient.setColorAt(0, mdiButtonGradientStartColor);
333 gradient.setColorAt(1, mdiButtonGradientStopColor);
334 QColor mdiButtonBorderColor(active ? option->palette.highlight().color().darker(180): dark.darker(110));
335
336 painter->setPen(QPen(mdiButtonBorderColor));
337 const QLine lines[4] = {
338 QLine(tmp.left() + 2, tmp.top(), tmp.right() - 2, tmp.top()),
339 QLine(tmp.left() + 2, tmp.bottom(), tmp.right() - 2, tmp.bottom()),
340 QLine(tmp.left(), tmp.top() + 2, tmp.left(), tmp.bottom() - 2),
341 QLine(tmp.right(), tmp.top() + 2, tmp.right(), tmp.bottom() - 2)
342 };
343 painter->drawLines(lines, 4);
344 const QPoint points[4] = {
345 QPoint(tmp.left() + 1, tmp.top() + 1),
346 QPoint(tmp.right() - 1, tmp.top() + 1),
347 QPoint(tmp.left() + 1, tmp.bottom() - 1),
348 QPoint(tmp.right() - 1, tmp.bottom() - 1)
349 };
350 painter->drawPoints(points, 4);
351
352 painter->setPen(titleBarHighlight);
353 painter->drawLine(tmp.left() + 2, tmp.top() + 1, tmp.right() - 2, tmp.top() + 1);
354 painter->drawLine(tmp.left() + 1, tmp.top() + 2, tmp.left() + 1, tmp.bottom() - 2);
355
356 painter->setPen(QPen(gradient, 1));
357 painter->drawLine(tmp.right() + 1, tmp.top() + 2, tmp.right() + 1, tmp.bottom() - 2);
358 painter->drawPoint(tmp.right() , tmp.top() + 1);
359
360 painter->drawLine(tmp.left() + 2, tmp.bottom() + 1, tmp.right() - 2, tmp.bottom() + 1);
361 painter->drawPoint(tmp.left() + 1, tmp.bottom());
362 painter->drawPoint(tmp.right() - 1, tmp.bottom());
363 painter->drawPoint(tmp.right() , tmp.bottom() - 1);
364}
365
366/*
367 \internal
368*/
369QFusionStylePrivate::QFusionStylePrivate()
370{
371 animationFps = 60;
372}
373
374/*!
375 \class QFusionStyle
376 \brief The QFusionStyle class provides a custom widget style
377
378 \inmodule QtWidgets
379 \internal
380
381 The Fusion style provides a custom look and feel that is not
382 tied to a particular platform.
383 //{Fusion Style Widget Gallery}
384 \sa QWindowsStyle, QWindowsVistaStyle, QMacStyle, QCommonStyle
385*/
386
387/*!
388 Constructs a QFusionStyle object.
389*/
390QFusionStyle::QFusionStyle() : QCommonStyle(*new QFusionStylePrivate)
391{
392 setObjectName(QLatin1String("Fusion"));
393}
394
395/*!
396 \internal
397
398 Constructs a QFusionStyle object.
399*/
400QFusionStyle::QFusionStyle(QFusionStylePrivate &dd) : QCommonStyle(dd)
401{
402}
403
404/*!
405 Destroys the QFusionStyle object.
406*/
407QFusionStyle::~QFusionStyle()
408{
409}
410
411/*!
412 \fn void QFusionStyle::drawItemText(QPainter *painter, const QRect &rectangle, int alignment, const QPalette &palette,
413 bool enabled, const QString& text, QPalette::ColorRole textRole) const
414
415 Draws the given \a text in the specified \a rectangle using the
416 provided \a painter and \a palette.
417
418 Text is drawn using the painter's pen. If an explicit \a textRole
419 is specified, then the text is drawn using the \a palette's color
420 for the specified role. The \a enabled value indicates whether or
421 not the item is enabled; when reimplementing, this value should
422 influence how the item is drawn.
423
424 The text is aligned and wrapped according to the specified \a
425 alignment.
426
427 \sa Qt::Alignment
428*/
429void QFusionStyle::drawItemText(QPainter *painter, const QRect &rect, int alignment, const QPalette &pal,
430 bool enabled, const QString& text, QPalette::ColorRole textRole) const
431{
432 if (text.isEmpty())
433 return;
434
435 QPen savedPen = painter->pen();
436 if (textRole != QPalette::NoRole) {
437 painter->setPen(QPen(pal.brush(textRole), savedPen.widthF()));
438 }
439 if (!enabled) {
440 QPen pen = painter->pen();
441 painter->setPen(pen);
442 }
443 painter->drawText(rect, alignment, text);
444 painter->setPen(savedPen);
445}
446
447
448/*!
449 \reimp
450*/
451void QFusionStyle::drawPrimitive(PrimitiveElement elem,
452 const QStyleOption *option,
453 QPainter *painter, const QWidget *widget) const
454{
455 Q_ASSERT(option);
456 Q_D (const QFusionStyle);
457
458 QRect rect = option->rect;
459 int state = option->state;
460
461 QColor outline = d->outline(option->palette);
462 QColor highlightedOutline = d->highlightedOutline(option->palette);
463
464 QColor tabFrameColor = d->tabFrameColor(option->palette);
465
466 switch (elem) {
467
468 // No frame drawn
469 case PE_FrameGroupBox:
470 {
471 QPixmap pixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/fusion_groupbox.png"));
472 int topMargin = 0;
473 auto control = dynamic_cast<const QGroupBox *>(widget);
474 if (control && !control->isCheckable() && control->title().isEmpty()) {
475 // Shrinking the topMargin if Not checkable AND title is empty
476 topMargin = groupBoxTopMargin;
477 } else {
478 topMargin = qMax(pixelMetric(PM_ExclusiveIndicatorHeight), option->fontMetrics.height()) + groupBoxTopMargin;
479 }
480 QRect frame = option->rect.adjusted(0, topMargin, 0, 0);
481 qDrawBorderPixmap(painter, frame, QMargins(6, 6, 6, 6), pixmap);
482 break;
483 }
484 case PE_IndicatorBranch: {
485 if (!(option->state & State_Children))
486 break;
487 if (option->state & State_Open)
488 drawPrimitive(PE_IndicatorArrowDown, option, painter, widget);
489 else {
490 const bool reverse = (option->direction == Qt::RightToLeft);
491 drawPrimitive(reverse ? PE_IndicatorArrowLeft : PE_IndicatorArrowRight, option, painter, widget);
492 }
493 break;
494 }
495#if QT_CONFIG(tabbar)
496 case PE_FrameTabBarBase:
497 if (const QStyleOptionTabBarBase *tbb
498 = qstyleoption_cast<const QStyleOptionTabBarBase *>(option)) {
499 painter->save();
500 painter->setPen(QPen(outline.lighter(110)));
501 switch (tbb->shape) {
502 case QTabBar::RoundedNorth: {
503 QRegion region(tbb->rect);
504 region -= tbb->selectedTabRect;
505 painter->drawLine(tbb->rect.topLeft(), tbb->rect.topRight());
506 painter->setClipRegion(region);
507 painter->setPen(option->palette.light().color());
508 painter->drawLine(tbb->rect.topLeft() + QPoint(0, 1), tbb->rect.topRight() + QPoint(0, 1));
509 }
510 break;
511 case QTabBar::RoundedWest:
512 painter->drawLine(tbb->rect.left(), tbb->rect.top(), tbb->rect.left(), tbb->rect.bottom());
513 break;
514 case QTabBar::RoundedSouth:
515 painter->drawLine(tbb->rect.left(), tbb->rect.bottom(),
516 tbb->rect.right(), tbb->rect.bottom());
517 break;
518 case QTabBar::RoundedEast:
519 painter->drawLine(tbb->rect.topRight(), tbb->rect.bottomRight());
520 break;
521 case QTabBar::TriangularNorth:
522 case QTabBar::TriangularEast:
523 case QTabBar::TriangularWest:
524 case QTabBar::TriangularSouth:
525 painter->restore();
526 QCommonStyle::drawPrimitive(elem, option, painter, widget);
527 return;
528 }
529 painter->restore();
530 }
531 return;
532#endif // QT_CONFIG(tabbar)
533 case PE_PanelScrollAreaCorner: {
534 painter->save();
535 QColor alphaOutline = outline;
536 alphaOutline.setAlpha(180);
537 painter->setPen(alphaOutline);
538 painter->setBrush(option->palette.brush(QPalette::Window));
539 painter->drawRect(option->rect);
540 painter->restore();
541 } break;
542 case PE_IndicatorArrowUp:
543 case PE_IndicatorArrowDown:
544 case PE_IndicatorArrowRight:
545 case PE_IndicatorArrowLeft:
546 {
547 if (option->rect.width() <= 1 || option->rect.height() <= 1)
548 break;
549 QColor arrowColor = option->palette.windowText().color();
550 arrowColor.setAlpha(160);
551 Qt::ArrowType arrow = Qt::UpArrow;
552 switch (elem) {
553 case PE_IndicatorArrowDown:
554 arrow = Qt::DownArrow;
555 break;
556 case PE_IndicatorArrowRight:
557 arrow = Qt::RightArrow;
558 break;
559 case PE_IndicatorArrowLeft:
560 arrow = Qt::LeftArrow;
561 break;
562 default:
563 break;
564 }
565 qt_fusion_draw_arrow(arrow, painter, option, option->rect, arrowColor);
566 }
567 break;
568 case PE_IndicatorItemViewItemCheck:
569 {
570 QStyleOptionButton button;
571 button.QStyleOption::operator=(*option);
572 button.state &= ~State_MouseOver;
573 proxy()->drawPrimitive(PE_IndicatorCheckBox, &button, painter, widget);
574 }
575 return;
576 case PE_IndicatorHeaderArrow:
577 if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) {
578 QRect r = header->rect;
579 QColor arrowColor = header->palette.windowText().color();
580 arrowColor.setAlpha(180);
581 QPoint offset = QPoint(0, -2);
582
583#if defined(Q_OS_LINUX)
584 if (header->sortIndicator & QStyleOptionHeader::SortUp) {
585 qt_fusion_draw_arrow(Qt::UpArrow, painter, option, r.translated(offset), arrowColor);
586 } else if (header->sortIndicator & QStyleOptionHeader::SortDown) {
587 qt_fusion_draw_arrow(Qt::DownArrow, painter, option, r.translated(offset), arrowColor);
588 }
589#else
590 if (header->sortIndicator & QStyleOptionHeader::SortUp) {
591 qt_fusion_draw_arrow(Qt::DownArrow, painter, option, r.translated(offset), arrowColor);
592 } else if (header->sortIndicator & QStyleOptionHeader::SortDown) {
593 qt_fusion_draw_arrow(Qt::UpArrow, painter, option, r.translated(offset), arrowColor);
594 }
595#endif
596 }
597 break;
598 case PE_IndicatorButtonDropDown:
599 proxy()->drawPrimitive(PE_PanelButtonCommand, option, painter, widget);
600 break;
601
602 case PE_IndicatorToolBarSeparator:
603 {
604 QRect rect = option->rect;
605 const int margin = 6;
606 if (option->state & State_Horizontal) {
607 const int offset = rect.width()/2;
608 painter->setPen(QPen(option->palette.window().color().darker(110)));
609 painter->drawLine(rect.bottomLeft().x() + offset,
610 rect.bottomLeft().y() - margin,
611 rect.topLeft().x() + offset,
612 rect.topLeft().y() + margin);
613 painter->setPen(QPen(option->palette.window().color().lighter(110)));
614 painter->drawLine(rect.bottomLeft().x() + offset + 1,
615 rect.bottomLeft().y() - margin,
616 rect.topLeft().x() + offset + 1,
617 rect.topLeft().y() + margin);
618 } else { //Draw vertical separator
619 const int offset = rect.height()/2;
620 painter->setPen(QPen(option->palette.window().color().darker(110)));
621 painter->drawLine(rect.topLeft().x() + margin ,
622 rect.topLeft().y() + offset,
623 rect.topRight().x() - margin,
624 rect.topRight().y() + offset);
625 painter->setPen(QPen(option->palette.window().color().lighter(110)));
626 painter->drawLine(rect.topLeft().x() + margin ,
627 rect.topLeft().y() + offset + 1,
628 rect.topRight().x() - margin,
629 rect.topRight().y() + offset + 1);
630 }
631 }
632 break;
633 case PE_Frame: {
634 if (widget && widget->inherits("QComboBoxPrivateContainer")){
635 QStyleOption copy = *option;
636 copy.state |= State_Raised;
637 proxy()->drawPrimitive(PE_PanelMenu, &copy, painter, widget);
638 break;
639 }
640 painter->save();
641 QPen thePen(outline.lighter(108));
642 thePen.setCosmetic(false);
643 painter->setPen(thePen);
644 painter->drawRect(option->rect.adjusted(0, 0, -1, -1));
645 painter->restore(); }
646 break;
647 case PE_FrameMenu:
648 painter->save();
649 {
650 painter->setPen(QPen(outline));
651 painter->drawRect(option->rect.adjusted(0, 0, -1, -1));
652 QColor frameLight = option->palette.window().color().lighter(160);
653 QColor frameShadow = option->palette.window().color().darker(110);
654
655 //paint beveleffect
656 QRect frame = option->rect.adjusted(1, 1, -1, -1);
657 painter->setPen(frameLight);
658 painter->drawLine(frame.topLeft(), frame.bottomLeft());
659 painter->drawLine(frame.topLeft(), frame.topRight());
660
661 painter->setPen(frameShadow);
662 painter->drawLine(frame.topRight(), frame.bottomRight());
663 painter->drawLine(frame.bottomLeft(), frame.bottomRight());
664 }
665 painter->restore();
666 break;
667 case PE_FrameDockWidget:
668
669 painter->save();
670 {
671 QColor softshadow = option->palette.window().color().darker(120);
672
673 QRect rect= option->rect;
674 painter->setPen(softshadow);
675 painter->drawRect(option->rect.adjusted(0, 0, -1, -1));
676 painter->setPen(QPen(option->palette.light(), 1));
677 painter->drawLine(QPoint(rect.left() + 1, rect.top() + 1), QPoint(rect.left() + 1, rect.bottom() - 1));
678 painter->setPen(QPen(option->palette.window().color().darker(120)));
679 painter->drawLine(QPoint(rect.left() + 1, rect.bottom() - 1), QPoint(rect.right() - 2, rect.bottom() - 1));
680 painter->drawLine(QPoint(rect.right() - 1, rect.top() + 1), QPoint(rect.right() - 1, rect.bottom() - 1));
681
682 }
683 painter->restore();
684 break;
685 case PE_PanelButtonTool:
686 painter->save();
687 if ((option->state & State_Enabled || option->state & State_On) || !(option->state & State_AutoRaise)) {
688 if (widget && widget->inherits("QDockWidgetTitleButton")) {
689 if (option->state & State_MouseOver)
690 proxy()->drawPrimitive(PE_PanelButtonCommand, option, painter, widget);
691 } else {
692 proxy()->drawPrimitive(PE_PanelButtonCommand, option, painter, widget);
693 }
694 }
695 painter->restore();
696 break;
697 case PE_IndicatorDockWidgetResizeHandle:
698 {
699 QStyleOption dockWidgetHandle = *option;
700 bool horizontal = option->state & State_Horizontal;
701 dockWidgetHandle.state.setFlag(State_Horizontal, !horizontal);
702 proxy()->drawControl(CE_Splitter, &dockWidgetHandle, painter, widget);
703 }
704 break;
705 case PE_FrameWindow:
706 painter->save();
707 {
708 QRect rect= option->rect;
709 painter->setPen(QPen(outline.darker(150)));
710 painter->drawRect(option->rect.adjusted(0, 0, -1, -1));
711 painter->setPen(QPen(option->palette.light(), 1));
712 painter->drawLine(QPoint(rect.left() + 1, rect.top() + 1),
713 QPoint(rect.left() + 1, rect.bottom() - 1));
714 painter->setPen(QPen(option->palette.window().color().darker(120)));
715 painter->drawLine(QPoint(rect.left() + 1, rect.bottom() - 1),
716 QPoint(rect.right() - 2, rect.bottom() - 1));
717 painter->drawLine(QPoint(rect.right() - 1, rect.top() + 1),
718 QPoint(rect.right() - 1, rect.bottom() - 1));
719 }
720 painter->restore();
721 break;
722 case PE_FrameLineEdit:
723 {
724 QRect r = rect;
725 bool hasFocus = option->state & State_HasFocus;
726
727 painter->save();
728
729 painter->setRenderHint(QPainter::Antialiasing, true);
730 // ### highdpi painter bug.
731 painter->translate(0.5, 0.5);
732
733 // Draw Outline
734 painter->setPen( QPen(hasFocus ? highlightedOutline : outline));
735 painter->drawRoundedRect(r.adjusted(0, 0, -1, -1), 2, 2);
736
737 if (hasFocus) {
738 QColor softHighlight = highlightedOutline;
739 softHighlight.setAlpha(40);
740 painter->setPen(softHighlight);
741 painter->drawRoundedRect(r.adjusted(1, 1, -2, -2), 1.7, 1.7);
742 }
743 // Draw inner shadow
744 painter->setPen(d->topShadow());
745 painter->drawLine(QPoint(r.left() + 2, r.top() + 1), QPoint(r.right() - 2, r.top() + 1));
746
747 painter->restore();
748
749 }
750 break;
751 case PE_IndicatorCheckBox:
752 painter->save();
753 if (const QStyleOptionButton *checkbox = qstyleoption_cast<const QStyleOptionButton*>(option)) {
754 painter->setRenderHint(QPainter::Antialiasing, true);
755 painter->translate(0.5, 0.5);
756 rect = rect.adjusted(0, 0, -1, -1);
757
758 QColor pressedColor = mergedColors(option->palette.base().color(), option->palette.windowText().color(), 85);
759 painter->setBrush(Qt::NoBrush);
760
761 // Gradient fill
762 QLinearGradient gradient(rect.topLeft(), rect.bottomLeft());
763 gradient.setColorAt(0, (state & State_Sunken) ? pressedColor : option->palette.base().color().darker(115));
764 gradient.setColorAt(0.15, (state & State_Sunken) ? pressedColor : option->palette.base().color());
765 gradient.setColorAt(1, (state & State_Sunken) ? pressedColor : option->palette.base().color());
766
767 painter->setBrush((state & State_Sunken) ? QBrush(pressedColor) : gradient);
768 painter->setPen(QPen(outline.lighter(110)));
769
770 if (option->state & State_HasFocus && option->state & State_KeyboardFocusChange)
771 painter->setPen(QPen(highlightedOutline));
772 painter->drawRect(rect);
773
774 QColor checkMarkColor = option->palette.text().color().darker(120);
775 const qreal checkMarkPadding = 1 + rect.width() * 0.13; // at least one pixel padding
776
777 if (checkbox->state & State_NoChange) {
778 gradient = QLinearGradient(rect.topLeft(), rect.bottomLeft());
779 checkMarkColor.setAlpha(80);
780 gradient.setColorAt(0, checkMarkColor);
781 checkMarkColor.setAlpha(140);
782 gradient.setColorAt(1, checkMarkColor);
783 checkMarkColor.setAlpha(180);
784 painter->setPen(QPen(checkMarkColor, 1));
785 painter->setBrush(gradient);
786 painter->drawRect(rect.adjusted(checkMarkPadding, checkMarkPadding, -checkMarkPadding, -checkMarkPadding));
787
788 } else if (checkbox->state & State_On) {
789 qreal penWidth = QStyleHelper::dpiScaled(1.5);
790 penWidth = qMax<qreal>(penWidth, 0.13 * rect.height());
791 penWidth = qMin<qreal>(penWidth, 0.20 * rect.height());
792 QPen checkPen = QPen(checkMarkColor, penWidth);
793 checkMarkColor.setAlpha(210);
794 painter->translate(dpiScaled(-0.8), dpiScaled(0.5));
795 painter->setPen(checkPen);
796 painter->setBrush(Qt::NoBrush);
797
798 // Draw checkmark
799 QPainterPath path;
800 const qreal rectHeight = rect.height(); // assuming height equals width
801 path.moveTo(checkMarkPadding + rectHeight * 0.11, rectHeight * 0.47);
802 path.lineTo(rectHeight * 0.5, rectHeight - checkMarkPadding);
803 path.lineTo(rectHeight - checkMarkPadding, checkMarkPadding);
804 painter->drawPath(path.translated(rect.topLeft()));
805 }
806 }
807 painter->restore();
808 break;
809 case PE_IndicatorRadioButton:
810 painter->save();
811 {
812 QColor pressedColor = mergedColors(option->palette.base().color(), option->palette.windowText().color(), 85);
813 painter->setBrush((state & State_Sunken) ? pressedColor : option->palette.base().color());
814 painter->setRenderHint(QPainter::Antialiasing, true);
815 QPainterPath circle;
816 const QPointF circleCenter = rect.center() + QPoint(1, 1);
817 const qreal outlineRadius = (rect.width() + (rect.width() + 1) % 2) / 2.0 - 1;
818 circle.addEllipse(circleCenter, outlineRadius, outlineRadius);
819 painter->setPen(QPen(option->palette.window().color().darker(150)));
820 if (option->state & State_HasFocus && option->state & State_KeyboardFocusChange)
821 painter->setPen(QPen(highlightedOutline));
822 painter->drawPath(circle);
823
824 if (state & (State_On )) {
825 circle = QPainterPath();
826 const qreal checkmarkRadius = outlineRadius / 2.32;
827 circle.addEllipse(circleCenter, checkmarkRadius, checkmarkRadius);
828 QColor checkMarkColor = option->palette.text().color().darker(120);
829 checkMarkColor.setAlpha(200);
830 painter->setPen(checkMarkColor);
831 checkMarkColor.setAlpha(180);
832 painter->setBrush(checkMarkColor);
833 painter->drawPath(circle);
834 }
835 }
836 painter->restore();
837 break;
838 case PE_IndicatorToolBarHandle:
839 {
840 //draw grips
841 if (option->state & State_Horizontal) {
842 for (int i = -3 ; i < 2 ; i += 3) {
843 for (int j = -8 ; j < 10 ; j += 3) {
844 painter->fillRect(rect.center().x() + i, rect.center().y() + j, 2, 2, d->lightShade());
845 painter->fillRect(rect.center().x() + i, rect.center().y() + j, 1, 1, d->darkShade());
846 }
847 }
848 } else { //vertical toolbar
849 for (int i = -6 ; i < 12 ; i += 3) {
850 for (int j = -3 ; j < 2 ; j += 3) {
851 painter->fillRect(rect.center().x() + i, rect.center().y() + j, 2, 2, d->lightShade());
852 painter->fillRect(rect.center().x() + i, rect.center().y() + j, 1, 1, d->darkShade());
853 }
854 }
855 }
856 break;
857 }
858 case PE_FrameDefaultButton:
859 break;
860 case PE_FrameFocusRect:
861 if (const QStyleOptionFocusRect *fropt = qstyleoption_cast<const QStyleOptionFocusRect *>(option)) {
862 //### check for d->alt_down
863 if (!(fropt->state & State_KeyboardFocusChange))
864 return;
865 QRect rect = option->rect;
866
867 painter->save();
868 painter->setRenderHint(QPainter::Antialiasing, true);
869 painter->translate(0.5, 0.5);
870 QColor fillcolor = highlightedOutline;
871 fillcolor.setAlpha(80);
872 painter->setPen(fillcolor.darker(120));
873 fillcolor.setAlpha(30);
874 QLinearGradient gradient(rect.topLeft(), rect.bottomLeft());
875 gradient.setColorAt(0, fillcolor.lighter(160));
876 gradient.setColorAt(1, fillcolor);
877 painter->setBrush(gradient);
878 painter->drawRoundedRect(option->rect.adjusted(0, 0, -1, -1), 1, 1);
879 painter->restore();
880 }
881 break;
882 case PE_PanelButtonCommand:
883 {
884 bool isDefault = false;
885 bool isFlat = false;
886 bool isDown = (option->state & State_Sunken) || (option->state & State_On);
887 QRect r;
888
889 if (const QStyleOptionButton *button = qstyleoption_cast<const QStyleOptionButton*>(option)) {
890 isDefault = (button->features & QStyleOptionButton::DefaultButton) && (button->state & State_Enabled);
891 isFlat = (button->features & QStyleOptionButton::Flat);
892 }
893
894 if (isFlat && !isDown) {
895 if (isDefault) {
896 r = option->rect.adjusted(0, 1, 0, -1);
897 painter->setPen(QPen(Qt::black));
898 const QLine lines[4] = {
899 QLine(QPoint(r.left() + 2, r.top()),
900 QPoint(r.right() - 2, r.top())),
901 QLine(QPoint(r.left(), r.top() + 2),
902 QPoint(r.left(), r.bottom() - 2)),
903 QLine(QPoint(r.right(), r.top() + 2),
904 QPoint(r.right(), r.bottom() - 2)),
905 QLine(QPoint(r.left() + 2, r.bottom()),
906 QPoint(r.right() - 2, r.bottom()))
907 };
908 painter->drawLines(lines, 4);
909 const QPoint points[4] = {
910 QPoint(r.right() - 1, r.bottom() - 1),
911 QPoint(r.right() - 1, r.top() + 1),
912 QPoint(r.left() + 1, r.bottom() - 1),
913 QPoint(r.left() + 1, r.top() + 1)
914 };
915 painter->drawPoints(points, 4);
916 }
917 return;
918 }
919
920
921 bool isEnabled = option->state & State_Enabled;
922 bool hasFocus = (option->state & State_HasFocus && option->state & State_KeyboardFocusChange);
923 QColor buttonColor = d->buttonColor(option->palette);
924
925 QColor darkOutline = outline;
926 if (hasFocus | isDefault) {
927 darkOutline = highlightedOutline;
928 }
929
930 if (isDefault)
931 buttonColor = mergedColors(buttonColor, highlightedOutline.lighter(130), 90);
932
933 BEGIN_STYLE_PIXMAPCACHE(QStringLiteral("pushbutton-") + buttonColor.name(QColor::HexArgb))
934 r = rect.adjusted(0, 1, -1, 0);
935
936 p->setRenderHint(QPainter::Antialiasing, true);
937 p->translate(0.5, -0.5);
938
939 QLinearGradient gradient = qt_fusion_gradient(rect, (isEnabled && option->state & State_MouseOver ) ? buttonColor : buttonColor.darker(104));
940 p->setPen(Qt::transparent);
941 p->setBrush(isDown ? QBrush(buttonColor.darker(110)) : gradient);
942 p->drawRoundedRect(r, 2.0, 2.0);
943 p->setBrush(Qt::NoBrush);
944
945 // Outline
946 p->setPen(!isEnabled ? QPen(darkOutline.lighter(115)) : QPen(darkOutline));
947 p->drawRoundedRect(r, 2.0, 2.0);
948
949 p->setPen(d->innerContrastLine());
950 p->drawRoundedRect(r.adjusted(1, 1, -1, -1), 2.0, 2.0);
951
952 END_STYLE_PIXMAPCACHE
953 }
954 break;
955 case PE_FrameTabWidget:
956 painter->save();
957 painter->fillRect(option->rect.adjusted(0, 0, -1, -1), tabFrameColor);
958#if QT_CONFIG(tabwidget)
959 if (const QStyleOptionTabWidgetFrame *twf = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(option)) {
960 QColor borderColor = outline.lighter(110);
961 QRect rect = option->rect.adjusted(0, 0, -1, -1);
962
963 // Shadow outline
964 if (twf->shape != QTabBar::RoundedSouth) {
965 rect.adjust(0, 0, 0, -1);
966 QColor alphaShadow(Qt::black);
967 alphaShadow.setAlpha(15);
968 painter->setPen(alphaShadow);
969 painter->drawLine(option->rect.bottomLeft(), option->rect.bottomRight()); painter->setPen(borderColor);
970 }
971
972 // outline
973 painter->setPen(outline);
974 painter->drawRect(rect);
975
976 // Inner frame highlight
977 painter->setPen(d->innerContrastLine());
978 painter->drawRect(rect.adjusted(1, 1, -1, -1));
979
980 }
981#endif // QT_CONFIG(tabwidget)
982 painter->restore();
983 break ;
984
985 case PE_FrameStatusBarItem:
986 break;
987 case PE_IndicatorTabClose:
988 {
989 Q_D(const QFusionStyle);
990 if (d->tabBarcloseButtonIcon.isNull())
991 d->tabBarcloseButtonIcon = proxy()->standardIcon(SP_DialogCloseButton, option, widget);
992 if ((option->state & State_Enabled) && (option->state & State_MouseOver))
993 proxy()->drawPrimitive(PE_PanelButtonCommand, option, painter, widget);
994 QPixmap pixmap = d->tabBarcloseButtonIcon.pixmap(QSize(16, 16), QIcon::Normal, QIcon::On);
995 proxy()->drawItemPixmap(painter, option->rect, Qt::AlignCenter, pixmap);
996 }
997 break;
998 case PE_PanelMenu: {
999 painter->save();
1000 const QBrush menuBackground = option->palette.base().color().lighter(108);
1001 QColor borderColor = option->palette.window().color().darker(160);
1002 qDrawPlainRect(painter, option->rect, borderColor, 1, &menuBackground);
1003 painter->restore();
1004 }
1005 break;
1006
1007 default:
1008 QCommonStyle::drawPrimitive(elem, option, painter, widget);
1009 break;
1010 }
1011}
1012
1013/*!
1014 \reimp
1015*/
1016void QFusionStyle::drawControl(ControlElement element, const QStyleOption *option, QPainter *painter,
1017 const QWidget *widget) const
1018{
1019 Q_D (const QFusionStyle);
1020 QRect rect = option->rect;
1021 QColor outline = d->outline(option->palette);
1022 QColor highlightedOutline = d->highlightedOutline(option->palette);
1023 QColor shadow = d->darkShade();
1024
1025 switch (element) {
1026 case CE_ComboBoxLabel:
1027 if (const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
1028 QRect editRect = proxy()->subControlRect(CC_ComboBox, cb, SC_ComboBoxEditField, widget);
1029 painter->save();
1030 painter->setClipRect(editRect);
1031 if (!cb->currentIcon.isNull()) {
1032 QIcon::Mode mode = cb->state & State_Enabled ? QIcon::Normal
1033 : QIcon::Disabled;
1034 QPixmap pixmap = cb->currentIcon.pixmap(cb->iconSize, mode);
1035 QRect iconRect(editRect);
1036 iconRect.setWidth(cb->iconSize.width() + 4);
1037 iconRect = alignedRect(cb->direction,
1038 Qt::AlignLeft | Qt::AlignVCenter,
1039 iconRect.size(), editRect);
1040 if (cb->editable)
1041 painter->fillRect(iconRect, cb->palette.brush(QPalette::Base));
1042 proxy()->drawItemPixmap(painter, iconRect, Qt::AlignCenter, pixmap);
1043
1044 if (cb->direction == Qt::RightToLeft)
1045 editRect.translate(-4 - cb->iconSize.width(), 0);
1046 else
1047 editRect.translate(cb->iconSize.width() + 4, 0);
1048 }
1049 if (!cb->currentText.isEmpty() && !cb->editable) {
1050 proxy()->drawItemText(painter, editRect.adjusted(1, 0, -1, 0),
1051 visualAlignment(cb->direction, Qt::AlignLeft | Qt::AlignVCenter),
1052 cb->palette, cb->state & State_Enabled, cb->currentText,
1053 cb->editable ? QPalette::Text : QPalette::ButtonText);
1054 }
1055 painter->restore();
1056 }
1057 break;
1058 case CE_Splitter:
1059 {
1060 // Don't draw handle for single pixel splitters
1061 if (option->rect.width() > 1 && option->rect.height() > 1) {
1062 //draw grips
1063 if (option->state & State_Horizontal) {
1064 for (int j = -6 ; j< 12 ; j += 3) {
1065 painter->fillRect(rect.center().x() + 1, rect.center().y() + j, 2, 2, d->lightShade());
1066 painter->fillRect(rect.center().x() + 1, rect.center().y() + j, 1, 1, d->darkShade());
1067 }
1068 } else {
1069 for (int i = -6; i< 12 ; i += 3) {
1070 painter->fillRect(rect.center().x() + i, rect.center().y(), 2, 2, d->lightShade());
1071 painter->fillRect(rect.center().x() + i, rect.center().y(), 1, 1, d->darkShade());
1072 }
1073 }
1074 }
1075 break;
1076 }
1077#if QT_CONFIG(rubberband)
1078 case CE_RubberBand:
1079 if (qstyleoption_cast<const QStyleOptionRubberBand *>(option)) {
1080 QColor highlight = option->palette.color(QPalette::Active, QPalette::Highlight);
1081 painter->save();
1082 QColor penColor = highlight.darker(120);
1083 penColor.setAlpha(180);
1084 painter->setPen(penColor);
1085 QColor dimHighlight(qMin(highlight.red()/2 + 110, 255),
1086 qMin(highlight.green()/2 + 110, 255),
1087 qMin(highlight.blue()/2 + 110, 255));
1088 dimHighlight.setAlpha(widget && widget->isTopLevel() ? 255 : 80);
1089 QLinearGradient gradient(rect.topLeft(), QPoint(rect.bottomLeft().x(), rect.bottomLeft().y()));
1090 gradient.setColorAt(0, dimHighlight.lighter(120));
1091 gradient.setColorAt(1, dimHighlight);
1092 painter->setRenderHint(QPainter::Antialiasing, true);
1093 painter->translate(0.5, 0.5);
1094 painter->setBrush(dimHighlight);
1095 painter->drawRoundedRect(option->rect.adjusted(0, 0, -1, -1), 1, 1);
1096 QColor innerLine = Qt::white;
1097 innerLine.setAlpha(40);
1098 painter->setPen(innerLine);
1099 painter->drawRoundedRect(option->rect.adjusted(1, 1, -2, -2), 1, 1);
1100 painter->restore();
1101 }
1102 break;
1103#endif //QT_CONFIG(rubberband)
1104 case CE_SizeGrip:
1105 painter->save();
1106 {
1107 //draw grips
1108 for (int i = -6; i< 12 ; i += 3) {
1109 for (int j = -6 ; j< 12 ; j += 3) {
1110 if ((option->direction == Qt::LeftToRight && i > -j) || (option->direction == Qt::RightToLeft && j > i) ) {
1111 painter->fillRect(rect.center().x() + i, rect.center().y() + j, 2, 2, d->lightShade());
1112 painter->fillRect(rect.center().x() + i, rect.center().y() + j, 1, 1, d->darkShade());
1113 }
1114 }
1115 }
1116 }
1117 painter->restore();
1118 break;
1119#if QT_CONFIG(toolbar)
1120 case CE_ToolBar:
1121 if (const QStyleOptionToolBar *toolBar = qstyleoption_cast<const QStyleOptionToolBar *>(option)) {
1122 // Reserve the beveled appearance only for mainwindow toolbars
1123 if (widget && !(qobject_cast<const QMainWindow*> (widget->parentWidget())))
1124 break;
1125
1126 // Draws the light line above and the dark line below menu bars and
1127 // tool bars.
1128 QLinearGradient gradient(option->rect.topLeft(), option->rect.bottomLeft());
1129 if (!(option->state & State_Horizontal))
1130 gradient = QLinearGradient(rect.left(), rect.center().y(),
1131 rect.right(), rect.center().y());
1132 gradient.setColorAt(0, option->palette.window().color().lighter(104));
1133 gradient.setColorAt(1, option->palette.window().color());
1134 painter->fillRect(option->rect, gradient);
1135
1136 QColor light = d->lightShade();
1137 QColor shadow = d->darkShade();
1138
1139 QPen oldPen = painter->pen();
1140 if (toolBar->toolBarArea == Qt::TopToolBarArea) {
1141 if (toolBar->positionOfLine == QStyleOptionToolBar::End
1142 || toolBar->positionOfLine == QStyleOptionToolBar::OnlyOne) {
1143 // The end and onlyone top toolbar lines draw a double
1144 // line at the bottom to blend with the central
1145 // widget.
1146 painter->setPen(light);
1147 painter->drawLine(option->rect.bottomLeft(), option->rect.bottomRight());
1148 painter->setPen(shadow);
1149 painter->drawLine(option->rect.left(), option->rect.bottom() - 1,
1150 option->rect.right(), option->rect.bottom() - 1);
1151 } else {
1152 // All others draw a single dark line at the bottom.
1153 painter->setPen(shadow);
1154 painter->drawLine(option->rect.bottomLeft(), option->rect.bottomRight());
1155 }
1156 // All top toolbar lines draw a light line at the top.
1157 painter->setPen(light);
1158 painter->drawLine(option->rect.topLeft(), option->rect.topRight());
1159 } else if (toolBar->toolBarArea == Qt::BottomToolBarArea) {
1160 if (toolBar->positionOfLine == QStyleOptionToolBar::End
1161 || toolBar->positionOfLine == QStyleOptionToolBar::Middle) {
1162 // The end and middle bottom tool bar lines draw a dark
1163 // line at the bottom.
1164 painter->setPen(shadow);
1165 painter->drawLine(option->rect.bottomLeft(), option->rect.bottomRight());
1166 }
1167 if (toolBar->positionOfLine == QStyleOptionToolBar::Beginning
1168 || toolBar->positionOfLine == QStyleOptionToolBar::OnlyOne) {
1169 // The beginning and only one tool bar lines draw a
1170 // double line at the bottom to blend with the
1171 // status bar.
1172 // ### The styleoption could contain whether the
1173 // main window has a menu bar and a status bar, and
1174 // possibly dock widgets.
1175 painter->setPen(shadow);
1176 painter->drawLine(option->rect.left(), option->rect.bottom() - 1,
1177 option->rect.right(), option->rect.bottom() - 1);
1178 painter->setPen(light);
1179 painter->drawLine(option->rect.bottomLeft(), option->rect.bottomRight());
1180 }
1181 if (toolBar->positionOfLine == QStyleOptionToolBar::End) {
1182 painter->setPen(shadow);
1183 painter->drawLine(option->rect.topLeft(), option->rect.topRight());
1184 painter->setPen(light);
1185 painter->drawLine(option->rect.left(), option->rect.top() + 1,
1186 option->rect.right(), option->rect.top() + 1);
1187
1188 } else {
1189 // All other bottom toolbars draw a light line at the top.
1190 painter->setPen(light);
1191 painter->drawLine(option->rect.topLeft(), option->rect.topRight());
1192 }
1193 }
1194 if (toolBar->toolBarArea == Qt::LeftToolBarArea) {
1195 if (toolBar->positionOfLine == QStyleOptionToolBar::Middle
1196 || toolBar->positionOfLine == QStyleOptionToolBar::End) {
1197 // The middle and left end toolbar lines draw a light
1198 // line to the left.
1199 painter->setPen(light);
1200 painter->drawLine(option->rect.topLeft(), option->rect.bottomLeft());
1201 }
1202 if (toolBar->positionOfLine == QStyleOptionToolBar::End) {
1203 // All other left toolbar lines draw a dark line to the right
1204 painter->setPen(shadow);
1205 painter->drawLine(option->rect.right() - 1, option->rect.top(),
1206 option->rect.right() - 1, option->rect.bottom());
1207 painter->setPen(light);
1208 painter->drawLine(option->rect.topRight(), option->rect.bottomRight());
1209 } else {
1210 // All other left toolbar lines draw a dark line to the right
1211 painter->setPen(shadow);
1212 painter->drawLine(option->rect.topRight(), option->rect.bottomRight());
1213 }
1214 } else if (toolBar->toolBarArea == Qt::RightToolBarArea) {
1215 if (toolBar->positionOfLine == QStyleOptionToolBar::Middle
1216 || toolBar->positionOfLine == QStyleOptionToolBar::End) {
1217 // Right middle and end toolbar lines draw the dark right line
1218 painter->setPen(shadow);
1219 painter->drawLine(option->rect.topRight(), option->rect.bottomRight());
1220 }
1221 if (toolBar->positionOfLine == QStyleOptionToolBar::End
1222 || toolBar->positionOfLine == QStyleOptionToolBar::OnlyOne) {
1223 // The right end and single toolbar draws the dark
1224 // line on its left edge
1225 painter->setPen(shadow);
1226 painter->drawLine(option->rect.topLeft(), option->rect.bottomLeft());
1227 // And a light line next to it
1228 painter->setPen(light);
1229 painter->drawLine(option->rect.left() + 1, option->rect.top(),
1230 option->rect.left() + 1, option->rect.bottom());
1231 } else {
1232 // Other right toolbars draw a light line on its left edge
1233 painter->setPen(light);
1234 painter->drawLine(option->rect.topLeft(), option->rect.bottomLeft());
1235 }
1236 }
1237 painter->setPen(oldPen);
1238 }
1239 break;
1240#endif // QT_CONFIG(toolbar)
1241 case CE_DockWidgetTitle:
1242 painter->save();
1243 if (const QStyleOptionDockWidget *dwOpt = qstyleoption_cast<const QStyleOptionDockWidget *>(option)) {
1244 bool verticalTitleBar = dwOpt->verticalTitleBar;
1245
1246 QRect titleRect = subElementRect(SE_DockWidgetTitleBarText, option, widget);
1247 if (verticalTitleBar) {
1248 QRect rect = dwOpt->rect;
1249 QRect r = rect.transposed();
1250 titleRect = QRect(r.left() + rect.bottom()
1251 - titleRect.bottom(),
1252 r.top() + titleRect.left() - rect.left(),
1253 titleRect.height(), titleRect.width());
1254
1255 painter->translate(r.left(), r.top() + r.width());
1256 painter->rotate(-90);
1257 painter->translate(-r.left(), -r.top());
1258 }
1259
1260 if (!dwOpt->title.isEmpty()) {
1261 QString titleText
1262 = painter->fontMetrics().elidedText(dwOpt->title,
1263 Qt::ElideRight, titleRect.width());
1264 proxy()->drawItemText(painter,
1265 titleRect,
1266 Qt::AlignLeft | Qt::AlignVCenter, dwOpt->palette,
1267 dwOpt->state & State_Enabled, titleText,
1268 QPalette::WindowText);
1269 }
1270 }
1271 painter->restore();
1272 break;
1273 case CE_HeaderSection:
1274 painter->save();
1275 // Draws the header in tables.
1276 if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) {
1277 QString pixmapName = QStyleHelper::uniqueName(QLatin1String("headersection"), option, option->rect.size());
1278 pixmapName += QString::number(- int(header->position));
1279 pixmapName += QString::number(- int(header->orientation));
1280
1281 QPixmap cache;
1282 if (!QPixmapCache::find(pixmapName, &cache)) {
1283 cache = styleCachePixmap(rect.size());
1284 cache.fill(Qt::transparent);
1285 QRect pixmapRect(0, 0, rect.width(), rect.height());
1286 QPainter cachePainter(&cache);
1287 QColor buttonColor = d->buttonColor(option->palette);
1288 QColor gradientStopColor;
1289 QColor gradientStartColor = buttonColor.lighter(104);
1290 gradientStopColor = buttonColor.darker(102);
1291 QLinearGradient gradient(pixmapRect.topLeft(), pixmapRect.bottomLeft());
1292
1293 if (option->palette.window().gradient()) {
1294 gradient.setStops(option->palette.window().gradient()->stops());
1295 } else {
1296 QColor midColor1 = mergedColors(gradientStartColor, gradientStopColor, 60);
1297 QColor midColor2 = mergedColors(gradientStartColor, gradientStopColor, 40);
1298 gradient.setColorAt(0, gradientStartColor);
1299 gradient.setColorAt(0.5, midColor1);
1300 gradient.setColorAt(0.501, midColor2);
1301 gradient.setColorAt(0.92, gradientStopColor);
1302 gradient.setColorAt(1, gradientStopColor.darker(104));
1303 }
1304 cachePainter.fillRect(pixmapRect, gradient);
1305 cachePainter.setPen(d->innerContrastLine());
1306 cachePainter.setBrush(Qt::NoBrush);
1307 cachePainter.drawLine(pixmapRect.topLeft(), pixmapRect.topRight());
1308 cachePainter.setPen(d->outline(option->palette));
1309 cachePainter.drawLine(pixmapRect.bottomLeft(), pixmapRect.bottomRight());
1310
1311 if (header->orientation == Qt::Horizontal &&
1312 header->position != QStyleOptionHeader::End &&
1313 header->position != QStyleOptionHeader::OnlyOneSection) {
1314 cachePainter.setPen(QColor(0, 0, 0, 40));
1315 cachePainter.drawLine(pixmapRect.topRight(), pixmapRect.bottomRight() + QPoint(0, -1));
1316 cachePainter.setPen(d->innerContrastLine());
1317 cachePainter.drawLine(pixmapRect.topRight() + QPoint(-1, 0), pixmapRect.bottomRight() + QPoint(-1, -1));
1318 } else if (header->orientation == Qt::Vertical) {
1319 cachePainter.setPen(d->outline(option->palette));
1320 cachePainter.drawLine(pixmapRect.topRight(), pixmapRect.bottomRight());
1321 }
1322 cachePainter.end();
1323 QPixmapCache::insert(pixmapName, cache);
1324 }
1325 painter->drawPixmap(rect.topLeft(), cache);
1326 }
1327 painter->restore();
1328 break;
1329 case CE_ProgressBarGroove:
1330 painter->save();
1331 {
1332 painter->setRenderHint(QPainter::Antialiasing, true);
1333 painter->translate(0.5, 0.5);
1334
1335 QColor shadowAlpha = Qt::black;
1336 shadowAlpha.setAlpha(16);
1337 painter->setPen(shadowAlpha);
1338 painter->drawLine(rect.topLeft() - QPoint(0, 1), rect.topRight() - QPoint(0, 1));
1339
1340 painter->setBrush(option->palette.base());
1341 painter->setPen(QPen(outline));
1342 painter->drawRoundedRect(rect.adjusted(0, 0, -1, -1), 2, 2);
1343
1344 // Inner shadow
1345 painter->setPen(d->topShadow());
1346 painter->drawLine(QPoint(rect.left() + 1, rect.top() + 1),
1347 QPoint(rect.right() - 1, rect.top() + 1));
1348 }
1349 painter->restore();
1350 break;
1351 case CE_ProgressBarContents:
1352 painter->save();
1353 painter->setRenderHint(QPainter::Antialiasing, true);
1354 painter->translate(0.5, 0.5);
1355 if (const QStyleOptionProgressBar *bar = qstyleoption_cast<const QStyleOptionProgressBar *>(option)) {
1356 bool vertical = false;
1357 bool inverted = false;
1358 bool indeterminate = (bar->minimum == 0 && bar->maximum == 0);
1359 bool complete = bar->progress == bar->maximum;
1360
1361 // Get extra style options if version 2
1362 vertical = (bar->orientation == Qt::Vertical);
1363 inverted = bar->invertedAppearance;
1364
1365 // If the orientation is vertical, we use a transform to rotate
1366 // the progress bar 90 degrees clockwise. This way we can use the
1367 // same rendering code for both orientations.
1368 if (vertical) {
1369 rect = QRect(rect.left(), rect.top(), rect.height(), rect.width()); // flip width and height
1370 QTransform m = QTransform::fromTranslate(rect.height()-1, -1.0);
1371 m.rotate(90.0);
1372 painter->setTransform(m, true);
1373 }
1374
1375 int maxWidth = rect.width();
1376 const auto progress = qMax(bar->progress, bar->minimum); // workaround for bug in QProgressBar
1377 const auto totalSteps = qMax(Q_INT64_C(1), qint64(bar->maximum) - bar->minimum);
1378 const auto progressSteps = qint64(progress) - bar->minimum;
1379 const auto progressBarWidth = progressSteps * maxWidth / totalSteps;
1380 int width = indeterminate ? maxWidth : progressBarWidth;
1381
1382 bool reverse = (!vertical && (bar->direction == Qt::RightToLeft)) || vertical;
1383 if (inverted)
1384 reverse = !reverse;
1385
1386 int step = 0;
1387 QRect progressBar;
1388 QColor highlight = d->highlight(option->palette);
1389 QColor highlightedoutline = highlight.darker(140);
1390 if (qGray(outline.rgb()) > qGray(highlightedoutline.rgb()))
1391 outline = highlightedoutline;
1392
1393 if (!indeterminate) {
1394 QColor innerShadow(Qt::black);
1395 innerShadow.setAlpha(35);
1396 painter->setPen(innerShadow);
1397 if (!reverse) {
1398 progressBar.setRect(rect.left(), rect.top(), width - 1, rect.height() - 1);
1399 if (!complete) {
1400 painter->drawLine(progressBar.topRight() + QPoint(2, 1), progressBar.bottomRight() + QPoint(2, 0));
1401 painter->setPen(QPen(highlight.darker(140)));
1402 painter->drawLine(progressBar.topRight() + QPoint(1, 1), progressBar.bottomRight() + QPoint(1, 0));
1403 }
1404 } else {
1405 progressBar.setRect(rect.right() - width - 1, rect.top(), width + 2, rect.height() - 1);
1406 if (!complete) {
1407 painter->drawLine(progressBar.topLeft() + QPoint(-2, 1), progressBar.bottomLeft() + QPoint(-2, 0));
1408 painter->setPen(QPen(highlight.darker(140)));
1409 painter->drawLine(progressBar.topLeft() + QPoint(-1, 1), progressBar.bottomLeft() + QPoint(-1, 0));
1410 }
1411 }
1412 } else {
1413 progressBar.setRect(rect.left(), rect.top(), rect.width() - 1, rect.height() - 1);
1414 }
1415
1416 if (indeterminate || bar->progress > bar->minimum) {
1417
1418 painter->setPen(QPen(outline));
1419
1420 QColor highlightedGradientStartColor = highlight.lighter(120);
1421 QColor highlightedGradientStopColor = highlight;
1422 QLinearGradient gradient(rect.topLeft(), QPoint(rect.bottomLeft().x(), rect.bottomLeft().y()));
1423 gradient.setColorAt(0, highlightedGradientStartColor);
1424 gradient.setColorAt(1, highlightedGradientStopColor);
1425
1426 painter->setBrush(gradient);
1427
1428 painter->save();
1429 if (!complete && !indeterminate)
1430 painter->setClipRect(progressBar.adjusted(-1, -1, -1, 1));
1431 QRect fillRect = progressBar.adjusted( !indeterminate && !complete && reverse ? -2 : 0, 0,
1432 indeterminate || complete || reverse ? 0 : 2, 0);
1433 painter->drawRoundedRect(fillRect, 2, 2);
1434 painter->restore();
1435
1436 painter->setBrush(Qt::NoBrush);
1437 painter->setPen(QColor(255, 255, 255, 50));
1438 painter->drawRoundedRect(progressBar.adjusted(1, 1, -1, -1), 1, 1);
1439
1440 if (!indeterminate) {
1441#if QT_CONFIG(animation)
1442 (const_cast<QFusionStylePrivate*>(d))->stopAnimation(option->styleObject);
1443#endif
1444 } else {
1445 highlightedGradientStartColor.setAlpha(120);
1446 painter->setPen(QPen(highlightedGradientStartColor, 9.0));
1447 painter->setClipRect(progressBar.adjusted(1, 1, -1, -1));
1448#if QT_CONFIG(animation)
1449 if (QProgressStyleAnimation *animation = qobject_cast<QProgressStyleAnimation*>(d->animation(option->styleObject)))
1450 step = animation->animationStep() % 22;
1451 else
1452 (const_cast<QFusionStylePrivate*>(d))->startAnimation(new QProgressStyleAnimation(d->animationFps, option->styleObject));
1453#endif
1454 for (int x = progressBar.left() - rect.height(); x < rect.right() ; x += 22)
1455 painter->drawLine(x + step, progressBar.bottom() + 1,
1456 x + rect.height() + step, progressBar.top() - 2);
1457 }
1458 }
1459 }
1460 painter->restore();
1461 break;
1462 case CE_ProgressBarLabel:
1463 if (const QStyleOptionProgressBar *bar = qstyleoption_cast<const QStyleOptionProgressBar *>(option)) {
1464 QRect leftRect;
1465 QRect rect = bar->rect;
1466 QColor textColor = option->palette.text().color();
1467 QColor alternateTextColor = d->highlightedText(option->palette);
1468
1469 painter->save();
1470 bool vertical = false, inverted = false;
1471 vertical = (bar->orientation == Qt::Vertical);
1472 inverted = bar->invertedAppearance;
1473 if (vertical)
1474 rect = QRect(rect.left(), rect.top(), rect.height(), rect.width()); // flip width and height
1475 const auto totalSteps = qMax(Q_INT64_C(1), qint64(bar->maximum) - bar->minimum);
1476 const auto progressSteps = qint64(bar->progress) - bar->minimum;
1477 const auto progressIndicatorPos = progressSteps * rect.width() / totalSteps;
1478 if (progressIndicatorPos >= 0 && progressIndicatorPos <= rect.width())
1479 leftRect = QRect(rect.left(), rect.top(), progressIndicatorPos, rect.height());
1480 if (vertical)
1481 leftRect.translate(rect.width() - progressIndicatorPos, 0);
1482
1483 bool flip = (!vertical && (((bar->direction == Qt::RightToLeft) && !inverted) ||
1484 ((bar->direction == Qt::LeftToRight) && inverted)));
1485
1486 QRegion rightRect = rect;
1487 rightRect = rightRect.subtracted(leftRect);
1488 painter->setClipRegion(rightRect);
1489 painter->setPen(flip ? alternateTextColor : textColor);
1490 painter->drawText(rect, bar->text, QTextOption(Qt::AlignAbsolute | Qt::AlignHCenter | Qt::AlignVCenter));
1491 if (!leftRect.isNull()) {
1492 painter->setPen(flip ? textColor : alternateTextColor);
1493 painter->setClipRect(leftRect);
1494 painter->drawText(rect, bar->text, QTextOption(Qt::AlignAbsolute | Qt::AlignHCenter | Qt::AlignVCenter));
1495 }
1496 painter->restore();
1497 }
1498 break;
1499 case CE_MenuBarItem:
1500 painter->save();
1501 if (const QStyleOptionMenuItem *mbi = qstyleoption_cast<const QStyleOptionMenuItem *>(option))
1502 {
1503 QStyleOptionMenuItem item = *mbi;
1504 item.rect = mbi->rect.adjusted(0, 1, 0, -3);
1505 QColor highlightOutline = option->palette.highlight().color().darker(125);
1506 painter->fillRect(rect, option->palette.window());
1507
1508 QCommonStyle::drawControl(element, &item, painter, widget);
1509
1510 bool act = mbi->state & State_Selected && mbi->state & State_Sunken;
1511 bool dis = !(mbi->state & State_Enabled);
1512
1513 QRect r = option->rect;
1514 if (act) {
1515 painter->setBrush(option->palette.highlight().color());
1516 painter->setPen(QPen(highlightOutline));
1517 painter->drawRect(r.adjusted(0, 0, -1, -1));
1518
1519 // painter->drawRoundedRect(r.adjusted(1, 1, -1, -1), 2, 2);
1520
1521 //draw text
1522 QPalette::ColorRole textRole = dis ? QPalette::Text : QPalette::HighlightedText;
1523 uint alignment = Qt::AlignCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine;
1524 if (!styleHint(SH_UnderlineShortcut, mbi, widget))
1525 alignment |= Qt::TextHideMnemonic;
1526 proxy()->drawItemText(painter, item.rect, alignment, mbi->palette, mbi->state & State_Enabled, mbi->text, textRole);
1527 } else {
1528
1529 QColor shadow = mergedColors(option->palette.window().color().darker(120),
1530 outline.lighter(140), 60);
1531 painter->setPen(QPen(shadow));
1532 painter->drawLine(option->rect.bottomLeft(), option->rect.bottomRight());
1533 }
1534 }
1535 painter->restore();
1536 break;
1537 case CE_MenuItem:
1538 painter->save();
1539 // Draws one item in a popup menu.
1540 if (const QStyleOptionMenuItem *menuItem = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) {
1541 QColor highlightOutline = highlightedOutline;
1542 QColor highlight = option->palette.highlight().color();
1543 if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) {
1544 int w = 0;
1545 const int margin = QStyleHelper::dpiScaled(5);
1546 if (!menuItem->text.isEmpty()) {
1547 painter->setFont(menuItem->font);
1548 proxy()->drawItemText(painter, menuItem->rect.adjusted(margin, 0, -margin, 0), Qt::AlignLeft | Qt::AlignVCenter,
1549 menuItem->palette, menuItem->state & State_Enabled, menuItem->text,
1550 QPalette::Text);
1551 w = menuItem->fontMetrics.horizontalAdvance(menuItem->text) + margin;
1552 }
1553 painter->setPen(shadow.lighter(106));
1554 bool reverse = menuItem->direction == Qt::RightToLeft;
1555 painter->drawLine(menuItem->rect.left() + margin + (reverse ? 0 : w), menuItem->rect.center().y(),
1556 menuItem->rect.right() - margin - (reverse ? w : 0), menuItem->rect.center().y());
1557 painter->restore();
1558 break;
1559 }
1560 bool selected = menuItem->state & State_Selected && menuItem->state & State_Enabled;
1561 if (selected) {
1562 QRect r = option->rect;
1563 painter->fillRect(r, highlight);
1564 painter->setPen(QPen(highlightOutline));
1565 painter->drawRect(QRectF(r).adjusted(0.5, 0.5, -0.5, -0.5));
1566 }
1567 bool checkable = menuItem->checkType != QStyleOptionMenuItem::NotCheckable;
1568 bool checked = menuItem->checked;
1569 bool sunken = menuItem->state & State_Sunken;
1570 bool enabled = menuItem->state & State_Enabled;
1571
1572 bool ignoreCheckMark = false;
1573 const int checkColHOffset = windowsItemHMargin + windowsItemFrame - 1;
1574 int checkcol = qMax<int>(menuItem->rect.height() * 0.79,
1575 qMax<int>(menuItem->maxIconWidth, dpiScaled(21))); // icon checkbox's highlight column width
1576 if (
1577#if QT_CONFIG(combobox)
1578 qobject_cast<const QComboBox*>(widget) ||
1579#endif
1580 (option->styleObject && option->styleObject->property("_q_isComboBoxPopupItem").toBool()))
1581 ignoreCheckMark = true; //ignore the checkmarks provided by the QComboMenuDelegate
1582
1583 if (!ignoreCheckMark) {
1584 // Check, using qreal and QRectF to avoid error accumulation
1585 const qreal boxMargin = dpiScaled(3.5);
1586 const qreal boxWidth = checkcol - 2 * boxMargin;
1587 QRectF checkRectF(option->rect.left() + boxMargin + checkColHOffset, option->rect.center().y() - boxWidth/2 + 1, boxWidth, boxWidth);
1588 QRect checkRect = checkRectF.toRect();
1589 checkRect.setWidth(checkRect.height()); // avoid .toRect() round error results in non-perfect square
1590 checkRect = visualRect(menuItem->direction, menuItem->rect, checkRect);
1591 if (checkable) {
1592 if (menuItem->checkType & QStyleOptionMenuItem::Exclusive) {
1593 // Radio button
1594 if (checked || sunken) {
1595 painter->setRenderHint(QPainter::Antialiasing);
1596 painter->setPen(Qt::NoPen);
1597
1598 QPalette::ColorRole textRole = !enabled ? QPalette::Text:
1599 selected ? QPalette::HighlightedText : QPalette::ButtonText;
1600 painter->setBrush(option->palette.brush( option->palette.currentColorGroup(), textRole));
1601 const int adjustment = checkRect.height() * 0.3;
1602 painter->drawEllipse(checkRect.adjusted(adjustment, adjustment, -adjustment, -adjustment));
1603 }
1604 } else {
1605 // Check box
1606 if (menuItem->icon.isNull()) {
1607 QStyleOptionButton box;
1608 box.QStyleOption::operator=(*option);
1609 box.rect = checkRect;
1610 if (checked)
1611 box.state |= State_On;
1612 proxy()->drawPrimitive(PE_IndicatorCheckBox, &box, painter, widget);
1613 }
1614 }
1615 }
1616 } else { //ignore checkmark
1617 if (menuItem->icon.isNull())
1618 checkcol = 0;
1619 else
1620 checkcol = menuItem->maxIconWidth;
1621 }
1622
1623 // Text and icon, ripped from windows style
1624 bool dis = !(menuItem->state & State_Enabled);
1625 bool act = menuItem->state & State_Selected;
1626 const QStyleOption *opt = option;
1627 const QStyleOptionMenuItem *menuitem = menuItem;
1628
1629 QPainter *p = painter;
1630 QRect vCheckRect = visualRect(opt->direction, menuitem->rect,
1631 QRect(menuitem->rect.x() + checkColHOffset, menuitem->rect.y(),
1632 checkcol, menuitem->rect.height()));
1633 if (!menuItem->icon.isNull()) {
1634 QIcon::Mode mode = dis ? QIcon::Disabled : QIcon::Normal;
1635 if (act && !dis)
1636 mode = QIcon::Active;
1637 QPixmap pixmap;
1638
1639 int smallIconSize = proxy()->pixelMetric(PM_SmallIconSize, option, widget);
1640 QSize iconSize(smallIconSize, smallIconSize);
1641#if QT_CONFIG(combobox)
1642 if (const QComboBox *combo = qobject_cast<const QComboBox*>(widget))
1643 iconSize = combo->iconSize();
1644#endif
1645 if (checked)
1646 pixmap = menuItem->icon.pixmap(iconSize, mode, QIcon::On);
1647 else
1648 pixmap = menuItem->icon.pixmap(iconSize, mode);
1649
1650 const int pixw = pixmap.width() / pixmap.devicePixelRatio();
1651 const int pixh = pixmap.height() / pixmap.devicePixelRatio();
1652
1653 QRect pmr(0, 0, pixw, pixh);
1654 pmr.moveCenter(vCheckRect.center());
1655 painter->setPen(menuItem->palette.text().color());
1656 if (!ignoreCheckMark && checkable && checked) {
1657 QStyleOption opt = *option;
1658 if (act) {
1659 QColor activeColor = mergedColors(option->palette.window().color(),
1660 option->palette.highlight().color());
1661 opt.palette.setBrush(QPalette::Button, activeColor);
1662 }
1663 opt.state |= State_Sunken;
1664 opt.rect = vCheckRect;
1665 proxy()->drawPrimitive(PE_PanelButtonCommand, &opt, painter, widget);
1666 }
1667 painter->drawPixmap(pmr.topLeft(), pixmap);
1668 }
1669 if (selected) {
1670 painter->setPen(menuItem->palette.highlightedText().color());
1671 } else {
1672 painter->setPen(menuItem->palette.text().color());
1673 }
1674 int x, y, w, h;
1675 menuitem->rect.getRect(&x, &y, &w, &h);
1676 int tab = menuitem->tabWidth;
1677 QColor discol;
1678 if (dis) {
1679 discol = menuitem->palette.text().color();
1680 p->setPen(discol);
1681 }
1682 int xm = checkColHOffset + checkcol + windowsItemHMargin;
1683 int xpos = menuitem->rect.x() + xm;
1684
1685 QRect textRect(xpos, y + windowsItemVMargin, w - xm - windowsRightBorder - tab + 1, h - 2 * windowsItemVMargin);
1686 QRect vTextRect = visualRect(opt->direction, menuitem->rect, textRect);
1687 QStringRef s(&menuitem->text);
1688 if (!s.isEmpty()) { // draw text
1689 p->save();
1690 int t = s.indexOf(QLatin1Char('\t'));
1691 int text_flags = Qt::AlignVCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine;
1692 if (!styleHint(SH_UnderlineShortcut, menuitem, widget))
1693 text_flags |= Qt::TextHideMnemonic;
1694 text_flags |= Qt::AlignLeft;
1695 if (t >= 0) {
1696 QRect vShortcutRect = visualRect(opt->direction, menuitem->rect,
1697 QRect(textRect.topRight(), QPoint(menuitem->rect.right(), textRect.bottom())));
1698 const QString textToDraw = s.mid(t + 1).toString();
1699 if (dis && !act && proxy()->styleHint(SH_EtchDisabledText, option, widget)) {
1700 p->setPen(menuitem->palette.light().color());
1701 p->drawText(vShortcutRect.adjusted(1, 1, 1, 1), text_flags, textToDraw);
1702 p->setPen(discol);
1703 }
1704 p->drawText(vShortcutRect, text_flags, textToDraw);
1705 s = s.left(t);
1706 }
1707 QFont font = menuitem->font;
1708 // font may not have any "hard" flags set. We override
1709 // the point size so that when it is resolved against the device, this font will win.
1710 // This is mainly to handle cases where someone sets the font on the window
1711 // and then the combo inherits it and passes it onward. At that point the resolve mask
1712 // is very, very weak. This makes it stonger.
1713 font.setPointSizeF(QFontInfo(menuItem->font).pointSizeF());
1714
1715 if (menuitem->menuItemType == QStyleOptionMenuItem::DefaultItem)
1716 font.setBold(true);
1717
1718 p->setFont(font);
1719 const QString textToDraw = s.left(t).toString();
1720 if (dis && !act && proxy()->styleHint(SH_EtchDisabledText, option, widget)) {
1721 p->setPen(menuitem->palette.light().color());
1722 p->drawText(vTextRect.adjusted(1, 1, 1, 1), text_flags, textToDraw);
1723 p->setPen(discol);
1724 }
1725 p->drawText(vTextRect, text_flags, textToDraw);
1726 p->restore();
1727 }
1728
1729 // Arrow
1730 if (menuItem->menuItemType == QStyleOptionMenuItem::SubMenu) {// draw sub menu arrow
1731 int dim = (menuItem->rect.height() - 4) / 2;
1732 PrimitiveElement arrow;
1733 arrow = option->direction == Qt::RightToLeft ? PE_IndicatorArrowLeft : PE_IndicatorArrowRight;
1734 int xpos = menuItem->rect.left() + menuItem->rect.width() - 3 - dim;
1735 QRect vSubMenuRect = visualRect(option->direction, menuItem->rect,
1736 QRect(xpos, menuItem->rect.top() + menuItem->rect.height() / 2 - dim / 2, dim, dim));
1737 QStyleOptionMenuItem newMI = *menuItem;
1738 newMI.rect = vSubMenuRect;
1739 newMI.state = !enabled ? State_None : State_Enabled;
1740 if (selected)
1741 newMI.palette.setColor(QPalette::WindowText,
1742 newMI.palette.highlightedText().color());
1743 proxy()->drawPrimitive(arrow, &newMI, painter, widget);
1744 }
1745 }
1746 painter->restore();
1747 break;
1748 case CE_MenuHMargin:
1749 case CE_MenuVMargin:
1750 break;
1751 case CE_MenuEmptyArea:
1752 break;
1753 case CE_PushButton:
1754 if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) {
1755 proxy()->drawControl(CE_PushButtonBevel, btn, painter, widget);
1756 QStyleOptionButton subopt = *btn;
1757 subopt.rect = subElementRect(SE_PushButtonContents, btn, widget);
1758 proxy()->drawControl(CE_PushButtonLabel, &subopt, painter, widget);
1759 }
1760 break;
1761 case CE_PushButtonLabel:
1762 if (const QStyleOptionButton *button = qstyleoption_cast<const QStyleOptionButton *>(option)) {
1763 QRect ir = button->rect;
1764 uint tf = Qt::AlignVCenter;
1765 if (styleHint(SH_UnderlineShortcut, button, widget))
1766 tf |= Qt::TextShowMnemonic;
1767 else
1768 tf |= Qt::TextHideMnemonic;
1769
1770 if (!button->icon.isNull()) {
1771 //Center both icon and text
1772 QPoint point;
1773
1774 QIcon::Mode mode = button->state & State_Enabled ? QIcon::Normal
1775 : QIcon::Disabled;
1776 if (mode == QIcon::Normal && button->state & State_HasFocus)
1777 mode = QIcon::Active;
1778 QIcon::State state = QIcon::Off;
1779 if (button->state & State_On)
1780 state = QIcon::On;
1781
1782 QPixmap pixmap = button->icon.pixmap(button->iconSize, mode, state);
1783 int w = pixmap.width() / pixmap.devicePixelRatio();
1784 int h = pixmap.height() / pixmap.devicePixelRatio();
1785
1786 if (!button->text.isEmpty())
1787 w += button->fontMetrics.boundingRect(option->rect, tf, button->text).width() + 2;
1788
1789 point = QPoint(ir.x() + ir.width() / 2 - w / 2,
1790 ir.y() + ir.height() / 2 - h / 2);
1791
1792 w = pixmap.width() / pixmap.devicePixelRatio();
1793
1794 if (button->direction == Qt::RightToLeft)
1795 point.rx() += w;
1796
1797 painter->drawPixmap(visualPos(button->direction, button->rect, point), pixmap);
1798
1799 if (button->direction == Qt::RightToLeft)
1800 ir.translate(-point.x() - 2, 0);
1801 else
1802 ir.translate(point.x() + w, 0);
1803
1804 // left-align text if there is
1805 if (!button->text.isEmpty())
1806 tf |= Qt::AlignLeft;
1807
1808 } else {
1809 tf |= Qt::AlignHCenter;
1810 }
1811
1812 if (button->features & QStyleOptionButton::HasMenu)
1813 ir = ir.adjusted(0, 0, -proxy()->pixelMetric(PM_MenuButtonIndicator, button, widget), 0);
1814 proxy()->drawItemText(painter, ir, tf, button->palette, (button->state & State_Enabled),
1815 button->text, QPalette::ButtonText);
1816 }
1817 break;
1818 case CE_MenuBarEmptyArea:
1819 painter->save();
1820 {
1821 painter->fillRect(rect, option->palette.window());
1822 QColor shadow = mergedColors(option->palette.window().color().darker(120),
1823 outline.lighter(140), 60);
1824 painter->setPen(QPen(shadow));
1825 painter->drawLine(option->rect.bottomLeft(), option->rect.bottomRight());
1826 }
1827 painter->restore();
1828 break;
1829#if QT_CONFIG(tabbar)
1830 case CE_TabBarTabShape:
1831 painter->save();
1832 if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(option)) {
1833
1834 bool rtlHorTabs = (tab->direction == Qt::RightToLeft
1835 && (tab->shape == QTabBar::RoundedNorth
1836 || tab->shape == QTabBar::RoundedSouth));
1837 bool selected = tab->state & State_Selected;
1838 bool lastTab = ((!rtlHorTabs && tab->position == QStyleOptionTab::End)
1839 || (rtlHorTabs
1840 && tab->position == QStyleOptionTab::Beginning));
1841 bool onlyOne = tab->position == QStyleOptionTab::OnlyOneTab;
1842 int tabOverlap = pixelMetric(PM_TabBarTabOverlap, option, widget);
1843 rect = option->rect.adjusted(0, 0, (onlyOne || lastTab) ? 0 : tabOverlap, 0);
1844
1845 QRect r2(rect);
1846 int x1 = r2.left();
1847 int x2 = r2.right();
1848 int y1 = r2.top();
1849 int y2 = r2.bottom();
1850
1851 painter->setPen(d->innerContrastLine());
1852
1853 QTransform rotMatrix;
1854 bool flip = false;
1855 painter->setPen(shadow);
1856
1857 switch (tab->shape) {
1858 case QTabBar::RoundedNorth:
1859 break;
1860 case QTabBar::RoundedSouth:
1861 rotMatrix.rotate(180);
1862 rotMatrix.translate(0, -rect.height() + 1);
1863 rotMatrix.scale(-1, 1);
1864 painter->setTransform(rotMatrix, true);
1865 break;
1866 case QTabBar::RoundedWest:
1867 rotMatrix.rotate(180 + 90);
1868 rotMatrix.scale(-1, 1);
1869 flip = true;
1870 painter->setTransform(rotMatrix, true);
1871 break;
1872 case QTabBar::RoundedEast:
1873 rotMatrix.rotate(90);
1874 rotMatrix.translate(0, - rect.width() + 1);
1875 flip = true;
1876 painter->setTransform(rotMatrix, true);
1877 break;
1878 default:
1879 painter->restore();
1880 QCommonStyle::drawControl(element, tab, painter, widget);
1881 return;
1882 }
1883
1884 if (flip) {
1885 QRect tmp = rect;
1886 rect = QRect(tmp.y(), tmp.x(), tmp.height(), tmp.width());
1887 int temp = x1;
1888 x1 = y1;
1889 y1 = temp;
1890 temp = x2;
1891 x2 = y2;
1892 y2 = temp;
1893 }
1894
1895 painter->setRenderHint(QPainter::Antialiasing, true);
1896 painter->translate(0.5, 0.5);
1897
1898 QColor tabFrameColor = tab->features & QStyleOptionTab::HasFrame ?
1899 d->tabFrameColor(option->palette) :
1900 option->palette.window().color();
1901
1902 QLinearGradient fillGradient(rect.topLeft(), rect.bottomLeft());
1903 QLinearGradient