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 = qMax(pixelMetric(PM_ExclusiveIndicatorHeight), option->fontMetrics.height()) + groupBoxTopMargin;
473 QRect frame = option->rect.adjusted(0, topMargin, 0, 0);
474 qDrawBorderPixmap(painter, frame, QMargins(6, 6, 6, 6), pixmap);
475 break;
476 }
477 case PE_IndicatorBranch: {
478 if (!(option->state & State_Children))
479 break;
480 if (option->state & State_Open)
481 drawPrimitive(PE_IndicatorArrowDown, option, painter, widget);
482 else {
483 const bool reverse = (option->direction == Qt::RightToLeft);
484 drawPrimitive(reverse ? PE_IndicatorArrowLeft : PE_IndicatorArrowRight, option, painter, widget);
485 }
486 break;
487 }
488#if QT_CONFIG(tabbar)
489 case PE_FrameTabBarBase:
490 if (const QStyleOptionTabBarBase *tbb
491 = qstyleoption_cast<const QStyleOptionTabBarBase *>(option)) {
492 painter->save();
493 painter->setPen(QPen(outline.lighter(110)));
494 switch (tbb->shape) {
495 case QTabBar::RoundedNorth: {
496 QRegion region(tbb->rect);
497 region -= tbb->selectedTabRect;
498 painter->drawLine(tbb->rect.topLeft(), tbb->rect.topRight());
499 painter->setClipRegion(region);
500 painter->setPen(option->palette.light().color());
501 painter->drawLine(tbb->rect.topLeft() + QPoint(0, 1), tbb->rect.topRight() + QPoint(0, 1));
502 }
503 break;
504 case QTabBar::RoundedWest:
505 painter->drawLine(tbb->rect.left(), tbb->rect.top(), tbb->rect.left(), tbb->rect.bottom());
506 break;
507 case QTabBar::RoundedSouth:
508 painter->drawLine(tbb->rect.left(), tbb->rect.bottom(),
509 tbb->rect.right(), tbb->rect.bottom());
510 break;
511 case QTabBar::RoundedEast:
512 painter->drawLine(tbb->rect.topRight(), tbb->rect.bottomRight());
513 break;
514 case QTabBar::TriangularNorth:
515 case QTabBar::TriangularEast:
516 case QTabBar::TriangularWest:
517 case QTabBar::TriangularSouth:
518 painter->restore();
519 QCommonStyle::drawPrimitive(elem, option, painter, widget);
520 return;
521 }
522 painter->restore();
523 }
524 return;
525#endif // QT_CONFIG(tabbar)
526 case PE_PanelScrollAreaCorner: {
527 painter->save();
528 QColor alphaOutline = outline;
529 alphaOutline.setAlpha(180);
530 painter->setPen(alphaOutline);
531 painter->setBrush(option->palette.brush(QPalette::Window));
532 painter->drawRect(option->rect);
533 painter->restore();
534 } break;
535 case PE_IndicatorArrowUp:
536 case PE_IndicatorArrowDown:
537 case PE_IndicatorArrowRight:
538 case PE_IndicatorArrowLeft:
539 {
540 if (option->rect.width() <= 1 || option->rect.height() <= 1)
541 break;
542 QColor arrowColor = option->palette.windowText().color();
543 arrowColor.setAlpha(160);
544 Qt::ArrowType arrow = Qt::UpArrow;
545 switch (elem) {
546 case PE_IndicatorArrowDown:
547 arrow = Qt::DownArrow;
548 break;
549 case PE_IndicatorArrowRight:
550 arrow = Qt::RightArrow;
551 break;
552 case PE_IndicatorArrowLeft:
553 arrow = Qt::LeftArrow;
554 break;
555 default:
556 break;
557 }
558 qt_fusion_draw_arrow(arrow, painter, option, option->rect, arrowColor);
559 }
560 break;
561 case PE_IndicatorItemViewItemCheck:
562 {
563 QStyleOptionButton button;
564 button.QStyleOption::operator=(*option);
565 button.state &= ~State_MouseOver;
566 proxy()->drawPrimitive(PE_IndicatorCheckBox, &button, painter, widget);
567 }
568 return;
569 case PE_IndicatorHeaderArrow:
570 if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) {
571 QRect r = header->rect;
572 QColor arrowColor = header->palette.windowText().color();
573 arrowColor.setAlpha(180);
574 QPoint offset = QPoint(0, -2);
575
576#if defined(Q_OS_LINUX)
577 if (header->sortIndicator & QStyleOptionHeader::SortUp) {
578 qt_fusion_draw_arrow(Qt::UpArrow, painter, option, r.translated(offset), arrowColor);
579 } else if (header->sortIndicator & QStyleOptionHeader::SortDown) {
580 qt_fusion_draw_arrow(Qt::DownArrow, painter, option, r.translated(offset), arrowColor);
581 }
582#else
583 if (header->sortIndicator & QStyleOptionHeader::SortUp) {
584 qt_fusion_draw_arrow(Qt::DownArrow, painter, option, r.translated(offset), arrowColor);
585 } else if (header->sortIndicator & QStyleOptionHeader::SortDown) {
586 qt_fusion_draw_arrow(Qt::UpArrow, painter, option, r.translated(offset), arrowColor);
587 }
588#endif
589 }
590 break;
591 case PE_IndicatorButtonDropDown:
592 proxy()->drawPrimitive(PE_PanelButtonCommand, option, painter, widget);
593 break;
594
595 case PE_IndicatorToolBarSeparator:
596 {
597 QRect rect = option->rect;
598 const int margin = 6;
599 if (option->state & State_Horizontal) {
600 const int offset = rect.width()/2;
601 painter->setPen(QPen(option->palette.window().color().darker(110)));
602 painter->drawLine(rect.bottomLeft().x() + offset,
603 rect.bottomLeft().y() - margin,
604 rect.topLeft().x() + offset,
605 rect.topLeft().y() + margin);
606 painter->setPen(QPen(option->palette.window().color().lighter(110)));
607 painter->drawLine(rect.bottomLeft().x() + offset + 1,
608 rect.bottomLeft().y() - margin,
609 rect.topLeft().x() + offset + 1,
610 rect.topLeft().y() + margin);
611 } else { //Draw vertical separator
612 const int offset = rect.height()/2;
613 painter->setPen(QPen(option->palette.window().color().darker(110)));
614 painter->drawLine(rect.topLeft().x() + margin ,
615 rect.topLeft().y() + offset,
616 rect.topRight().x() - margin,
617 rect.topRight().y() + offset);
618 painter->setPen(QPen(option->palette.window().color().lighter(110)));
619 painter->drawLine(rect.topLeft().x() + margin ,
620 rect.topLeft().y() + offset + 1,
621 rect.topRight().x() - margin,
622 rect.topRight().y() + offset + 1);
623 }
624 }
625 break;
626 case PE_Frame: {
627 if (widget && widget->inherits("QComboBoxPrivateContainer")){
628 QStyleOption copy = *option;
629 copy.state |= State_Raised;
630 proxy()->drawPrimitive(PE_PanelMenu, &copy, painter, widget);
631 break;
632 }
633 painter->save();
634 QPen thePen(outline.lighter(108));
635 thePen.setCosmetic(false);
636 painter->setPen(thePen);
637 painter->drawRect(option->rect.adjusted(0, 0, -1, -1));
638 painter->restore(); }
639 break;
640 case PE_FrameMenu:
641 painter->save();
642 {
643 painter->setPen(QPen(outline));
644 painter->drawRect(option->rect.adjusted(0, 0, -1, -1));
645 QColor frameLight = option->palette.window().color().lighter(160);
646 QColor frameShadow = option->palette.window().color().darker(110);
647
648 //paint beveleffect
649 QRect frame = option->rect.adjusted(1, 1, -1, -1);
650 painter->setPen(frameLight);
651 painter->drawLine(frame.topLeft(), frame.bottomLeft());
652 painter->drawLine(frame.topLeft(), frame.topRight());
653
654 painter->setPen(frameShadow);
655 painter->drawLine(frame.topRight(), frame.bottomRight());
656 painter->drawLine(frame.bottomLeft(), frame.bottomRight());
657 }
658 painter->restore();
659 break;
660 case PE_FrameDockWidget:
661
662 painter->save();
663 {
664 QColor softshadow = option->palette.window().color().darker(120);
665
666 QRect rect= option->rect;
667 painter->setPen(softshadow);
668 painter->drawRect(option->rect.adjusted(0, 0, -1, -1));
669 painter->setPen(QPen(option->palette.light(), 1));
670 painter->drawLine(QPoint(rect.left() + 1, rect.top() + 1), QPoint(rect.left() + 1, rect.bottom() - 1));
671 painter->setPen(QPen(option->palette.window().color().darker(120)));
672 painter->drawLine(QPoint(rect.left() + 1, rect.bottom() - 1), QPoint(rect.right() - 2, rect.bottom() - 1));
673 painter->drawLine(QPoint(rect.right() - 1, rect.top() + 1), QPoint(rect.right() - 1, rect.bottom() - 1));
674
675 }
676 painter->restore();
677 break;
678 case PE_PanelButtonTool:
679 painter->save();
680 if ((option->state & State_Enabled || option->state & State_On) || !(option->state & State_AutoRaise)) {
681 if (widget && widget->inherits("QDockWidgetTitleButton")) {
682 if (option->state & State_MouseOver)
683 proxy()->drawPrimitive(PE_PanelButtonCommand, option, painter, widget);
684 } else {
685 proxy()->drawPrimitive(PE_PanelButtonCommand, option, painter, widget);
686 }
687 }
688 painter->restore();
689 break;
690 case PE_IndicatorDockWidgetResizeHandle:
691 {
692 QStyleOption dockWidgetHandle = *option;
693 bool horizontal = option->state & State_Horizontal;
694 dockWidgetHandle.state.setFlag(State_Horizontal, !horizontal);
695 proxy()->drawControl(CE_Splitter, &dockWidgetHandle, painter, widget);
696 }
697 break;
698 case PE_FrameWindow:
699 painter->save();
700 {
701 QRect rect= option->rect;
702 painter->setPen(QPen(outline.darker(150)));
703 painter->drawRect(option->rect.adjusted(0, 0, -1, -1));
704 painter->setPen(QPen(option->palette.light(), 1));
705 painter->drawLine(QPoint(rect.left() + 1, rect.top() + 1),
706 QPoint(rect.left() + 1, rect.bottom() - 1));
707 painter->setPen(QPen(option->palette.window().color().darker(120)));
708 painter->drawLine(QPoint(rect.left() + 1, rect.bottom() - 1),
709 QPoint(rect.right() - 2, rect.bottom() - 1));
710 painter->drawLine(QPoint(rect.right() - 1, rect.top() + 1),
711 QPoint(rect.right() - 1, rect.bottom() - 1));
712 }
713 painter->restore();
714 break;
715 case PE_FrameLineEdit:
716 {
717 QRect r = rect;
718 bool hasFocus = option->state & State_HasFocus;
719
720 painter->save();
721
722 painter->setRenderHint(QPainter::Antialiasing, true);
723 // ### highdpi painter bug.
724 painter->translate(0.5, 0.5);
725
726 // Draw Outline
727 painter->setPen( QPen(hasFocus ? highlightedOutline : outline));
728 painter->drawRoundedRect(r.adjusted(0, 0, -1, -1), 2, 2);
729
730 if (hasFocus) {
731 QColor softHighlight = highlightedOutline;
732 softHighlight.setAlpha(40);
733 painter->setPen(softHighlight);
734 painter->drawRoundedRect(r.adjusted(1, 1, -2, -2), 1.7, 1.7);
735 }
736 // Draw inner shadow
737 painter->setPen(d->topShadow());
738 painter->drawLine(QPoint(r.left() + 2, r.top() + 1), QPoint(r.right() - 2, r.top() + 1));
739
740 painter->restore();
741
742 }
743 break;
744 case PE_IndicatorCheckBox:
745 painter->save();
746 if (const QStyleOptionButton *checkbox = qstyleoption_cast<const QStyleOptionButton*>(option)) {
747 painter->setRenderHint(QPainter::Antialiasing, true);
748 painter->translate(0.5, 0.5);
749 rect = rect.adjusted(0, 0, -1, -1);
750
751 QColor pressedColor = mergedColors(option->palette.base().color(), option->palette.windowText().color(), 85);
752 painter->setBrush(Qt::NoBrush);
753
754 // Gradient fill
755 QLinearGradient gradient(rect.topLeft(), rect.bottomLeft());
756 gradient.setColorAt(0, (state & State_Sunken) ? pressedColor : option->palette.base().color().darker(115));
757 gradient.setColorAt(0.15, (state & State_Sunken) ? pressedColor : option->palette.base().color());
758 gradient.setColorAt(1, (state & State_Sunken) ? pressedColor : option->palette.base().color());
759
760 painter->setBrush((state & State_Sunken) ? QBrush(pressedColor) : gradient);
761 painter->setPen(QPen(outline.lighter(110)));
762
763 if (option->state & State_HasFocus && option->state & State_KeyboardFocusChange)
764 painter->setPen(QPen(highlightedOutline));
765 painter->drawRect(rect);
766
767 QColor checkMarkColor = option->palette.text().color().darker(120);
768 const qreal checkMarkPadding = 1 + rect.width() * 0.13; // at least one pixel padding
769
770 if (checkbox->state & State_NoChange) {
771 gradient = QLinearGradient(rect.topLeft(), rect.bottomLeft());
772 checkMarkColor.setAlpha(80);
773 gradient.setColorAt(0, checkMarkColor);
774 checkMarkColor.setAlpha(140);
775 gradient.setColorAt(1, checkMarkColor);
776 checkMarkColor.setAlpha(180);
777 painter->setPen(QPen(checkMarkColor, 1));
778 painter->setBrush(gradient);
779 painter->drawRect(rect.adjusted(checkMarkPadding, checkMarkPadding, -checkMarkPadding, -checkMarkPadding));
780
781 } else if (checkbox->state & State_On) {
782 qreal penWidth = QStyleHelper::dpiScaled(1.5);
783 penWidth = qMax<qreal>(penWidth, 0.13 * rect.height());
784 penWidth = qMin<qreal>(penWidth, 0.20 * rect.height());
785 QPen checkPen = QPen(checkMarkColor, penWidth);
786 checkMarkColor.setAlpha(210);
787 painter->translate(dpiScaled(-0.8), dpiScaled(0.5));
788 painter->setPen(checkPen);
789 painter->setBrush(Qt::NoBrush);
790
791 // Draw checkmark
792 QPainterPath path;
793 const qreal rectHeight = rect.height(); // assuming height equals width
794 path.moveTo(checkMarkPadding + rectHeight * 0.11, rectHeight * 0.47);
795 path.lineTo(rectHeight * 0.5, rectHeight - checkMarkPadding);
796 path.lineTo(rectHeight - checkMarkPadding, checkMarkPadding);
797 painter->drawPath(path.translated(rect.topLeft()));
798 }
799 }
800 painter->restore();
801 break;
802 case PE_IndicatorRadioButton:
803 painter->save();
804 {
805 QColor pressedColor = mergedColors(option->palette.base().color(), option->palette.windowText().color(), 85);
806 painter->setBrush((state & State_Sunken) ? pressedColor : option->palette.base().color());
807 painter->setRenderHint(QPainter::Antialiasing, true);
808 QPainterPath circle;
809 const QPointF circleCenter = rect.center() + QPoint(1, 1);
810 const qreal outlineRadius = (rect.width() + (rect.width() + 1) % 2) / 2.0 - 1;
811 circle.addEllipse(circleCenter, outlineRadius, outlineRadius);
812 painter->setPen(QPen(option->palette.window().color().darker(150)));
813 if (option->state & State_HasFocus && option->state & State_KeyboardFocusChange)
814 painter->setPen(QPen(highlightedOutline));
815 painter->drawPath(circle);
816
817 if (state & (State_On )) {
818 circle = QPainterPath();
819 const qreal checkmarkRadius = outlineRadius / 2.32;
820 circle.addEllipse(circleCenter, checkmarkRadius, checkmarkRadius);
821 QColor checkMarkColor = option->palette.text().color().darker(120);
822 checkMarkColor.setAlpha(200);
823 painter->setPen(checkMarkColor);
824 checkMarkColor.setAlpha(180);
825 painter->setBrush(checkMarkColor);
826 painter->drawPath(circle);
827 }
828 }
829 painter->restore();
830 break;
831 case PE_IndicatorToolBarHandle:
832 {
833 //draw grips
834 if (option->state & State_Horizontal) {
835 for (int i = -3 ; i < 2 ; i += 3) {
836 for (int j = -8 ; j < 10 ; j += 3) {
837 painter->fillRect(rect.center().x() + i, rect.center().y() + j, 2, 2, d->lightShade());
838 painter->fillRect(rect.center().x() + i, rect.center().y() + j, 1, 1, d->darkShade());
839 }
840 }
841 } else { //vertical toolbar
842 for (int i = -6 ; i < 12 ; i += 3) {
843 for (int j = -3 ; j < 2 ; 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 }
849 break;
850 }
851 case PE_FrameDefaultButton:
852 break;
853 case PE_FrameFocusRect:
854 if (const QStyleOptionFocusRect *fropt = qstyleoption_cast<const QStyleOptionFocusRect *>(option)) {
855 //### check for d->alt_down
856 if (!(fropt->state & State_KeyboardFocusChange))
857 return;
858 QRect rect = option->rect;
859
860 painter->save();
861 painter->setRenderHint(QPainter::Antialiasing, true);
862 painter->translate(0.5, 0.5);
863 QColor fillcolor = highlightedOutline;
864 fillcolor.setAlpha(80);
865 painter->setPen(fillcolor.darker(120));
866 fillcolor.setAlpha(30);
867 QLinearGradient gradient(rect.topLeft(), rect.bottomLeft());
868 gradient.setColorAt(0, fillcolor.lighter(160));
869 gradient.setColorAt(1, fillcolor);
870 painter->setBrush(gradient);
871 painter->drawRoundedRect(option->rect.adjusted(0, 0, -1, -1), 1, 1);
872 painter->restore();
873 }
874 break;
875 case PE_PanelButtonCommand:
876 {
877 bool isDefault = false;
878 bool isFlat = false;
879 bool isDown = (option->state & State_Sunken) || (option->state & State_On);
880 QRect r;
881
882 if (const QStyleOptionButton *button = qstyleoption_cast<const QStyleOptionButton*>(option)) {
883 isDefault = (button->features & QStyleOptionButton::DefaultButton) && (button->state & State_Enabled);
884 isFlat = (button->features & QStyleOptionButton::Flat);
885 }
886
887 if (isFlat && !isDown) {
888 if (isDefault) {
889 r = option->rect.adjusted(0, 1, 0, -1);
890 painter->setPen(QPen(Qt::black));
891 const QLine lines[4] = {
892 QLine(QPoint(r.left() + 2, r.top()),
893 QPoint(r.right() - 2, r.top())),
894 QLine(QPoint(r.left(), r.top() + 2),
895 QPoint(r.left(), r.bottom() - 2)),
896 QLine(QPoint(r.right(), r.top() + 2),
897 QPoint(r.right(), r.bottom() - 2)),
898 QLine(QPoint(r.left() + 2, r.bottom()),
899 QPoint(r.right() - 2, r.bottom()))
900 };
901 painter->drawLines(lines, 4);
902 const QPoint points[4] = {
903 QPoint(r.right() - 1, r.bottom() - 1),
904 QPoint(r.right() - 1, r.top() + 1),
905 QPoint(r.left() + 1, r.bottom() - 1),
906 QPoint(r.left() + 1, r.top() + 1)
907 };
908 painter->drawPoints(points, 4);
909 }
910 return;
911 }
912
913
914 bool isEnabled = option->state & State_Enabled;
915 bool hasFocus = (option->state & State_HasFocus && option->state & State_KeyboardFocusChange);
916 QColor buttonColor = d->buttonColor(option->palette);
917
918 QColor darkOutline = outline;
919 if (hasFocus | isDefault) {
920 darkOutline = highlightedOutline;
921 }
922
923 if (isDefault)
924 buttonColor = mergedColors(buttonColor, highlightedOutline.lighter(130), 90);
925
926 BEGIN_STYLE_PIXMAPCACHE(QStringLiteral("pushbutton-") + buttonColor.name(QColor::HexArgb))
927 r = rect.adjusted(0, 1, -1, 0);
928
929 p->setRenderHint(QPainter::Antialiasing, true);
930 p->translate(0.5, -0.5);
931
932 QLinearGradient gradient = qt_fusion_gradient(rect, (isEnabled && option->state & State_MouseOver ) ? buttonColor : buttonColor.darker(104));
933 p->setPen(Qt::transparent);
934 p->setBrush(isDown ? QBrush(buttonColor.darker(110)) : gradient);
935 p->drawRoundedRect(r, 2.0, 2.0);
936 p->setBrush(Qt::NoBrush);
937
938 // Outline
939 p->setPen(!isEnabled ? QPen(darkOutline.lighter(115)) : QPen(darkOutline));
940 p->drawRoundedRect(r, 2.0, 2.0);
941
942 p->setPen(d->innerContrastLine());
943 p->drawRoundedRect(r.adjusted(1, 1, -1, -1), 2.0, 2.0);
944
945 END_STYLE_PIXMAPCACHE
946 }
947 break;
948 case PE_FrameTabWidget:
949 painter->save();
950 painter->fillRect(option->rect.adjusted(0, 0, -1, -1), tabFrameColor);
951#if QT_CONFIG(tabwidget)
952 if (const QStyleOptionTabWidgetFrame *twf = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(option)) {
953 QColor borderColor = outline.lighter(110);
954 QRect rect = option->rect.adjusted(0, 0, -1, -1);
955
956 // Shadow outline
957 if (twf->shape != QTabBar::RoundedSouth) {
958 rect.adjust(0, 0, 0, -1);
959 QColor alphaShadow(Qt::black);
960 alphaShadow.setAlpha(15);
961 painter->setPen(alphaShadow);
962 painter->drawLine(option->rect.bottomLeft(), option->rect.bottomRight()); painter->setPen(borderColor);
963 }
964
965 // outline
966 painter->setPen(outline);
967 painter->drawRect(rect);
968
969 // Inner frame highlight
970 painter->setPen(d->innerContrastLine());
971 painter->drawRect(rect.adjusted(1, 1, -1, -1));
972
973 }
974#endif // QT_CONFIG(tabwidget)
975 painter->restore();
976 break ;
977
978 case PE_FrameStatusBarItem:
979 break;
980 case PE_IndicatorTabClose:
981 {
982 Q_D(const QFusionStyle);
983 if (d->tabBarcloseButtonIcon.isNull())
984 d->tabBarcloseButtonIcon = proxy()->standardIcon(SP_DialogCloseButton, option, widget);
985 if ((option->state & State_Enabled) && (option->state & State_MouseOver))
986 proxy()->drawPrimitive(PE_PanelButtonCommand, option, painter, widget);
987 QPixmap pixmap = d->tabBarcloseButtonIcon.pixmap(QSize(16, 16), QIcon::Normal, QIcon::On);
988 proxy()->drawItemPixmap(painter, option->rect, Qt::AlignCenter, pixmap);
989 }
990 break;
991 case PE_PanelMenu: {
992 painter->save();
993 const QBrush menuBackground = option->palette.base().color().lighter(108);
994 QColor borderColor = option->palette.window().color().darker(160);
995 qDrawPlainRect(painter, option->rect, borderColor, 1, &menuBackground);
996 painter->restore();
997 }
998 break;
999
1000 default:
1001 QCommonStyle::drawPrimitive(elem, option, painter, widget);
1002 break;
1003 }
1004}
1005
1006/*!
1007 \reimp
1008*/
1009void QFusionStyle::drawControl(ControlElement element, const QStyleOption *option, QPainter *painter,
1010 const QWidget *widget) const
1011{
1012 Q_D (const QFusionStyle);
1013 QRect rect = option->rect;
1014 QColor outline = d->outline(option->palette);
1015 QColor highlightedOutline = d->highlightedOutline(option->palette);
1016 QColor shadow = d->darkShade();
1017
1018 switch (element) {
1019 case CE_ComboBoxLabel:
1020 if (const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
1021 QRect editRect = proxy()->subControlRect(CC_ComboBox, cb, SC_ComboBoxEditField, widget);
1022 painter->save();
1023 painter->setClipRect(editRect);
1024 if (!cb->currentIcon.isNull()) {
1025 QIcon::Mode mode = cb->state & State_Enabled ? QIcon::Normal
1026 : QIcon::Disabled;
1027 QPixmap pixmap = cb->currentIcon.pixmap(cb->iconSize, mode);
1028 QRect iconRect(editRect);
1029 iconRect.setWidth(cb->iconSize.width() + 4);
1030 iconRect = alignedRect(cb->direction,
1031 Qt::AlignLeft | Qt::AlignVCenter,
1032 iconRect.size(), editRect);
1033 if (cb->editable)
1034 painter->fillRect(iconRect, cb->palette.brush(QPalette::Base));
1035 proxy()->drawItemPixmap(painter, iconRect, Qt::AlignCenter, pixmap);
1036
1037 if (cb->direction == Qt::RightToLeft)
1038 editRect.translate(-4 - cb->iconSize.width(), 0);
1039 else
1040 editRect.translate(cb->iconSize.width() + 4, 0);
1041 }
1042 if (!cb->currentText.isEmpty() && !cb->editable) {
1043 proxy()->drawItemText(painter, editRect.adjusted(1, 0, -1, 0),
1044 visualAlignment(cb->direction, Qt::AlignLeft | Qt::AlignVCenter),
1045 cb->palette, cb->state & State_Enabled, cb->currentText,
1046 cb->editable ? QPalette::Text : QPalette::ButtonText);
1047 }
1048 painter->restore();
1049 }
1050 break;
1051 case CE_Splitter:
1052 {
1053 // Don't draw handle for single pixel splitters
1054 if (option->rect.width() > 1 && option->rect.height() > 1) {
1055 //draw grips
1056 if (option->state & State_Horizontal) {
1057 for (int j = -6 ; j< 12 ; j += 3) {
1058 painter->fillRect(rect.center().x() + 1, rect.center().y() + j, 2, 2, d->lightShade());
1059 painter->fillRect(rect.center().x() + 1, rect.center().y() + j, 1, 1, d->darkShade());
1060 }
1061 } else {
1062 for (int i = -6; i< 12 ; i += 3) {
1063 painter->fillRect(rect.center().x() + i, rect.center().y(), 2, 2, d->lightShade());
1064 painter->fillRect(rect.center().x() + i, rect.center().y(), 1, 1, d->darkShade());
1065 }
1066 }
1067 }
1068 break;
1069 }
1070#if QT_CONFIG(rubberband)
1071 case CE_RubberBand:
1072 if (qstyleoption_cast<const QStyleOptionRubberBand *>(option)) {
1073 QColor highlight = option->palette.color(QPalette::Active, QPalette::Highlight);
1074 painter->save();
1075 QColor penColor = highlight.darker(120);
1076 penColor.setAlpha(180);
1077 painter->setPen(penColor);
1078 QColor dimHighlight(qMin(highlight.red()/2 + 110, 255),
1079 qMin(highlight.green()/2 + 110, 255),
1080 qMin(highlight.blue()/2 + 110, 255));
1081 dimHighlight.setAlpha(widget && widget->isTopLevel() ? 255 : 80);
1082 QLinearGradient gradient(rect.topLeft(), QPoint(rect.bottomLeft().x(), rect.bottomLeft().y()));
1083 gradient.setColorAt(0, dimHighlight.lighter(120));
1084 gradient.setColorAt(1, dimHighlight);
1085 painter->setRenderHint(QPainter::Antialiasing, true);
1086 painter->translate(0.5, 0.5);
1087 painter->setBrush(dimHighlight);
1088 painter->drawRoundedRect(option->rect.adjusted(0, 0, -1, -1), 1, 1);
1089 QColor innerLine = Qt::white;
1090 innerLine.setAlpha(40);
1091 painter->setPen(innerLine);
1092 painter->drawRoundedRect(option->rect.adjusted(1, 1, -2, -2), 1, 1);
1093 painter->restore();
1094 }
1095 break;
1096#endif //QT_CONFIG(rubberband)
1097 case CE_SizeGrip:
1098 painter->save();
1099 {
1100 //draw grips
1101 for (int i = -6; i< 12 ; i += 3) {
1102 for (int j = -6 ; j< 12 ; j += 3) {
1103 if ((option->direction == Qt::LeftToRight && i > -j) || (option->direction == Qt::RightToLeft && j > i) ) {
1104 painter->fillRect(rect.center().x() + i, rect.center().y() + j, 2, 2, d->lightShade());
1105 painter->fillRect(rect.center().x() + i, rect.center().y() + j, 1, 1, d->darkShade());
1106 }
1107 }
1108 }
1109 }
1110 painter->restore();
1111 break;
1112#if QT_CONFIG(toolbar)
1113 case CE_ToolBar:
1114 if (const QStyleOptionToolBar *toolBar = qstyleoption_cast<const QStyleOptionToolBar *>(option)) {
1115 // Reserve the beveled appearance only for mainwindow toolbars
1116 if (widget && !(qobject_cast<const QMainWindow*> (widget->parentWidget())))
1117 break;
1118
1119 // Draws the light line above and the dark line below menu bars and
1120 // tool bars.
1121 QLinearGradient gradient(option->rect.topLeft(), option->rect.bottomLeft());
1122 if (!(option->state & State_Horizontal))
1123 gradient = QLinearGradient(rect.left(), rect.center().y(),
1124 rect.right(), rect.center().y());
1125 gradient.setColorAt(0, option->palette.window().color().lighter(104));
1126 gradient.setColorAt(1, option->palette.window().color());
1127 painter->fillRect(option->rect, gradient);
1128
1129 QColor light = d->lightShade();
1130 QColor shadow = d->darkShade();
1131
1132 QPen oldPen = painter->pen();
1133 if (toolBar->toolBarArea == Qt::TopToolBarArea) {
1134 if (toolBar->positionOfLine == QStyleOptionToolBar::End
1135 || toolBar->positionOfLine == QStyleOptionToolBar::OnlyOne) {
1136 // The end and onlyone top toolbar lines draw a double
1137 // line at the bottom to blend with the central
1138 // widget.
1139 painter->setPen(light);
1140 painter->drawLine(option->rect.bottomLeft(), option->rect.bottomRight());
1141 painter->setPen(shadow);
1142 painter->drawLine(option->rect.left(), option->rect.bottom() - 1,
1143 option->rect.right(), option->rect.bottom() - 1);
1144 } else {
1145 // All others draw a single dark line at the bottom.
1146 painter->setPen(shadow);
1147 painter->drawLine(option->rect.bottomLeft(), option->rect.bottomRight());
1148 }
1149 // All top toolbar lines draw a light line at the top.
1150 painter->setPen(light);
1151 painter->drawLine(option->rect.topLeft(), option->rect.topRight());
1152 } else if (toolBar->toolBarArea == Qt::BottomToolBarArea) {
1153 if (toolBar->positionOfLine == QStyleOptionToolBar::End
1154 || toolBar->positionOfLine == QStyleOptionToolBar::Middle) {
1155 // The end and middle bottom tool bar lines draw a dark
1156 // line at the bottom.
1157 painter->setPen(shadow);
1158 painter->drawLine(option->rect.bottomLeft(), option->rect.bottomRight());
1159 }
1160 if (toolBar->positionOfLine == QStyleOptionToolBar::Beginning
1161 || toolBar->positionOfLine == QStyleOptionToolBar::OnlyOne) {
1162 // The beginning and only one tool bar lines draw a
1163 // double line at the bottom to blend with the
1164 // status bar.
1165 // ### The styleoption could contain whether the
1166 // main window has a menu bar and a status bar, and
1167 // possibly dock widgets.
1168 painter->setPen(shadow);
1169 painter->drawLine(option->rect.left(), option->rect.bottom() - 1,
1170 option->rect.right(), option->rect.bottom() - 1);
1171 painter->setPen(light);
1172 painter->drawLine(option->rect.bottomLeft(), option->rect.bottomRight());
1173 }
1174 if (toolBar->positionOfLine == QStyleOptionToolBar::End) {
1175 painter->setPen(shadow);
1176 painter->drawLine(option->rect.topLeft(), option->rect.topRight());
1177 painter->setPen(light);
1178 painter->drawLine(option->rect.left(), option->rect.top() + 1,
1179 option->rect.right(), option->rect.top() + 1);
1180
1181 } else {
1182 // All other bottom toolbars draw a light line at the top.
1183 painter->setPen(light);
1184 painter->drawLine(option->rect.topLeft(), option->rect.topRight());
1185 }
1186 }
1187 if (toolBar->toolBarArea == Qt::LeftToolBarArea) {
1188 if (toolBar->positionOfLine == QStyleOptionToolBar::Middle
1189 || toolBar->positionOfLine == QStyleOptionToolBar::End) {
1190 // The middle and left end toolbar lines draw a light
1191 // line to the left.
1192 painter->setPen(light);
1193 painter->drawLine(option->rect.topLeft(), option->rect.bottomLeft());
1194 }
1195 if (toolBar->positionOfLine == QStyleOptionToolBar::End) {
1196 // All other left toolbar lines draw a dark line to the right
1197 painter->setPen(shadow);
1198 painter->drawLine(option->rect.right() - 1, option->rect.top(),
1199 option->rect.right() - 1, option->rect.bottom());
1200 painter->setPen(light);
1201 painter->drawLine(option->rect.topRight(), option->rect.bottomRight());
1202 } else {
1203 // All other left toolbar lines draw a dark line to the right
1204 painter->setPen(shadow);
1205 painter->drawLine(option->rect.topRight(), option->rect.bottomRight());
1206 }
1207 } else if (toolBar->toolBarArea == Qt::RightToolBarArea) {
1208 if (toolBar->positionOfLine == QStyleOptionToolBar::Middle
1209 || toolBar->positionOfLine == QStyleOptionToolBar::End) {
1210 // Right middle and end toolbar lines draw the dark right line
1211 painter->setPen(shadow);
1212 painter->drawLine(option->rect.topRight(), option->rect.bottomRight());
1213 }
1214 if (toolBar->positionOfLine == QStyleOptionToolBar::End
1215 || toolBar->positionOfLine == QStyleOptionToolBar::OnlyOne) {
1216 // The right end and single toolbar draws the dark
1217 // line on its left edge
1218 painter->setPen(shadow);
1219 painter->drawLine(option->rect.topLeft(), option->rect.bottomLeft());
1220 // And a light line next to it
1221 painter->setPen(light);
1222 painter->drawLine(option->rect.left() + 1, option->rect.top(),
1223 option->rect.left() + 1, option->rect.bottom());
1224 } else {
1225 // Other right toolbars draw a light line on its left edge
1226 painter->setPen(light);
1227 painter->drawLine(option->rect.topLeft(), option->rect.bottomLeft());
1228 }
1229 }
1230 painter->setPen(oldPen);
1231 }
1232 break;
1233#endif // QT_CONFIG(toolbar)
1234 case CE_DockWidgetTitle:
1235 painter->save();
1236 if (const QStyleOptionDockWidget *dwOpt = qstyleoption_cast<const QStyleOptionDockWidget *>(option)) {
1237 bool verticalTitleBar = dwOpt->verticalTitleBar;
1238
1239 QRect titleRect = subElementRect(SE_DockWidgetTitleBarText, option, widget);
1240 if (verticalTitleBar) {
1241 QRect rect = dwOpt->rect;
1242 QRect r = rect.transposed();
1243 titleRect = QRect(r.left() + rect.bottom()
1244 - titleRect.bottom(),
1245 r.top() + titleRect.left() - rect.left(),
1246 titleRect.height(), titleRect.width());
1247
1248 painter->translate(r.left(), r.top() + r.width());
1249 painter->rotate(-90);
1250 painter->translate(-r.left(), -r.top());
1251 }
1252
1253 if (!dwOpt->title.isEmpty()) {
1254 QString titleText
1255 = painter->fontMetrics().elidedText(dwOpt->title,
1256 Qt::ElideRight, titleRect.width());
1257 proxy()->drawItemText(painter,
1258 titleRect,
1259 Qt::AlignLeft | Qt::AlignVCenter, dwOpt->palette,
1260 dwOpt->state & State_Enabled, titleText,
1261 QPalette::WindowText);
1262 }
1263 }
1264 painter->restore();
1265 break;
1266 case CE_HeaderSection:
1267 painter->save();
1268 // Draws the header in tables.
1269 if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) {
1270 QString pixmapName = QStyleHelper::uniqueName(QLatin1String("headersection"), option, option->rect.size());
1271 pixmapName += QString::number(- int(header->position));
1272 pixmapName += QString::number(- int(header->orientation));
1273
1274 QPixmap cache;
1275 if (!QPixmapCache::find(pixmapName, &cache)) {
1276 cache = styleCachePixmap(rect.size());
1277 cache.fill(Qt::transparent);
1278 QRect pixmapRect(0, 0, rect.width(), rect.height());
1279 QPainter cachePainter(&cache);
1280 QColor buttonColor = d->buttonColor(option->palette);
1281 QColor gradientStopColor;
1282 QColor gradientStartColor = buttonColor.lighter(104);
1283 gradientStopColor = buttonColor.darker(102);
1284 QLinearGradient gradient(pixmapRect.topLeft(), pixmapRect.bottomLeft());
1285
1286 if (option->palette.window().gradient()) {
1287 gradient.setStops(option->palette.window().gradient()->stops());
1288 } else {
1289 QColor midColor1 = mergedColors(gradientStartColor, gradientStopColor, 60);
1290 QColor midColor2 = mergedColors(gradientStartColor, gradientStopColor, 40);
1291 gradient.setColorAt(0, gradientStartColor);
1292 gradient.setColorAt(0.5, midColor1);
1293 gradient.setColorAt(0.501, midColor2);
1294 gradient.setColorAt(0.92, gradientStopColor);
1295 gradient.setColorAt(1, gradientStopColor.darker(104));
1296 }
1297 cachePainter.fillRect(pixmapRect, gradient);
1298 cachePainter.setPen(d->innerContrastLine());
1299 cachePainter.setBrush(Qt::NoBrush);
1300 cachePainter.drawLine(pixmapRect.topLeft(), pixmapRect.topRight());
1301 cachePainter.setPen(d->outline(option->palette));
1302 cachePainter.drawLine(pixmapRect.bottomLeft(), pixmapRect.bottomRight());
1303
1304 if (header->orientation == Qt::Horizontal &&
1305 header->position != QStyleOptionHeader::End &&
1306 header->position != QStyleOptionHeader::OnlyOneSection) {
1307 cachePainter.setPen(QColor(0, 0, 0, 40));
1308 cachePainter.drawLine(pixmapRect.topRight(), pixmapRect.bottomRight() + QPoint(0, -1));
1309 cachePainter.setPen(d->innerContrastLine());
1310 cachePainter.drawLine(pixmapRect.topRight() + QPoint(-1, 0), pixmapRect.bottomRight() + QPoint(-1, -1));
1311 } else if (header->orientation == Qt::Vertical) {
1312 cachePainter.setPen(d->outline(option->palette));
1313 cachePainter.drawLine(pixmapRect.topRight(), pixmapRect.bottomRight());
1314 }
1315 cachePainter.end();
1316 QPixmapCache::insert(pixmapName, cache);
1317 }
1318 painter->drawPixmap(rect.topLeft(), cache);
1319 }
1320 painter->restore();
1321 break;
1322 case CE_ProgressBarGroove:
1323 painter->save();
1324 {
1325 painter->setRenderHint(QPainter::Antialiasing, true);
1326 painter->translate(0.5, 0.5);
1327
1328 QColor shadowAlpha = Qt::black;
1329 shadowAlpha.setAlpha(16);
1330 painter->setPen(shadowAlpha);
1331 painter->drawLine(rect.topLeft() - QPoint(0, 1), rect.topRight() - QPoint(0, 1));
1332
1333 painter->setBrush(option->palette.base());
1334 painter->setPen(QPen(outline));
1335 painter->drawRoundedRect(rect.adjusted(0, 0, -1, -1), 2, 2);
1336
1337 // Inner shadow
1338 painter->setPen(d->topShadow());
1339 painter->drawLine(QPoint(rect.left() + 1, rect.top() + 1),
1340 QPoint(rect.right() - 1, rect.top() + 1));
1341 }
1342 painter->restore();
1343 break;
1344 case CE_ProgressBarContents:
1345 painter->save();
1346 painter->setRenderHint(QPainter::Antialiasing, true);
1347 painter->translate(0.5, 0.5);
1348 if (const QStyleOptionProgressBar *bar = qstyleoption_cast<const QStyleOptionProgressBar *>(option)) {
1349 bool vertical = false;
1350 bool inverted = false;
1351 bool indeterminate = (bar->minimum == 0 && bar->maximum == 0);
1352 bool complete = bar->progress == bar->maximum;
1353
1354 // Get extra style options if version 2
1355 vertical = (bar->orientation == Qt::Vertical);
1356 inverted = bar->invertedAppearance;
1357
1358 // If the orientation is vertical, we use a transform to rotate
1359 // the progress bar 90 degrees clockwise. This way we can use the
1360 // same rendering code for both orientations.
1361 if (vertical) {
1362 rect = QRect(rect.left(), rect.top(), rect.height(), rect.width()); // flip width and height
1363 QTransform m = QTransform::fromTranslate(rect.height()-1, -1.0);
1364 m.rotate(90.0);
1365 painter->setTransform(m, true);
1366 }
1367
1368 int maxWidth = rect.width();
1369 const auto progress = qMax(bar->progress, bar->minimum); // workaround for bug in QProgressBar
1370 const auto totalSteps = qMax(Q_INT64_C(1), qint64(bar->maximum) - bar->minimum);
1371 const auto progressSteps = qint64(progress) - bar->minimum;
1372 const auto progressBarWidth = progressSteps * maxWidth / totalSteps;
1373 int width = indeterminate ? maxWidth : progressBarWidth;
1374
1375 bool reverse = (!vertical && (bar->direction == Qt::RightToLeft)) || vertical;
1376 if (inverted)
1377 reverse = !reverse;
1378
1379 int step = 0;
1380 QRect progressBar;
1381 QColor highlight = d->highlight(option->palette);
1382 QColor highlightedoutline = highlight.darker(140);
1383 if (qGray(outline.rgb()) > qGray(highlightedoutline.rgb()))
1384 outline = highlightedoutline;
1385
1386 if (!indeterminate) {
1387 QColor innerShadow(Qt::black);
1388 innerShadow.setAlpha(35);
1389 painter->setPen(innerShadow);
1390 if (!reverse) {
1391 progressBar.setRect(rect.left(), rect.top(), width - 1, rect.height() - 1);
1392 if (!complete) {
1393 painter->drawLine(progressBar.topRight() + QPoint(2, 1), progressBar.bottomRight() + QPoint(2, 0));
1394 painter->setPen(QPen(highlight.darker(140)));
1395 painter->drawLine(progressBar.topRight() + QPoint(1, 1), progressBar.bottomRight() + QPoint(1, 0));
1396 }
1397 } else {
1398 progressBar.setRect(rect.right() - width - 1, rect.top(), width + 2, rect.height() - 1);
1399 if (!complete) {
1400 painter->drawLine(progressBar.topLeft() + QPoint(-2, 1), progressBar.bottomLeft() + QPoint(-2, 0));
1401 painter->setPen(QPen(highlight.darker(140)));
1402 painter->drawLine(progressBar.topLeft() + QPoint(-1, 1), progressBar.bottomLeft() + QPoint(-1, 0));
1403 }
1404 }
1405 } else {
1406 progressBar.setRect(rect.left(), rect.top(), rect.width() - 1, rect.height() - 1);
1407 }
1408
1409 if (indeterminate || bar->progress > bar->minimum) {
1410
1411 painter->setPen(QPen(outline));
1412
1413 QColor highlightedGradientStartColor = highlight.lighter(120);
1414 QColor highlightedGradientStopColor = highlight;
1415 QLinearGradient gradient(rect.topLeft(), QPoint(rect.bottomLeft().x(), rect.bottomLeft().y()));
1416 gradient.setColorAt(0, highlightedGradientStartColor);
1417 gradient.setColorAt(1, highlightedGradientStopColor);
1418
1419 painter->setBrush(gradient);
1420
1421 painter->save();
1422 if (!complete && !indeterminate)
1423 painter->setClipRect(progressBar.adjusted(-1, -1, -1, 1));
1424 QRect fillRect = progressBar.adjusted( !indeterminate && !complete && reverse ? -2 : 0, 0,
1425 indeterminate || complete || reverse ? 0 : 2, 0);
1426 painter->drawRoundedRect(fillRect, 2, 2);
1427 painter->restore();
1428
1429 painter->setBrush(Qt::NoBrush);
1430 painter->setPen(QColor(255, 255, 255, 50));
1431 painter->drawRoundedRect(progressBar.adjusted(1, 1, -1, -1), 1, 1);
1432
1433 if (!indeterminate) {
1434#if QT_CONFIG(animation)
1435 (const_cast<QFusionStylePrivate*>(d))->stopAnimation(option->styleObject);
1436#endif
1437 } else {
1438 highlightedGradientStartColor.setAlpha(120);
1439 painter->setPen(QPen(highlightedGradientStartColor, 9.0));
1440 painter->setClipRect(progressBar.adjusted(1, 1, -1, -1));
1441#if QT_CONFIG(animation)
1442 if (QProgressStyleAnimation *animation = qobject_cast<QProgressStyleAnimation*>(d->animation(option->styleObject)))
1443 step = animation->animationStep() % 22;
1444 else
1445 (const_cast<QFusionStylePrivate*>(d))->startAnimation(new QProgressStyleAnimation(d->animationFps, option->styleObject));
1446#endif
1447 for (int x = progressBar.left() - rect.height(); x < rect.right() ; x += 22)
1448 painter->drawLine(x + step, progressBar.bottom() + 1,
1449 x + rect.height() + step, progressBar.top() - 2);
1450 }
1451 }
1452 }
1453 painter->restore();
1454 break;
1455 case CE_ProgressBarLabel:
1456 if (const QStyleOptionProgressBar *bar = qstyleoption_cast<const QStyleOptionProgressBar *>(option)) {
1457 QRect leftRect;
1458 QRect rect = bar->rect;
1459 QColor textColor = option->palette.text().color();
1460 QColor alternateTextColor = d->highlightedText(option->palette);
1461
1462 painter->save();
1463 bool vertical = false, inverted = false;
1464 vertical = (bar->orientation == Qt::Vertical);
1465 inverted = bar->invertedAppearance;
1466 if (vertical)
1467 rect = QRect(rect.left(), rect.top(), rect.height(), rect.width()); // flip width and height
1468 const auto totalSteps = qMax(Q_INT64_C(1), qint64(bar->maximum) - bar->minimum);
1469 const auto progressSteps = qint64(bar->progress) - bar->minimum;
1470 const auto progressIndicatorPos = progressSteps * rect.width() / totalSteps;
1471 if (progressIndicatorPos >= 0 && progressIndicatorPos <= rect.width())
1472 leftRect = QRect(rect.left(), rect.top(), progressIndicatorPos, rect.height());
1473 if (vertical)
1474 leftRect.translate(rect.width() - progressIndicatorPos, 0);
1475
1476 bool flip = (!vertical && (((bar->direction == Qt::RightToLeft) && !inverted) ||
1477 ((bar->direction == Qt::LeftToRight) && inverted)));
1478
1479 QRegion rightRect = rect;
1480 rightRect = rightRect.subtracted(leftRect);
1481 painter->setClipRegion(rightRect);
1482 painter->setPen(flip ? alternateTextColor : textColor);
1483 painter->drawText(rect, bar->text, QTextOption(Qt::AlignAbsolute | Qt::AlignHCenter | Qt::AlignVCenter));
1484 if (!leftRect.isNull()) {
1485 painter->setPen(flip ? textColor : alternateTextColor);
1486 painter->setClipRect(leftRect);
1487 painter->drawText(rect, bar->text, QTextOption(Qt::AlignAbsolute | Qt::AlignHCenter | Qt::AlignVCenter));
1488 }
1489 painter->restore();
1490 }
1491 break;
1492 case CE_MenuBarItem:
1493 painter->save();
1494 if (const QStyleOptionMenuItem *mbi = qstyleoption_cast<const QStyleOptionMenuItem *>(option))
1495 {
1496 QStyleOptionMenuItem item = *mbi;
1497 item.rect = mbi->rect.adjusted(0, 1, 0, -3);
1498 QColor highlightOutline = option->palette.highlight().color().darker(125);
1499 painter->fillRect(rect, option->palette.window());
1500
1501 QCommonStyle::drawControl(element, &item, painter, widget);
1502
1503 bool act = mbi->state & State_Selected && mbi->state & State_Sunken;
1504 bool dis = !(mbi->state & State_Enabled);
1505
1506 QRect r = option->rect;
1507 if (act) {
1508 painter->setBrush(option->palette.highlight().color());
1509 painter->setPen(QPen(highlightOutline));
1510 painter->drawRect(r.adjusted(0, 0, -1, -1));
1511
1512 // painter->drawRoundedRect(r.adjusted(1, 1, -1, -1), 2, 2);
1513
1514 //draw text
1515 QPalette::ColorRole textRole = dis ? QPalette::Text : QPalette::HighlightedText;
1516 uint alignment = Qt::AlignCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine;
1517 if (!styleHint(SH_UnderlineShortcut, mbi, widget))
1518 alignment |= Qt::TextHideMnemonic;
1519 proxy()->drawItemText(painter, item.rect, alignment, mbi->palette, mbi->state & State_Enabled, mbi->text, textRole);
1520 } else {
1521
1522 QColor shadow = mergedColors(option->palette.window().color().darker(120),
1523 outline.lighter(140), 60);
1524 painter->setPen(QPen(shadow));
1525 painter->drawLine(option->rect.bottomLeft(), option->rect.bottomRight());
1526 }
1527 }
1528 painter->restore();
1529 break;
1530 case CE_MenuItem:
1531 painter->save();
1532 // Draws one item in a popup menu.
1533 if (const QStyleOptionMenuItem *menuItem = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) {
1534 QColor highlightOutline = highlightedOutline;
1535 QColor highlight = option->palette.highlight().color();
1536 if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) {
1537 int w = 0;
1538 const int margin = QStyleHelper::dpiScaled(5);
1539 if (!menuItem->text.isEmpty()) {
1540 painter->setFont(menuItem->font);
1541 proxy()->drawItemText(painter, menuItem->rect.adjusted(margin, 0, -margin, 0), Qt::AlignLeft | Qt::AlignVCenter,
1542 menuItem->palette, menuItem->state & State_Enabled, menuItem->text,
1543 QPalette::Text);
1544 w = menuItem->fontMetrics.horizontalAdvance(menuItem->text) + margin;
1545 }
1546 painter->setPen(shadow.lighter(106));
1547 bool reverse = menuItem->direction == Qt::RightToLeft;
1548 painter->drawLine(menuItem->rect.left() + margin + (reverse ? 0 : w), menuItem->rect.center().y(),
1549 menuItem->rect.right() - margin - (reverse ? w : 0), menuItem->rect.center().y());
1550 painter->restore();
1551 break;
1552 }
1553 bool selected = menuItem->state & State_Selected && menuItem->state & State_Enabled;
1554 if (selected) {
1555 QRect r = option->rect;
1556 painter->fillRect(r, highlight);
1557 painter->setPen(QPen(highlightOutline));
1558 painter->drawRect(QRectF(r).adjusted(0.5, 0.5, -0.5, -0.5));
1559 }
1560 bool checkable = menuItem->checkType != QStyleOptionMenuItem::NotCheckable;
1561 bool checked = menuItem->checked;
1562 bool sunken = menuItem->state & State_Sunken;
1563 bool enabled = menuItem->state & State_Enabled;
1564
1565 bool ignoreCheckMark = false;
1566 const int checkColHOffset = windowsItemHMargin + windowsItemFrame - 1;
1567 int checkcol = qMax<int>(menuItem->rect.height() * 0.79,
1568 qMax<int>(menuItem->maxIconWidth, dpiScaled(21))); // icon checkbox's highlight column width
1569 if (
1570#if QT_CONFIG(combobox)
1571 qobject_cast<const QComboBox*>(widget) ||
1572#endif
1573 (option->styleObject && option->styleObject->property("_q_isComboBoxPopupItem").toBool()))
1574 ignoreCheckMark = true; //ignore the checkmarks provided by the QComboMenuDelegate
1575
1576 if (!ignoreCheckMark) {
1577 // Check, using qreal and QRectF to avoid error accumulation
1578 const qreal boxMargin = dpiScaled(3.5);
1579 const qreal boxWidth = checkcol - 2 * boxMargin;
1580 QRectF checkRectF(option->rect.left() + boxMargin + checkColHOffset, option->rect.center().y() - boxWidth/2 + 1, boxWidth, boxWidth);
1581 QRect checkRect = checkRectF.toRect();
1582 checkRect.setWidth(checkRect.height()); // avoid .toRect() round error results in non-perfect square
1583 checkRect = visualRect(menuItem->direction, menuItem->rect, checkRect);
1584 if (checkable) {
1585 if (menuItem->checkType & QStyleOptionMenuItem::Exclusive) {
1586 // Radio button
1587 if (checked || sunken) {
1588 painter->setRenderHint(QPainter::Antialiasing);
1589 painter->setPen(Qt::NoPen);
1590
1591 QPalette::ColorRole textRole = !enabled ? QPalette::Text:
1592 selected ? QPalette::HighlightedText : QPalette::ButtonText;
1593 painter->setBrush(option->palette.brush( option->palette.currentColorGroup(), textRole));
1594 const int adjustment = checkRect.height() * 0.3;
1595 painter->drawEllipse(checkRect.adjusted(adjustment, adjustment, -adjustment, -adjustment));
1596 }
1597 } else {
1598 // Check box
1599 if (menuItem->icon.isNull()) {
1600 QStyleOptionButton box;
1601 box.QStyleOption::operator=(*option);
1602 box.rect = checkRect;
1603 if (checked)
1604 box.state |= State_On;
1605 proxy()->drawPrimitive(PE_IndicatorCheckBox, &box, painter, widget);
1606 }
1607 }
1608 }
1609 } else { //ignore checkmark
1610 if (menuItem->icon.isNull())
1611 checkcol = 0;
1612 else
1613 checkcol = menuItem->maxIconWidth;
1614 }
1615
1616 // Text and icon, ripped from windows style
1617 bool dis = !(menuItem->state & State_Enabled);
1618 bool act = menuItem->state & State_Selected;
1619 const QStyleOption *opt = option;
1620 const QStyleOptionMenuItem *menuitem = menuItem;
1621
1622 QPainter *p = painter;
1623 QRect vCheckRect = visualRect(opt->direction, menuitem->rect,
1624 QRect(menuitem->rect.x() + checkColHOffset, menuitem->rect.y(),
1625 checkcol, menuitem->rect.height()));
1626 if (!menuItem->icon.isNull()) {
1627 QIcon::Mode mode = dis ? QIcon::Disabled : QIcon::Normal;
1628 if (act && !dis)
1629 mode = QIcon::Active;
1630 QPixmap pixmap;
1631
1632 int smallIconSize = proxy()->pixelMetric(PM_SmallIconSize, option, widget);
1633 QSize iconSize(smallIconSize, smallIconSize);
1634#if QT_CONFIG(combobox)
1635 if (const QComboBox *combo = qobject_cast<const QComboBox*>(widget))
1636 iconSize = combo->iconSize();
1637#endif
1638 if (checked)
1639 pixmap = menuItem->icon.pixmap(iconSize, mode, QIcon::On);
1640 else
1641 pixmap = menuItem->icon.pixmap(iconSize, mode);
1642
1643 const int pixw = pixmap.width() / pixmap.devicePixelRatio();
1644 const int pixh = pixmap.height() / pixmap.devicePixelRatio();
1645
1646 QRect pmr(0, 0, pixw, pixh);
1647 pmr.moveCenter(vCheckRect.center());
1648 painter->setPen(menuItem->palette.text().color());
1649 if (!ignoreCheckMark && checkable && checked) {
1650 QStyleOption opt = *option;
1651 if (act) {
1652 QColor activeColor = mergedColors(option->palette.window().color(),
1653 option->palette.highlight().color());
1654 opt.palette.setBrush(QPalette::Button, activeColor);
1655 }
1656 opt.state |= State_Sunken;
1657 opt.rect = vCheckRect;
1658 proxy()->drawPrimitive(PE_PanelButtonCommand, &opt, painter, widget);
1659 }
1660 painter->drawPixmap(pmr.topLeft(), pixmap);
1661 }
1662 if (selected) {
1663 painter->setPen(menuItem->palette.highlightedText().color());
1664 } else {
1665 painter->setPen(menuItem->palette.text().color());
1666 }
1667 int x, y, w, h;
1668 menuitem->rect.getRect(&x, &y, &w, &h);
1669 int tab = menuitem->tabWidth;
1670 QColor discol;
1671 if (dis) {
1672 discol = menuitem->palette.text().color();
1673 p->setPen(discol);
1674 }
1675 int xm = checkColHOffset + checkcol + windowsItemHMargin;
1676 int xpos = menuitem->rect.x() + xm;
1677
1678 QRect textRect(xpos, y + windowsItemVMargin, w - xm - windowsRightBorder - tab + 1, h - 2 * windowsItemVMargin);
1679 QRect vTextRect = visualRect(opt->direction, menuitem->rect, textRect);
1680 QStringRef s(&menuitem->text);
1681 if (!s.isEmpty()) { // draw text
1682 p->save();
1683 int t = s.indexOf(QLatin1Char('\t'));
1684 int text_flags = Qt::AlignVCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine;
1685 if (!styleHint(SH_UnderlineShortcut, menuitem, widget))
1686 text_flags |= Qt::TextHideMnemonic;
1687 text_flags |= Qt::AlignLeft;
1688 if (t >= 0) {
1689 QRect vShortcutRect = visualRect(opt->direction, menuitem->rect,
1690 QRect(textRect.topRight(), QPoint(menuitem->rect.right(), textRect.bottom())));
1691 const QString textToDraw = s.mid(t + 1).toString();
1692 if (dis && !act && proxy()->styleHint(SH_EtchDisabledText, option, widget)) {
1693 p->setPen(menuitem->palette.light().color());
1694 p->drawText(vShortcutRect.adjusted(1, 1, 1, 1), text_flags, textToDraw);
1695 p->setPen(discol);
1696 }
1697 p->drawText(vShortcutRect, text_flags, textToDraw);
1698 s = s.left(t);
1699 }
1700 QFont font = menuitem->font;
1701 // font may not have any "hard" flags set. We override
1702 // the point size so that when it is resolved against the device, this font will win.
1703 // This is mainly to handle cases where someone sets the font on the window
1704 // and then the combo inherits it and passes it onward. At that point the resolve mask
1705 // is very, very weak. This makes it stonger.
1706 font.setPointSizeF(QFontInfo(menuItem->font).pointSizeF());
1707
1708 if (menuitem->menuItemType == QStyleOptionMenuItem::DefaultItem)
1709 font.setBold(true);
1710
1711 p->setFont(font);
1712 const QString textToDraw = s.left(t).toString();
1713 if (dis && !act && proxy()->styleHint(SH_EtchDisabledText, option, widget)) {
1714 p->setPen(menuitem->palette.light().color());
1715 p->drawText(vTextRect.adjusted(1, 1, 1, 1), text_flags, textToDraw);
1716 p->setPen(discol);
1717 }
1718 p->drawText(vTextRect, text_flags, textToDraw);
1719 p->restore();
1720 }
1721
1722 // Arrow
1723 if (menuItem->menuItemType == QStyleOptionMenuItem::SubMenu) {// draw sub menu arrow
1724 int dim = (menuItem->rect.height() - 4) / 2;
1725 PrimitiveElement arrow;
1726 arrow = option->direction == Qt::RightToLeft ? PE_IndicatorArrowLeft : PE_IndicatorArrowRight;
1727 int xpos = menuItem->rect.left() + menuItem->rect.width() - 3 - dim;
1728 QRect vSubMenuRect = visualRect(option->direction, menuItem->rect,
1729 QRect(xpos, menuItem->rect.top() + menuItem->rect.height() / 2 - dim / 2, dim, dim));
1730 QStyleOptionMenuItem newMI = *menuItem;
1731 newMI.rect = vSubMenuRect;
1732 newMI.state = !enabled ? State_None : State_Enabled;
1733 if (selected)
1734 newMI.palette.setColor(QPalette::WindowText,
1735 newMI.palette.highlightedText().color());
1736 proxy()->drawPrimitive(arrow, &newMI, painter, widget);
1737 }
1738 }
1739 painter->restore();
1740 break;
1741 case CE_MenuHMargin:
1742 case CE_MenuVMargin:
1743 break;
1744 case CE_MenuEmptyArea:
1745 break;
1746 case CE_PushButton:
1747 if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) {
1748 proxy()->drawControl(CE_PushButtonBevel, btn, painter, widget);
1749 QStyleOptionButton subopt = *btn;
1750 subopt.rect = subElementRect(SE_PushButtonContents, btn, widget);
1751 proxy()->drawControl(CE_PushButtonLabel, &subopt, painter, widget);
1752 }
1753 break;
1754 case CE_PushButtonLabel:
1755 if (const QStyleOptionButton *button = qstyleoption_cast<const QStyleOptionButton *>(option)) {
1756 QRect ir = button->rect;
1757 uint tf = Qt::AlignVCenter;
1758 if (styleHint(SH_UnderlineShortcut, button, widget))
1759 tf |= Qt::TextShowMnemonic;
1760 else
1761 tf |= Qt::TextHideMnemonic;
1762
1763 if (!button->icon.isNull()) {
1764 //Center both icon and text
1765 QPoint point;
1766
1767 QIcon::Mode mode = button->state & State_Enabled ? QIcon::Normal
1768 : QIcon::Disabled;
1769 if (mode == QIcon::Normal && button->state & State_HasFocus)
1770 mode = QIcon::Active;
1771 QIcon::State state = QIcon::Off;
1772 if (button->state & State_On)
1773 state = QIcon::On;
1774
1775 QPixmap pixmap = button->icon.pixmap(button->iconSize, mode, state);
1776 int w = pixmap.width() / pixmap.devicePixelRatio();
1777 int h = pixmap.height() / pixmap.devicePixelRatio();
1778
1779 if (!button->text.isEmpty())
1780 w += button->fontMetrics.boundingRect(option->rect, tf, button->text).width() + 2;
1781
1782 point = QPoint(ir.x() + ir.width() / 2 - w / 2,
1783 ir.y() + ir.height() / 2 - h / 2);
1784
1785 w = pixmap.width() / pixmap.devicePixelRatio();
1786
1787 if (button->direction == Qt::RightToLeft)
1788 point.rx() += w;
1789
1790 painter->drawPixmap(visualPos(button->direction, button->rect, point), pixmap);
1791
1792 if (button->direction == Qt::RightToLeft)
1793 ir.translate(-point.x() - 2, 0);
1794 else
1795 ir.translate(point.x() + w, 0);
1796
1797 // left-align text if there is
1798 if (!button->text.isEmpty())
1799 tf |= Qt::AlignLeft;
1800
1801 } else {
1802 tf |= Qt::AlignHCenter;
1803 }
1804
1805 if (button->features & QStyleOptionButton::HasMenu)
1806 ir = ir.adjusted(0, 0, -proxy()->pixelMetric(PM_MenuButtonIndicator, button, widget), 0);
1807 proxy()->drawItemText(painter, ir, tf, button->palette, (button->state & State_Enabled),
1808 button->text, QPalette::ButtonText);
1809 }
1810 break;
1811 case CE_MenuBarEmptyArea:
1812 painter->save();
1813 {
1814 painter->fillRect(rect, option->palette.window());
1815 QColor shadow = mergedColors(option->palette.window().color().darker(120),
1816 outline.lighter(140), 60);
1817 painter->setPen(QPen(shadow));
1818 painter->drawLine(option->rect.bottomLeft(), option->rect.bottomRight());
1819 }
1820 painter->restore();
1821 break;
1822#if QT_CONFIG(tabbar)
1823 case CE_TabBarTabShape:
1824 painter->save();
1825 if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(option)) {
1826
1827 bool rtlHorTabs = (tab->direction == Qt::RightToLeft
1828 && (tab->shape == QTabBar::RoundedNorth
1829 || tab->shape == QTabBar::RoundedSouth));
1830 bool selected = tab->state & State_Selected;
1831 bool lastTab = ((!rtlHorTabs && tab->position == QStyleOptionTab::End)
1832 || (rtlHorTabs
1833 && tab->position == QStyleOptionTab::Beginning));
1834 bool onlyOne = tab->position == QStyleOptionTab::OnlyOneTab;
1835 int tabOverlap = pixelMetric(PM_TabBarTabOverlap, option, widget);
1836 rect = option->rect.adjusted(0, 0, (onlyOne || lastTab) ? 0 : tabOverlap, 0);
1837
1838 QRect r2(rect);
1839 int x1 = r2.left();
1840 int x2 = r2.right();
1841 int y1 = r2.top();
1842 int y2 = r2.bottom();
1843
1844 painter->setPen(d->innerContrastLine());
1845
1846 QTransform rotMatrix;
1847 bool flip = false;
1848 painter->setPen(shadow);
1849
1850 switch (tab->shape) {
1851 case QTabBar::RoundedNorth:
1852 break;
1853 case QTabBar::RoundedSouth:
1854 rotMatrix.rotate(180);
1855 rotMatrix.translate(0, -rect.height() + 1);
1856 rotMatrix.scale(-1, 1);
1857 painter->setTransform(rotMatrix, true);
1858 break;
1859 case QTabBar::RoundedWest:
1860 rotMatrix.rotate(180 + 90);
1861 rotMatrix.scale(-1, 1);
1862 flip = true;
1863 painter->setTransform(rotMatrix, true);
1864 break;
1865 case QTabBar::RoundedEast:
1866 rotMatrix.rotate(90);
1867 rotMatrix.translate(0, - rect.width() + 1);
1868 flip = true;
1869 painter->setTransform(rotMatrix, true);
1870 break;
1871 default:
1872 painter->restore();
1873 QCommonStyle::drawControl(element, tab, painter, widget);
1874 return;
1875 }
1876
1877 if (flip) {
1878 QRect tmp = rect;
1879 rect = QRect(tmp.y(), tmp.x(), tmp.height(), tmp.width());
1880 int temp = x1;
1881 x1 = y1;
1882 y1 = temp;
1883 temp = x2;
1884 x2 = y2;
1885 y2 = temp;
1886 }
1887
1888 painter->setRenderHint(QPainter::Antialiasing, true);
1889 painter->translate(0.5, 0.5);
1890
1891 QColor tabFrameColor = tab->features & QStyleOptionTab::HasFrame ?
1892 d->tabFrameColor(option->palette) :
1893 option->palette.window().color();
1894
1895 QLinearGradient fillGradient(rect.topLeft(), rect.bottomLeft());
1896 QLinearGradient outlineGradient(rect.topLeft(), rect.bottomLeft());
1897 QPen outlinePen = outline.lighter(110);
1898 if (