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 "qwindowsstyle_p.h"
41#include "qwindowsstyle_p_p.h"
42
43#if QT_CONFIG(style_windows) || defined(QT_PLUGIN)
44
45#include "qapplication.h"
46#include "qbitmap.h"
47#include "qdrawutil.h" // for now
48#include "qevent.h"
49#if QT_CONFIG(menu)
50#include "qmenu.h"
51#endif
52#if QT_CONFIG(menubar)
53#include "qmenubar.h"
54#include <private/qmenubar_p.h>
55#endif
56#include "qpaintengine.h"
57#include "qpainter.h"
58#if QT_CONFIG(rubberband)
59#include "qrubberband.h"
60#endif
61#include "qstyleoption.h"
62#if QT_CONFIG(tabbar)
63#include "qtabbar.h"
64#endif
65#include "qwidget.h"
66#include "qdebug.h"
67#if QT_CONFIG(mainwindow)
68#include "qmainwindow.h"
69#endif
70#include "qfile.h"
71#include "qtextstream.h"
72#include "qpixmapcache.h"
73#if QT_CONFIG(wizard)
74#include "qwizard.h"
75#endif
76#if QT_CONFIG(listview)
77#include "qlistview.h"
78#endif
79#include <private/qmath_p.h>
80#include <qmath.h>
81#include <QtGui/qscreen.h>
82#include <QtGui/qwindow.h>
83#include <qpa/qplatformtheme.h>
84#include <qpa/qplatformscreen.h>
85#include <private/qguiapplication_p.h>
86#include <private/qhighdpiscaling_p.h>
87#include <private/qwidget_p.h>
88
89#include <private/qstylehelper_p.h>
90#if QT_CONFIG(animation)
91#include <private/qstyleanimation_p.h>
92#endif
93
94#include <algorithm>
95
96QT_BEGIN_NAMESPACE
97
98#if defined(Q_OS_WIN)
99
100QT_BEGIN_INCLUDE_NAMESPACE
101#include "qt_windows.h"
102QT_END_INCLUDE_NAMESPACE
103# ifndef COLOR_GRADIENTACTIVECAPTION
104# define COLOR_GRADIENTACTIVECAPTION 27
105# endif
106# ifndef COLOR_GRADIENTINACTIVECAPTION
107# define COLOR_GRADIENTINACTIVECAPTION 28
108# endif
109
110Q_GUI_EXPORT HICON qt_pixmapToWinHICON(const QPixmap &);
111#endif //Q_OS_WIN
112
113QT_BEGIN_INCLUDE_NAMESPACE
114#include <limits.h>
115QT_END_INCLUDE_NAMESPACE
116
117enum QSliderDirection { SlUp, SlDown, SlLeft, SlRight };
118
119/*
120 \internal
121*/
122
123QWindowsStylePrivate::QWindowsStylePrivate()
124 : alt_down(false), menuBarTimer(0)
125{
126}
127
128qreal QWindowsStylePrivate::appDevicePixelRatio()
129{
130 return qApp->devicePixelRatio();
131}
132
133// Returns \c true if the toplevel parent of \a widget has seen the Alt-key
134bool QWindowsStylePrivate::hasSeenAlt(const QWidget *widget) const
135{
136 widget = widget->window();
137 return seenAlt.contains(widget);
138}
139
140/*!
141 \reimp
142*/
143bool QWindowsStyle::eventFilter(QObject *o, QEvent *e)
144{
145 // Records Alt- and Focus events
146 if (!o->isWidgetType())
147 return QObject::eventFilter(o, e);
148
149 QWidget *widget = qobject_cast<QWidget*>(o);
150 Q_D(QWindowsStyle);
151 switch(e->type()) {
152 case QEvent::KeyPress:
153 if (static_cast<QKeyEvent *>(e)->key() == Qt::Key_Alt) {
154 widget = widget->window();
155
156 // Alt has been pressed - find all widgets that care
157 QList<QWidget *> l = widget->findChildren<QWidget *>();
158 auto ignorable = [](QWidget *w) {
159 return w->isWindow() || !w->isVisible()
160 || w->style()->styleHint(SH_UnderlineShortcut, 0, w);
161 };
162 l.erase(std::remove_if(l.begin(), l.end(), ignorable), l.end());
163 // Update states before repainting
164 d->seenAlt.append(widget);
165 d->alt_down = true;
166
167 // Repaint all relevant widgets
168 for (int pos = 0; pos < l.size(); ++pos)
169 l.at(pos)->update();
170 }
171 break;
172 case QEvent::KeyRelease:
173 if (static_cast<QKeyEvent*>(e)->key() == Qt::Key_Alt) {
174 widget = widget->window();
175
176 // Update state and repaint the menu bars.
177 d->alt_down = false;
178#if QT_CONFIG(menubar)
179 QList<QMenuBar *> l = widget->findChildren<QMenuBar *>();
180 for (int i = 0; i < l.size(); ++i)
181 l.at(i)->update();
182#endif
183 }
184 break;
185 case QEvent::Close:
186 // Reset widget when closing
187 d->seenAlt.removeAll(widget);
188 d->seenAlt.removeAll(widget->window());
189 break;
190 default:
191 break;
192 }
193 return QCommonStyle::eventFilter(o, e);
194}
195
196/*!
197 \class QWindowsStyle
198 \brief The QWindowsStyle class provides a Microsoft Windows-like look and feel.
199
200 \ingroup appearance
201 \inmodule QtWidgets
202 \internal
203
204 This style is Qt's default GUI style on Windows.
205
206 \image qwindowsstyle.png
207 \sa QWindowsVistaStyle, QMacStyle, QFusionStyle
208*/
209
210/*!
211 Constructs a QWindowsStyle object.
212*/
213QWindowsStyle::QWindowsStyle() : QCommonStyle(*new QWindowsStylePrivate)
214{
215}
216
217/*!
218 \internal
219
220 Constructs a QWindowsStyle object.
221*/
222QWindowsStyle::QWindowsStyle(QWindowsStylePrivate &dd) : QCommonStyle(dd)
223{
224}
225
226
227/*! Destroys the QWindowsStyle object. */
228QWindowsStyle::~QWindowsStyle()
229{
230}
231
232#ifdef Q_OS_WIN
233static inline QRgb colorref2qrgb(COLORREF col)
234{
235 return qRgb(GetRValue(col), GetGValue(col), GetBValue(col));
236}
237#endif
238
239/*! \reimp */
240void QWindowsStyle::polish(QApplication *app)
241{
242 QCommonStyle::polish(app);
243 QWindowsStylePrivate *d = const_cast<QWindowsStylePrivate*>(d_func());
244 // We only need the overhead when shortcuts are sometimes hidden
245 if (!proxy()->styleHint(SH_UnderlineShortcut, 0) && app)
246 app->installEventFilter(this);
247
248 const auto &palette = QGuiApplication::palette();
249 d->activeGradientCaptionColor = palette.highlight().color();
250 d->activeCaptionColor = d->activeGradientCaptionColor;
251 d->inactiveGradientCaptionColor = palette.dark().color();
252 d->inactiveCaptionColor = d->inactiveGradientCaptionColor;
253 d->inactiveCaptionText = palette.window().color();
254
255#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) //fetch native title bar colors
256 if(app->desktopSettingsAware()){
257 DWORD activeCaption = GetSysColor(COLOR_ACTIVECAPTION);
258 DWORD gradientActiveCaption = GetSysColor(COLOR_GRADIENTACTIVECAPTION);
259 DWORD inactiveCaption = GetSysColor(COLOR_INACTIVECAPTION);
260 DWORD gradientInactiveCaption = GetSysColor(COLOR_GRADIENTINACTIVECAPTION);
261 DWORD inactiveCaptionText = GetSysColor(COLOR_INACTIVECAPTIONTEXT);
262 d->activeCaptionColor = colorref2qrgb(activeCaption);
263 d->activeGradientCaptionColor = colorref2qrgb(gradientActiveCaption);
264 d->inactiveCaptionColor = colorref2qrgb(inactiveCaption);
265 d->inactiveGradientCaptionColor = colorref2qrgb(gradientInactiveCaption);
266 d->inactiveCaptionText = colorref2qrgb(inactiveCaptionText);
267 }
268#endif
269}
270
271/*! \reimp */
272void QWindowsStyle::unpolish(QApplication *app)
273{
274 QCommonStyle::unpolish(app);
275 app->removeEventFilter(this);
276}
277
278/*! \reimp */
279void QWindowsStyle::polish(QWidget *widget)
280{
281 QCommonStyle::polish(widget);
282}
283
284/*! \reimp */
285void QWindowsStyle::unpolish(QWidget *widget)
286{
287 QCommonStyle::unpolish(widget);
288}
289
290/*!
291 \reimp
292*/
293void QWindowsStyle::polish(QPalette &pal)
294{
295 QCommonStyle::polish(pal);
296}
297
298int QWindowsStylePrivate::pixelMetricFromSystemDp(QStyle::PixelMetric pm, const QStyleOption *, const QWidget *widget)
299{
300#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
301 switch (pm) {
302 case QStyle::PM_DockWidgetFrameWidth:
303 return GetSystemMetrics(SM_CXFRAME);
304
305 case QStyle::PM_TitleBarHeight:
306 if (widget && (widget->windowType() == Qt::Tool)) {
307 // MS always use one less than they say
308 return GetSystemMetrics(SM_CYSMCAPTION) - 1;
309 }
310 return GetSystemMetrics(SM_CYCAPTION) - 1;
311
312 case QStyle::PM_ScrollBarExtent:
313 {
314 NONCLIENTMETRICS ncm;
315 ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICS, lfMessageFont) + sizeof(LOGFONT);
316 if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0))
317 return qMax(ncm.iScrollHeight, ncm.iScrollWidth);
318 }
319 break;
320
321 case QStyle::PM_MdiSubWindowFrameWidth:
322 return GetSystemMetrics(SM_CYFRAME);
323
324 default:
325 break;
326 }
327#else // Q_OS_WIN && !Q_OS_WINRT
328 Q_UNUSED(pm);
329 Q_UNUSED(widget);
330#endif
331 return QWindowsStylePrivate::InvalidMetric;
332}
333
334int QWindowsStylePrivate::fixedPixelMetric(QStyle::PixelMetric pm)
335{
336 switch (pm) {
337 case QStyle::PM_ToolBarItemSpacing:
338 return 0;
339 case QStyle::PM_ButtonDefaultIndicator:
340 case QStyle::PM_ButtonShiftHorizontal:
341 case QStyle::PM_ButtonShiftVertical:
342 case QStyle::PM_MenuHMargin:
343 case QStyle::PM_MenuVMargin:
344 case QStyle::PM_ToolBarItemMargin:
345 return 1;
346 break;
347 case QStyle::PM_DockWidgetSeparatorExtent:
348 return 4;
349#if QT_CONFIG(tabbar)
350 case QStyle::PM_TabBarTabShiftHorizontal:
351 return 0;
352 case QStyle::PM_TabBarTabShiftVertical:
353 return 2;
354#endif
355
356#if QT_CONFIG(slider)
357 case QStyle::PM_SliderLength:
358 return 11;
359#endif // QT_CONFIG(slider)
360
361#if QT_CONFIG(menu)
362 case QStyle::PM_MenuBarHMargin:
363 case QStyle::PM_MenuBarVMargin:
364 case QStyle::PM_MenuBarPanelWidth:
365 return 0;
366 case QStyle::PM_SmallIconSize:
367 return 16;
368 case QStyle::PM_LargeIconSize:
369 return 32;
370 case QStyle::PM_DockWidgetTitleMargin:
371 return 2;
372 case QStyle::PM_DockWidgetTitleBarButtonMargin:
373 case QStyle::PM_DockWidgetFrameWidth:
374 return 4;
375
376#endif // QT_CONFIG(menu)
377 case QStyle::PM_ToolBarHandleExtent:
378 return 10;
379 default:
380 break;
381 }
382 return QWindowsStylePrivate::InvalidMetric;
383}
384
385static QScreen *screenOf(const QWidget *w)
386{
387 if (w) {
388 if (auto screen = qt_widget_private(const_cast<QWidget *>(w))->associatedScreen())
389 return screen;
390 }
391 return QGuiApplication::primaryScreen();
392}
393
394// Calculate the overall scale factor to obtain Qt Device Independent
395// Pixels from a native Windows size. Divide by devicePixelRatio
396// and account for secondary screens with differing logical DPI.
397qreal QWindowsStylePrivate::nativeMetricScaleFactor(const QWidget *widget)
398{
399 if (!QHighDpiScaling::isActive())
400 return 1;
401 qreal result = qreal(1) / QWindowsStylePrivate::devicePixelRatio(widget);
402 if (QGuiApplicationPrivate::screen_list.size() > 1) {
403 const QScreen *primaryScreen = QGuiApplication::primaryScreen();
404 const QScreen *screen = screenOf(widget);
405 if (screen != primaryScreen) {
406 const qreal primaryLogicalDpi = primaryScreen->handle()->logicalDpi().first;
407 const qreal logicalDpi = screen->handle()->logicalDpi().first;
408 if (!qFuzzyCompare(primaryLogicalDpi, logicalDpi))
409 result *= logicalDpi / primaryLogicalDpi;
410 }
411 }
412 return result;
413}
414
415/*!
416 \reimp
417*/
418int QWindowsStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, const QWidget *widget) const
419{
420 int ret = QWindowsStylePrivate::pixelMetricFromSystemDp(pm, opt, widget);
421 if (ret != QWindowsStylePrivate::InvalidMetric)
422 return qRound(qreal(ret) * QWindowsStylePrivate::nativeMetricScaleFactor(widget));
423
424 ret = QWindowsStylePrivate::fixedPixelMetric(pm);
425 if (ret != QWindowsStylePrivate::InvalidMetric)
426 return int(QStyleHelper::dpiScaled(ret));
427
428 ret = 0;
429
430 switch (pm) {
431 case PM_MaximumDragDistance:
432 ret = QCommonStyle::pixelMetric(PM_MaximumDragDistance);
433 if (ret == -1)
434 ret = 60;
435 break;
436
437#if QT_CONFIG(slider)
438 // Returns the number of pixels to use for the business part of the
439 // slider (i.e., the non-tickmark portion). The remaining space is shared
440 // equally between the tickmark regions.
441 case PM_SliderControlThickness:
442 if (const QStyleOptionSlider *sl = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
443 int space = (sl->orientation == Qt::Horizontal) ? sl->rect.height() : sl->rect.width();
444 int ticks = sl->tickPosition;
445 int n = 0;
446 if (ticks & QSlider::TicksAbove)
447 ++n;
448 if (ticks & QSlider::TicksBelow)
449 ++n;
450 if (!n) {
451 ret = space;
452 break;
453 }
454
455 int thick = 6; // Magic constant to get 5 + 16 + 5
456 if (ticks != QSlider::TicksBothSides && ticks != QSlider::NoTicks)
457 thick += proxy()->pixelMetric(PM_SliderLength, sl, widget) / 4;
458
459 space -= thick;
460 if (space > 0)
461 thick += (space * 2) / (n + 2);
462 ret = thick;
463 }
464 break;
465#endif // QT_CONFIG(slider)
466
467 case PM_IconViewIconSize:
468 ret = proxy()->pixelMetric(PM_LargeIconSize, opt, widget);
469 break;
470
471 case PM_SplitterWidth:
472 ret = qMax(int(QStyleHelper::dpiScaled(4)), QApplication::globalStrut().width());
473 break;
474
475 default:
476 ret = QCommonStyle::pixelMetric(pm, opt, widget);
477 break;
478 }
479
480 return ret;
481}
482
483/*!
484 \reimp
485 */
486QPixmap QWindowsStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt,
487 const QWidget *widget) const
488{
489#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
490 QPixmap desktopIcon;
491 switch(standardPixmap) {
492 case SP_DriveCDIcon:
493 case SP_DriveDVDIcon:
494 case SP_DriveNetIcon:
495 case SP_DriveHDIcon:
496 case SP_DriveFDIcon:
497 case SP_FileIcon:
498 case SP_FileLinkIcon:
499 case SP_DirLinkIcon:
500 case SP_DirClosedIcon:
501 case SP_DesktopIcon:
502 case SP_ComputerIcon:
503 case SP_DirOpenIcon:
504 case SP_FileDialogNewFolder:
505 case SP_DirHomeIcon:
506 case SP_TrashIcon:
507 case SP_VistaShield:
508 if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) {
509 QPlatformTheme::StandardPixmap sp = static_cast<QPlatformTheme::StandardPixmap>(standardPixmap);
510 desktopIcon = theme->standardPixmap(sp, QSizeF(16, 16));
511 }
512 break;
513 case SP_MessageBoxInformation:
514 case SP_MessageBoxWarning:
515 case SP_MessageBoxCritical:
516 case SP_MessageBoxQuestion:
517 if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) {
518 QPlatformTheme::StandardPixmap sp = static_cast<QPlatformTheme::StandardPixmap>(standardPixmap);
519 desktopIcon = theme->standardPixmap(sp, QSizeF());
520 }
521 break;
522 default:
523 break;
524 }
525 if (!desktopIcon.isNull()) {
526 return desktopIcon;
527 }
528#endif // Q_OS_WIN && !Q_OS_WINRT
529 return QCommonStyle::standardPixmap(standardPixmap, opt, widget);
530}
531
532/*! \reimp */
533int QWindowsStyle::styleHint(StyleHint hint, const QStyleOption *opt, const QWidget *widget,
534 QStyleHintReturn *returnData) const
535{
536 int ret = 0;
537
538 switch (hint) {
539 case SH_EtchDisabledText:
540 case SH_Slider_SnapToValue:
541 case SH_PrintDialog_RightAlignButtons:
542 case SH_FontDialog_SelectAssociatedText:
543 case SH_Menu_AllowActiveAndDisabled:
544 case SH_MenuBar_AltKeyNavigation:
545 case SH_MenuBar_MouseTracking:
546 case SH_Menu_MouseTracking:
547 case SH_ComboBox_ListMouseTracking:
548 case SH_Slider_StopMouseOverSlider:
549 case SH_MainWindow_SpaceBelowMenuBar:
550 ret = 1;
551
552 break;
553 case SH_ItemView_ShowDecorationSelected:
554#if QT_CONFIG(listview)
555 if (qobject_cast<const QListView*>(widget))
556 ret = 1;
557#endif
558 break;
559 case SH_ItemView_ChangeHighlightOnFocus:
560 ret = 1;
561 break;
562 case SH_ToolBox_SelectedPageTitleBold:
563 ret = 0;
564 break;
565
566#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) // Option not used on WinRT -> common style
567 case SH_UnderlineShortcut:
568 {
569 ret = 1;
570 BOOL cues = false;
571 SystemParametersInfo(SPI_GETKEYBOARDCUES, 0, &cues, 0);
572 ret = int(cues);
573 // Do nothing if we always paint underlines
574 Q_D(const QWindowsStyle);
575 if (!ret && widget && d) {
576#if QT_CONFIG(menubar)
577 const QMenuBar *menuBar = qobject_cast<const QMenuBar *>(widget);
578 if (!menuBar && qobject_cast<const QMenu *>(widget)) {
579 QWidget *w = QApplication::activeWindow();
580 if (w && w != widget)
581 menuBar = w->findChild<QMenuBar *>();
582 }
583 // If we paint a menu bar draw underlines if is in the keyboardState
584 if (menuBar) {
585 if (menuBar->d_func()->keyboardState || d->altDown())
586 ret = 1;
587 // Otherwise draw underlines if the toplevel widget has seen an alt-press
588 } else
589#endif // QT_CONFIG(menubar)
590 if (d->hasSeenAlt(widget)) {
591 ret = 1;
592 }
593 }
594#ifndef QT_NO_ACCESSIBILITY
595 if (!ret && opt && opt->type == QStyleOption::SO_MenuItem
596 && QStyleHelper::isInstanceOf(opt->styleObject, QAccessible::MenuItem)
597 && opt->styleObject->property("_q_showUnderlined").toBool())
598 ret = 1;
599#endif // QT_NO_ACCESSIBILITY
600 break;
601 }
602#endif // Q_OS_WIN && !Q_OS_WINRT
603 case SH_Menu_SubMenuSloppyCloseTimeout:
604 case SH_Menu_SubMenuPopupDelay: {
605#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
606 DWORD delay;
607 if (SystemParametersInfo(SPI_GETMENUSHOWDELAY, 0, &delay, 0))
608 ret = delay;
609 else
610#endif // Q_OS_WIN && !Q_OS_WINRT
611 ret = 400;
612 break;
613 }
614#if QT_CONFIG(rubberband)
615 case SH_RubberBand_Mask:
616 if (const QStyleOptionRubberBand *rbOpt = qstyleoption_cast<const QStyleOptionRubberBand *>(opt)) {
617 ret = 0;
618 if (rbOpt->shape == QRubberBand::Rectangle) {
619 ret = true;
620 if(QStyleHintReturnMask *mask = qstyleoption_cast<QStyleHintReturnMask*>(returnData)) {
621 mask->region = opt->rect;
622 int size = 1;
623 if (widget && widget->isWindow())
624 size = 4;
625 mask->region -= opt->rect.adjusted(size, size, -size, -size);
626 }
627 }
628 }
629 break;
630#endif // QT_CONFIG(rubberband)
631#if QT_CONFIG(wizard)
632 case SH_WizardStyle:
633 ret = QWizard::ModernStyle;
634 break;
635#endif
636 case SH_ItemView_ArrowKeysNavigateIntoChildren:
637 ret = true;
638 break;
639 case SH_DialogButtonBox_ButtonsHaveIcons:
640 ret = 0;
641 break;
642 default:
643 ret = QCommonStyle::styleHint(hint, opt, widget, returnData);
644 break;
645 }
646 return ret;
647}
648
649/*! \reimp */
650void QWindowsStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPainter *p,
651 const QWidget *w) const
652{
653 // Used to restore across fallthrough cases. Currently only used in PE_IndicatorCheckBox
654 bool doRestore = false;
655
656 switch (pe) {
657#if QT_CONFIG(toolbar)
658 case PE_IndicatorToolBarSeparator:
659 {
660 QRect rect = opt->rect;
661 const int margin = 2;
662 QPen oldPen = p->pen();
663 if(opt->state & State_Horizontal){
664 const int offset = rect.width()/2;
665 p->setPen(QPen(opt->palette.dark().color()));
666 p->drawLine(rect.bottomLeft().x() + offset,
667 rect.bottomLeft().y() - margin,
668 rect.topLeft().x() + offset,
669 rect.topLeft().y() + margin);
670 p->setPen(QPen(opt->palette.light().color()));
671 p->drawLine(rect.bottomLeft().x() + offset + 1,
672 rect.bottomLeft().y() - margin,
673 rect.topLeft().x() + offset + 1,
674 rect.topLeft().y() + margin);
675 }
676 else{ //Draw vertical separator
677 const int offset = rect.height()/2;
678 p->setPen(QPen(opt->palette.dark().color()));
679 p->drawLine(rect.topLeft().x() + margin ,
680 rect.topLeft().y() + offset,
681 rect.topRight().x() - margin,
682 rect.topRight().y() + offset);
683 p->setPen(QPen(opt->palette.light().color()));
684 p->drawLine(rect.topLeft().x() + margin ,
685 rect.topLeft().y() + offset + 1,
686 rect.topRight().x() - margin,
687 rect.topRight().y() + offset + 1);
688 }
689 p->setPen(oldPen);
690 }
691 break;
692 case PE_IndicatorToolBarHandle:
693 p->save();
694 p->translate(opt->rect.x(), opt->rect.y());
695 if (opt->state & State_Horizontal) {
696 int x = opt->rect.width() / 2 - 4;
697 if (opt->direction == Qt::RightToLeft)
698 x -= 2;
699 if (opt->rect.height() > 4) {
700 qDrawShadePanel(p, x, 2, 3, opt->rect.height() - 4,
701 opt->palette, false, 1, 0);
702 qDrawShadePanel(p, x + 3, 2, 3, opt->rect.height() - 4,
703 opt->palette, false, 1, 0);
704 }
705 } else {
706 if (opt->rect.width() > 4) {
707 int y = opt->rect.height() / 2 - 4;
708 qDrawShadePanel(p, 2, y, opt->rect.width() - 4, 3,
709 opt->palette, false, 1, 0);
710 qDrawShadePanel(p, 2, y + 3, opt->rect.width() - 4, 3,
711 opt->palette, false, 1, 0);
712 }
713 }
714 p->restore();
715 break;
716
717#endif // QT_CONFIG(toolbar)
718 case PE_FrameButtonTool:
719 case PE_PanelButtonTool: {
720 QPen oldPen = p->pen();
721#if QT_CONFIG(dockwidget)
722 if (w && w->inherits("QDockWidgetTitleButton")) {
723 if (const QWidget *dw = w->parentWidget())
724 if (dw->isWindow()){
725 qDrawWinButton(p, opt->rect.adjusted(1, 1, 0, 0), opt->palette, opt->state & (State_Sunken | State_On),
726 &opt->palette.button());
727
728 return;
729 }
730 }
731#endif // QT_CONFIG(dockwidget)
732 QBrush fill;
733 bool stippled;
734 bool panel = (pe == PE_PanelButtonTool);
735 if ((!(opt->state & State_Sunken ))
736 && (!(opt->state & State_Enabled)
737 || !(opt->state & State_MouseOver && opt->state & State_AutoRaise))
738 && (opt->state & State_On)) {
739 fill = QBrush(opt->palette.light().color(), Qt::Dense4Pattern);
740 stippled = true;
741 } else {
742 fill = opt->palette.brush(QPalette::Button);
743 stippled = false;
744 }
745
746 if (opt->state & (State_Raised | State_Sunken | State_On)) {
747 if (opt->state & State_AutoRaise) {
748 if(opt->state & (State_Enabled | State_Sunken | State_On)){
749 if (panel)
750 qDrawShadePanel(p, opt->rect, opt->palette,
751 opt->state & (State_Sunken | State_On), 1, &fill);
752 else
753 qDrawShadeRect(p, opt->rect, opt->palette,
754 opt->state & (State_Sunken | State_On), 1);
755 }
756 if (stippled) {
757 p->setPen(opt->palette.button().color());
758 p->drawRect(opt->rect.adjusted(1,1,-2,-2));
759 }
760 } else {
761 qDrawWinButton(p, opt->rect, opt->palette,
762 opt->state & (State_Sunken | State_On), panel ? &fill : 0);
763 }
764 } else {
765 p->fillRect(opt->rect, fill);
766 }
767 p->setPen(oldPen);
768 break; }
769 case PE_PanelButtonCommand:
770 if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
771 QBrush fill;
772 State flags = opt->state;
773 QPalette pal = opt->palette;
774 QRect r = opt->rect;
775 if (! (flags & State_Sunken) && (flags & State_On))
776 fill = QBrush(pal.light().color(), Qt::Dense4Pattern);
777 else
778 fill = pal.brush(QPalette::Button);
779
780 if (btn->features & QStyleOptionButton::DefaultButton && flags & State_Sunken) {
781 p->setPen(pal.dark().color());
782 p->setBrush(fill);
783 p->drawRect(r.adjusted(0, 0, -1, -1));
784 } else if (flags & (State_Raised | State_On | State_Sunken)) {
785 qDrawWinButton(p, r, pal, flags & (State_Sunken | State_On),
786 &fill);
787 } else {
788 p->fillRect(r, fill);
789 }
790 }
791 break;
792 case PE_FrameDefaultButton: {
793 QPen oldPen = p->pen();
794 p->setPen(QPen(opt->palette.shadow().color(), 0));
795 QRectF rect = opt->rect;
796 const qreal topLevelAdjustment = QStyleHelper::dpiScaled(0.5);
797 const qreal bottomRightAdjustment = QStyleHelper::dpiScaled(-1.5);
798 rect.adjust(topLevelAdjustment, topLevelAdjustment,
799 bottomRightAdjustment, bottomRightAdjustment);
800 p->drawRect(rect);
801 p->setPen(oldPen);
802 break;
803 }
804 case PE_IndicatorCheckBox: {
805 QBrush fill;
806 if (opt->state & State_NoChange)
807 fill = QBrush(opt->palette.base().color(), Qt::Dense4Pattern);
808 else if (opt->state & State_Sunken)
809 fill = opt->palette.button();
810 else if (opt->state & State_Enabled)
811 fill = opt->palette.base();
812 else
813 fill = opt->palette.window();
814 p->save();
815 doRestore = true;
816 qDrawWinPanel(p, opt->rect, opt->palette, true, &fill);
817 if (opt->state & State_NoChange)
818 p->setPen(opt->palette.dark().color());
819 else
820 p->setPen(opt->palette.text().color());
821 }
822 Q_FALLTHROUGH();
823 case PE_IndicatorItemViewItemCheck:
824 if (!doRestore) {
825 p->save();
826 doRestore = true;
827 }
828#if QT_CONFIG(itemviews)
829 if (pe == PE_IndicatorItemViewItemCheck) {
830 const QStyleOptionViewItem *itemViewOpt = qstyleoption_cast<const QStyleOptionViewItem *>(opt);
831 p->setPen(itemViewOpt
832 && itemViewOpt->showDecorationSelected
833 && opt->state & State_Selected
834 ? opt->palette.highlightedText().color()
835 : opt->palette.text().color());
836 if (opt->state & State_NoChange)
837 p->setBrush(opt->palette.brush(QPalette::Button));
838 p->drawRect(opt->rect.x() + 1, opt->rect.y() + 1, opt->rect.width() - 2, opt->rect.height() - 2);
839 }
840#endif // QT_CONFIG(itemviews)
841 if (!(opt->state & State_Off)) {
842 QPointF points[6];
843 qreal scaleh = opt->rect.width() / 12.0;
844 qreal scalev = opt->rect.height() / 12.0;
845 points[0] = { opt->rect.x() + 3.5 * scaleh, opt->rect.y() + 5.5 * scalev };
846 points[1] = { points[0].x(), points[0].y() + 2 * scalev };
847 points[2] = { points[1].x() + 2 * scaleh, points[1].y() + 2 * scalev };
848 points[3] = { points[2].x() + 4 * scaleh, points[2].y() - 4 * scalev };
849 points[4] = { points[3].x(), points[3].y() - 2 * scalev };
850 points[5] = { points[4].x() - 4 * scaleh, points[4].y() + 4 * scalev };
851 p->setPen(QPen(opt->palette.text().color(), 0));
852 p->setBrush(opt->palette.text().color());
853 p->drawPolygon(points, 6);
854 }
855 if (doRestore)
856 p->restore();
857 break;
858 case PE_FrameFocusRect:
859 if (const QStyleOptionFocusRect *fropt = qstyleoption_cast<const QStyleOptionFocusRect *>(opt)) {
860 //### check for d->alt_down
861 if (!(fropt->state & State_KeyboardFocusChange) && !proxy()->styleHint(SH_UnderlineShortcut, opt))
862 return;
863 QRect r = opt->rect;
864 p->save();
865 p->setBackgroundMode(Qt::TransparentMode);
866 QColor bg_col = fropt->backgroundColor;
867 if (!bg_col.isValid())
868 bg_col = p->background().color();
869 // Create an "XOR" color.
870 QColor patternCol((bg_col.red() ^ 0xff) & 0xff,
871 (bg_col.green() ^ 0xff) & 0xff,
872 (bg_col.blue() ^ 0xff) & 0xff);
873 p->setBrush(QBrush(patternCol, Qt::Dense4Pattern));
874 p->setBrushOrigin(r.topLeft());
875 p->setPen(Qt::NoPen);
876 p->drawRect(r.left(), r.top(), r.width(), 1); // Top
877 p->drawRect(r.left(), r.bottom(), r.width(), 1); // Bottom
878 p->drawRect(r.left(), r.top(), 1, r.height()); // Left
879 p->drawRect(r.right(), r.top(), 1, r.height()); // Right
880 p->restore();
881 }
882 break;
883 case PE_IndicatorRadioButton:
884 {
885 QRect r = opt->rect;
886 p->save();
887 p->setRenderHint(QPainter::Antialiasing, true);
888
889 QPointF circleCenter = r.center() + QPoint(1, 1);
890 qreal radius = (r.width() + (r.width() + 1) % 2) / 2.0 - 1;
891
892 QPainterPath path1;
893 path1.addEllipse(circleCenter, radius, radius);
894 radius *= 0.85;
895 QPainterPath path2;
896 path2.addEllipse(circleCenter, radius, radius);
897 radius *= 0.85;
898 QPainterPath path3;
899 path3.addEllipse(circleCenter, radius, radius);
900 radius *= 0.5;
901 QPainterPath path4;
902 path4.addEllipse(circleCenter, radius, radius);
903
904 QPolygon topLeftPol, bottomRightPol;
905 topLeftPol.setPoints(3, r.x(), r.y(), r.x(), r.y() + r.height(), r.x() + r.width(), r.y());
906 bottomRightPol.setPoints(3, r.x(), r.y() + r.height(), r.x() + r.width(), r.y() + r.height(), r.x() + r.width(), r.y());
907
908 p->setClipRegion(QRegion(topLeftPol));
909 p->setPen(opt->palette.dark().color());
910 p->setBrush(opt->palette.dark().color());
911 p->drawPath(path1);
912 p->setPen(opt->palette.shadow().color());
913 p->setBrush(opt->palette.shadow().color());
914 p->drawPath(path2);
915
916 p->setClipRegion(QRegion(bottomRightPol));
917 p->setPen(opt->palette.light().color());
918 p->setBrush(opt->palette.light().color());
919 p->drawPath(path1);
920 p->setPen(opt->palette.midlight().color());
921 p->setBrush(opt->palette.midlight().color());
922 p->drawPath(path2);
923
924 QColor fillColor = ((opt->state & State_Sunken) || !(opt->state & State_Enabled)) ?
925 opt->palette.button().color() : opt->palette.base().color();
926
927 p->setClipping(false);
928 p->setPen(fillColor);
929 p->setBrush(fillColor);
930 p->drawPath(path3);
931
932 if (opt->state & State_On) {
933 p->setPen(opt->palette.text().color());
934 p->setBrush(opt->palette.text());
935 p->drawPath(path4);
936 }
937 p->restore();
938 break;
939 }
940#ifndef QT_NO_FRAME
941 case PE_Frame:
942 case PE_FrameMenu:
943 if (const QStyleOptionFrame *frame = qstyleoption_cast<const QStyleOptionFrame *>(opt)) {
944 if (frame->lineWidth == 2 || pe == PE_Frame) {
945 QPalette popupPal = frame->palette;
946 if (pe == PE_FrameMenu) {
947 popupPal.setColor(QPalette::Light, frame->palette.window().color());
948 popupPal.setColor(QPalette::Midlight, frame->palette.light().color());
949 }
950 if (pe == PE_Frame && (frame->state & State_Raised))
951 qDrawWinButton(p, frame->rect, popupPal, frame->state & State_Sunken);
952 else if (pe == PE_Frame && (frame->state & State_Sunken))
953 {
954 popupPal.setColor(QPalette::Midlight, frame->palette.window().color());
955 qDrawWinPanel(p, frame->rect, popupPal, frame->state & State_Sunken);
956 }
957 else
958 qDrawWinPanel(p, frame->rect, popupPal, frame->state & State_Sunken);
959 } else {
960 QCommonStyle::drawPrimitive(pe, opt, p, w);
961 }
962 } else {
963 QPalette popupPal = opt->palette;
964 popupPal.setColor(QPalette::Light, opt->palette.window().color());
965 popupPal.setColor(QPalette::Midlight, opt->palette.light().color());
966 qDrawWinPanel(p, opt->rect, popupPal, opt->state & State_Sunken);
967 }
968 break;
969#endif // QT_NO_FRAME
970 case PE_FrameButtonBevel:
971 case PE_PanelButtonBevel: {
972 QBrush fill;
973 bool panel = pe != PE_FrameButtonBevel;
974 p->setBrushOrigin(opt->rect.topLeft());
975 if (!(opt->state & State_Sunken) && (opt->state & State_On))
976 fill = QBrush(opt->palette.light().color(), Qt::Dense4Pattern);
977 else
978 fill = opt->palette.brush(QPalette::Button);
979
980 if (opt->state & (State_Raised | State_On | State_Sunken)) {
981 qDrawWinButton(p, opt->rect, opt->palette, opt->state & (State_Sunken | State_On),
982 panel ? &fill : 0);
983 } else {
984 if (panel)
985 p->fillRect(opt->rect, fill);
986 else
987 p->drawRect(opt->rect);
988 }
989 break; }
990 case PE_FrameWindow: {
991 QPalette popupPal = opt->palette;
992 popupPal.setColor(QPalette::Light, opt->palette.window().color());
993 popupPal.setColor(QPalette::Midlight, opt->palette.light().color());
994 qDrawWinPanel(p, opt->rect, popupPal, opt->state & State_Sunken);
995 break; }
996#if QT_CONFIG(dockwidget)
997 case PE_IndicatorDockWidgetResizeHandle:
998 break;
999 case PE_FrameDockWidget:
1000 if (qstyleoption_cast<const QStyleOptionFrame *>(opt)) {
1001 proxy()->drawPrimitive(QStyle::PE_FrameWindow, opt, p, w);
1002 }
1003 break;
1004#endif // QT_CONFIG(dockwidget)
1005
1006 case PE_FrameStatusBarItem:
1007 qDrawShadePanel(p, opt->rect, opt->palette, true, 1, 0);
1008 break;
1009
1010 case PE_IndicatorProgressChunk:
1011 {
1012 bool vertical = false, inverted = false;
1013 if (const QStyleOptionProgressBar *pb = qstyleoption_cast<const QStyleOptionProgressBar *>(opt)) {
1014 vertical = pb->orientation == Qt::Vertical;
1015 inverted = pb->invertedAppearance;
1016 }
1017
1018 int space = 2;
1019 int chunksize = proxy()->pixelMetric(PM_ProgressBarChunkWidth, opt, w) - space;
1020 if (!vertical) {
1021 if (opt->rect.width() <= chunksize)
1022 space = 0;
1023
1024 if (inverted)
1025 p->fillRect(opt->rect.x() + space, opt->rect.y(), opt->rect.width() - space, opt->rect.height(),
1026 opt->palette.brush(QPalette::Highlight));
1027 else
1028 p->fillRect(opt->rect.x(), opt->rect.y(), opt->rect.width() - space, opt->rect.height(),
1029 opt->palette.brush(QPalette::Highlight));
1030 } else {
1031 if (opt->rect.height() <= chunksize)
1032 space = 0;
1033
1034 if (inverted)
1035 p->fillRect(opt->rect.x(), opt->rect.y(), opt->rect.width(), opt->rect.height() - space,
1036 opt->palette.brush(QPalette::Highlight));
1037 else
1038 p->fillRect(opt->rect.x(), opt->rect.y() + space, opt->rect.width(), opt->rect.height() - space,
1039 opt->palette.brush(QPalette::Highlight));
1040 }
1041 }
1042 break;
1043
1044 case PE_FrameTabWidget: {
1045 qDrawWinButton(p, opt->rect, opt->palette, false, 0);
1046 break;
1047 }
1048 default:
1049 QCommonStyle::drawPrimitive(pe, opt, p, w);
1050 }
1051}
1052
1053/*! \reimp */
1054void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter *p,
1055 const QWidget *widget) const
1056{
1057 switch (ce) {
1058#if QT_CONFIG(rubberband)
1059 case CE_RubberBand:
1060 if (qstyleoption_cast<const QStyleOptionRubberBand *>(opt)) {
1061 // ### workaround for slow general painter path
1062 QPixmap tiledPixmap(16, 16);
1063 QPainter pixmapPainter(&tiledPixmap);
1064 pixmapPainter.setPen(Qt::NoPen);
1065 pixmapPainter.setBrush(Qt::Dense4Pattern);
1066 pixmapPainter.setBackground(Qt::white);
1067 pixmapPainter.setBackgroundMode(Qt::OpaqueMode);
1068 pixmapPainter.drawRect(0, 0, tiledPixmap.width(), tiledPixmap.height());
1069 pixmapPainter.end();
1070 tiledPixmap = QPixmap::fromImage(tiledPixmap.toImage());
1071 p->save();
1072 QRect r = opt->rect;
1073 QStyleHintReturnMask mask;
1074 if (proxy()->styleHint(QStyle::SH_RubberBand_Mask, opt, widget, &mask))
1075 p->setClipRegion(mask.region);
1076 p->drawTiledPixmap(r.x(), r.y(), r.width(), r.height(), tiledPixmap);
1077 p->restore();
1078 return;
1079 }
1080 break;
1081#endif // QT_CONFIG(rubberband)
1082
1083#if QT_CONFIG(menu) && QT_CONFIG(mainwindow)
1084 case CE_MenuBarEmptyArea:
1085 if (widget && qobject_cast<const QMainWindow *>(widget->parentWidget())) {
1086 p->fillRect(opt->rect, opt->palette.button());
1087 QPen oldPen = p->pen();
1088 p->setPen(QPen(opt->palette.dark().color()));
1089 p->drawLine(opt->rect.bottomLeft(), opt->rect.bottomRight());
1090 p->setPen(oldPen);
1091 }
1092 break;
1093#endif
1094#if QT_CONFIG(menu)
1095 case CE_MenuItem:
1096 if (const QStyleOptionMenuItem *menuitem = qstyleoption_cast<const QStyleOptionMenuItem *>(opt)) {
1097 int x, y, w, h;
1098 menuitem->rect.getRect(&x, &y, &w, &h);
1099 int tab = menuitem->tabWidth;
1100 bool dis = !(menuitem->state & State_Enabled);
1101 bool checked = menuitem->checkType != QStyleOptionMenuItem::NotCheckable
1102 ? menuitem->checked : false;
1103 bool act = menuitem->state & State_Selected;
1104
1105 // windows always has a check column, regardless whether we have an icon or not
1106 int checkcol = qMax<int>(menuitem->maxIconWidth, QWindowsStylePrivate::windowsCheckMarkWidth);
1107
1108 QBrush fill = menuitem->palette.brush(act ? QPalette::Highlight : QPalette::Button);
1109 p->fillRect(menuitem->rect.adjusted(0, 0, -1, 0), fill);
1110
1111 if (menuitem->menuItemType == QStyleOptionMenuItem::Separator){
1112 int yoff = y-1 + h / 2;
1113 p->setPen(menuitem->palette.dark().color());
1114 p->drawLine(x + 2, yoff, x + w - 4, yoff);
1115 p->setPen(menuitem->palette.light().color());
1116 p->drawLine(x + 2, yoff + 1, x + w - 4, yoff + 1);
1117 return;
1118 }
1119
1120 QRect vCheckRect = visualRect(opt->direction, menuitem->rect, QRect(menuitem->rect.x(), menuitem->rect.y(), checkcol, menuitem->rect.height()));
1121 if (!menuitem->icon.isNull() && checked) {
1122 if (act) {
1123 qDrawShadePanel(p, vCheckRect,
1124 menuitem->palette, true, 1,
1125 &menuitem->palette.brush(QPalette::Button));
1126 } else {
1127 QBrush fill(menuitem->palette.light().color(), Qt::Dense4Pattern);
1128 qDrawShadePanel(p, vCheckRect, menuitem->palette, true, 1, &fill);
1129 }
1130 } else if (!act) {
1131 p->fillRect(vCheckRect, menuitem->palette.brush(QPalette::Button));
1132 }
1133
1134 // On Windows Style, if we have a checkable item and an icon we
1135 // draw the icon recessed to indicate an item is checked. If we
1136 // have no icon, we draw a checkmark instead.
1137 if (!menuitem->icon.isNull()) {
1138 QIcon::Mode mode = dis ? QIcon::Disabled : QIcon::Normal;
1139 if (act && !dis)
1140 mode = QIcon::Active;
1141 QPixmap pixmap;
1142 if (checked)
1143 pixmap = menuitem->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize, opt, widget), mode, QIcon::On);
1144 else
1145 pixmap = menuitem->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize, opt, widget), mode);
1146 const int pixw = pixmap.width() / pixmap.devicePixelRatio();
1147 const int pixh = pixmap.height() / pixmap.devicePixelRatio();
1148 QRect pmr(0, 0, pixw, pixh);
1149 pmr.moveCenter(vCheckRect.center());
1150 p->setPen(menuitem->palette.text().color());
1151 p->drawPixmap(pmr.topLeft(), pixmap);
1152 } else if (checked) {
1153 QStyleOptionMenuItem newMi = *menuitem;
1154 newMi.state = State_None;
1155 if (!dis)
1156 newMi.state |= State_Enabled;
1157 if (act)
1158 newMi.state |= State_On;
1159 newMi.rect = visualRect(opt->direction, menuitem->rect, QRect(menuitem->rect.x() + QWindowsStylePrivate::windowsItemFrame,
1160 menuitem->rect.y() + QWindowsStylePrivate::windowsItemFrame,
1161 checkcol - 2 * QWindowsStylePrivate::windowsItemFrame,
1162 menuitem->rect.height() - 2 * QWindowsStylePrivate::windowsItemFrame));
1163 proxy()->drawPrimitive(PE_IndicatorMenuCheckMark, &newMi, p, widget);
1164 }
1165 p->setPen(act ? menuitem->palette.highlightedText().color() : menuitem->palette.buttonText().color());
1166
1167 QColor discol;
1168 if (dis) {
1169 discol = menuitem->palette.text().color();
1170 p->setPen(discol);
1171 }
1172
1173 int xm = int(QWindowsStylePrivate::windowsItemFrame) + checkcol + int(QWindowsStylePrivate::windowsItemHMargin);
1174 int xpos = menuitem->rect.x() + xm;
1175 QRect textRect(xpos, y + QWindowsStylePrivate::windowsItemVMargin,
1176 w - xm - QWindowsStylePrivate::windowsRightBorder - tab + 1, h - 2 * QWindowsStylePrivate::windowsItemVMargin);
1177 QRect vTextRect = visualRect(opt->direction, menuitem->rect, textRect);
1178 QStringRef s(&menuitem->text);
1179 if (!s.isEmpty()) { // draw text
1180 p->save();
1181 int t = s.indexOf(QLatin1Char('\t'));
1182 int text_flags = Qt::AlignVCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine;
1183 if (!proxy()->styleHint(SH_UnderlineShortcut, menuitem, widget))
1184 text_flags |= Qt::TextHideMnemonic;
1185 text_flags |= Qt::AlignLeft;
1186 if (t >= 0) {
1187 QRect vShortcutRect = visualRect(opt->direction, menuitem->rect,
1188 QRect(textRect.topRight(), QPoint(menuitem->rect.right(), textRect.bottom())));
1189 const QString textToDraw = s.mid(t + 1).toString();
1190 if (dis && !act && proxy()->styleHint(SH_EtchDisabledText, opt, widget)) {
1191 p->setPen(menuitem->palette.light().color());
1192 p->drawText(vShortcutRect.adjusted(1, 1, 1, 1), text_flags, textToDraw);
1193 p->setPen(discol);
1194 }
1195 p->drawText(vShortcutRect, text_flags, textToDraw);
1196 s = s.left(t);
1197 }
1198 QFont font = menuitem->font;
1199 if (menuitem->menuItemType == QStyleOptionMenuItem::DefaultItem)
1200 font.setBold(true);
1201 p->setFont(font);
1202 const QString textToDraw = s.left(t).toString();
1203 if (dis && !act && proxy()->styleHint(SH_EtchDisabledText, opt, widget)) {
1204 p->setPen(menuitem->palette.light().color());
1205 p->drawText(vTextRect.adjusted(1, 1, 1, 1), text_flags, textToDraw);
1206 p->setPen(discol);
1207 }
1208 p->drawText(vTextRect, text_flags, textToDraw);
1209 p->restore();
1210 }
1211 if (menuitem->menuItemType == QStyleOptionMenuItem::SubMenu) {// draw sub menu arrow
1212 int dim = (h - 2 * QWindowsStylePrivate::windowsItemFrame) / 2;
1213 PrimitiveElement arrow;
1214 arrow = (opt->direction == Qt::RightToLeft) ? PE_IndicatorArrowLeft : PE_IndicatorArrowRight;
1215 xpos = x + w - QWindowsStylePrivate::windowsArrowHMargin - QWindowsStylePrivate::windowsItemFrame - dim;
1216 QRect vSubMenuRect = visualRect(opt->direction, menuitem->rect, QRect(xpos, y + h / 2 - dim / 2, dim, dim));
1217 QStyleOptionMenuItem newMI = *menuitem;
1218 newMI.rect = vSubMenuRect;
1219 newMI.state = dis ? State_None : State_Enabled;
1220 if (act)
1221 newMI.palette.setColor(QPalette::ButtonText,
1222 newMI.palette.highlightedText().color());
1223 proxy()->drawPrimitive(arrow, &newMI, p, widget);
1224 }
1225
1226 }
1227 break;
1228#endif // QT_CONFIG(menu)
1229#if QT_CONFIG(menubar)
1230 case CE_MenuBarItem:
1231 if (const QStyleOptionMenuItem *mbi = qstyleoption_cast<const QStyleOptionMenuItem *>(opt)) {
1232 bool active = mbi->state & State_Selected;
1233 bool hasFocus = mbi->state & State_HasFocus;
1234 bool down = mbi->state & State_Sunken;
1235 QStyleOptionMenuItem newMbi = *mbi;
1236 p->fillRect(mbi->rect, mbi->palette.brush(QPalette::Button));
1237 if (active || hasFocus) {
1238 QBrush b = mbi->palette.brush(QPalette::Button);
1239 if (active && down)
1240 p->setBrushOrigin(p->brushOrigin() + QPoint(1, 1));
1241 if (active && hasFocus)
1242 qDrawShadeRect(p, mbi->rect.x(), mbi->rect.y(), mbi->rect.width(),
1243 mbi->rect.height(), mbi->palette, active && down, 1, 0, &b);
1244 if (active && down) {
1245 newMbi.rect.translate(proxy()->pixelMetric(PM_ButtonShiftHorizontal, mbi, widget),
1246 proxy()->pixelMetric(PM_ButtonShiftVertical, mbi, widget));
1247 p->setBrushOrigin(p->brushOrigin() - QPoint(1, 1));
1248 }
1249 }
1250 QCommonStyle::drawControl(ce, &newMbi, p, widget);
1251 }
1252 break;
1253#endif // QT_CONFIG(menubar)
1254#if QT_CONFIG(tabbar)
1255 case CE_TabBarTabShape:
1256 if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(opt)) {
1257 bool rtlHorTabs = (tab->direction == Qt::RightToLeft
1258 && (tab->shape == QTabBar::RoundedNorth
1259 || tab->shape == QTabBar::RoundedSouth));
1260 bool selected = tab->state & State_Selected;
1261 bool lastTab = ((!rtlHorTabs && tab->position == QStyleOptionTab::End)
1262 || (rtlHorTabs
1263 && tab->position == QStyleOptionTab::Beginning));
1264 bool firstTab = ((!rtlHorTabs
1265 && tab->position == QStyleOptionTab::Beginning)
1266 || (rtlHorTabs
1267 && tab->position == QStyleOptionTab::End));
1268 bool onlyOne = tab->position == QStyleOptionTab::OnlyOneTab;
1269 bool previousSelected =
1270 ((!rtlHorTabs
1271 && tab->selectedPosition == QStyleOptionTab::PreviousIsSelected)
1272 || (rtlHorTabs
1273 && tab->selectedPosition == QStyleOptionTab::NextIsSelected));
1274 bool nextSelected =
1275 ((!rtlHorTabs
1276 && tab->selectedPosition == QStyleOptionTab::NextIsSelected)
1277 || (rtlHorTabs
1278 && tab->selectedPosition
1279 == QStyleOptionTab::PreviousIsSelected));
1280 int tabBarAlignment = proxy()->styleHint(SH_TabBar_Alignment, tab, widget);
1281 bool leftAligned = (!rtlHorTabs && tabBarAlignment == Qt::AlignLeft)
1282 || (rtlHorTabs
1283 && tabBarAlignment == Qt::AlignRight);
1284
1285 bool rightAligned = (!rtlHorTabs && tabBarAlignment == Qt::AlignRight)
1286 || (rtlHorTabs
1287 && tabBarAlignment == Qt::AlignLeft);
1288
1289 QColor light = tab->palette.light().color();
1290 QColor dark = tab->palette.dark().color();
1291 QColor shadow = tab->palette.shadow().color();
1292 int borderThinkness = proxy()->pixelMetric(PM_TabBarBaseOverlap, tab, widget);
1293 if (selected)
1294 borderThinkness /= 2;
1295 QRect r2(opt->rect);
1296 int x1 = r2.left();
1297 int x2 = r2.right();
1298 int y1 = r2.top();
1299 int y2 = r2.bottom();
1300 switch (tab->shape) {
1301 default:
1302 QCommonStyle::drawControl(ce, tab, p, widget);
1303 break;
1304 case QTabBar::RoundedNorth: {
1305 if (!selected) {
1306 y1 += 2;
1307 x1 += onlyOne || firstTab ? borderThinkness : 0;
1308 x2 -= onlyOne || lastTab ? borderThinkness : 0;
1309 }
1310
1311 p->fillRect(QRect(x1 + 1, y1 + 1, (x2 - x1) - 1, (y2 - y1) - 2), tab->palette.window());
1312
1313 // Delete border
1314 if (selected) {
1315 p->fillRect(QRect(x1,y2-1,x2-x1,1), tab->palette.window());
1316 p->fillRect(QRect(x1,y2,x2-x1,1), tab->palette.window());
1317 }
1318 // Left
1319 if (firstTab || selected || onlyOne || !previousSelected) {
1320 p->setPen(light);
1321 p->drawLine(x1, y1 + 2, x1, y2 - ((onlyOne || firstTab) && selected && leftAligned ? 0 : borderThinkness));
1322 p->drawPoint(x1 + 1, y1 + 1);
1323 }
1324 // Top
1325 {
1326 int beg = x1 + (previousSelected ? 0 : 2);
1327 int end = x2 - (nextSelected ? 0 : 2);
1328 p->setPen(light);
1329 p->drawLine(beg, y1, end, y1);
1330 }
1331 // Right
1332 if (lastTab || selected || onlyOne || !nextSelected) {
1333 p->setPen(shadow);
1334 p->drawLine(x2, y1 + 2, x2, y2 - ((onlyOne || lastTab) && selected && rightAligned ? 0 : borderThinkness));
1335 p->drawPoint(x2 - 1, y1 + 1);
1336 p->setPen(dark);
1337 p->drawLine(x2 - 1, y1 + 2, x2 - 1, y2 - ((onlyOne || lastTab) && selected && rightAligned ? 0 : borderThinkness));
1338 }
1339 break; }
1340 case QTabBar::RoundedSouth: {
1341 if (!selected) {
1342 y2 -= 2;
1343 x1 += firstTab ? borderThinkness : 0;
1344 x2 -= lastTab ? borderThinkness : 0;
1345 }
1346
1347 p->fillRect(QRect(x1 + 1, y1 + 2, (x2 - x1) - 1, (y2 - y1) - 1), tab->palette.window());
1348
1349 // Delete border
1350 if (selected) {
1351 p->fillRect(QRect(x1, y1 + 1, (x2 - 1)-x1, 1), tab->palette.window());
1352 p->fillRect(QRect(x1, y1, (x2 - 1)-x1, 1), tab->palette.window());
1353 }
1354 // Left
1355 if (firstTab || selected || onlyOne || !previousSelected) {
1356 p->setPen(light);
1357 p->drawLine(x1, y2 - 2, x1, y1 + ((onlyOne || firstTab) && selected && leftAligned ? 0 : borderThinkness));
1358 p->drawPoint(x1 + 1, y2 - 1);
1359 }
1360 // Bottom
1361 {
1362 int beg = x1 + (previousSelected ? 0 : 2);
1363 int end = x2 - (nextSelected ? 0 : 2);
1364 p->setPen(shadow);
1365 p->drawLine(beg, y2, end, y2);
1366 p->setPen(dark);
1367 p->drawLine(beg, y2 - 1, end, y2 - 1);
1368 }
1369 // Right
1370 if (lastTab || selected || onlyOne || !nextSelected) {
1371 p->setPen(shadow);
1372 p->drawLine(x2, y2 - 2, x2, y1 + ((onlyOne || lastTab) && selected && rightAligned ? 0 : borderThinkness));
1373 p->drawPoint(x2 - 1, y2 - 1);
1374 p->setPen(dark);
1375 p->drawLine(x2 - 1, y2 - 2, x2 - 1, y1 + ((onlyOne || lastTab) && selected && rightAligned ? 0 : borderThinkness));
1376 }
1377 break; }
1378 case QTabBar::RoundedWest: {
1379 if (!selected) {
1380 x1 += 2;
1381 y1 += firstTab ? borderThinkness : 0;
1382 y2 -= lastTab ? borderThinkness : 0;
1383 }
1384
1385 p->fillRect(QRect(x1 + 1, y1 + 1, (x2 - x1) - 2, (y2 - y1) - 1), tab->palette.window());
1386
1387 // Delete border
1388 if (selected) {
1389 p->fillRect(QRect(x2 - 1, y1, 1, y2-y1), tab->palette.window());
1390 p->fillRect(QRect(x2, y1, 1, y2-y1), tab->palette.window());
1391 }
1392 // Top
1393 if (firstTab || selected || onlyOne || !previousSelected) {
1394 p->setPen(light);
1395 p->drawLine(x1 + 2, y1, x2 - ((onlyOne || firstTab) && selected && leftAligned ? 0 : borderThinkness), y1);
1396 p->drawPoint(x1 + 1, y1 + 1);
1397 }
1398 // Left
1399 {
1400 int beg = y1 + (previousSelected ? 0 : 2);
1401 int end = y2 - (nextSelected ? 0 : 2);
1402 p->setPen(light);
1403 p->drawLine(x1, beg, x1, end);
1404 }
1405 // Bottom
1406 if (lastTab || selected || onlyOne || !nextSelected) {
1407 p->setPen(shadow);
1408 p->drawLine(x1 + 3, y2, x2 - ((onlyOne || lastTab) && selected && rightAligned ? 0 : borderThinkness), y2);
1409 p->drawPoint(x1 + 2, y2 - 1);
1410 p->setPen(dark);
1411 p->drawLine(x1 + 3, y2 - 1, x2 - ((onlyOne || lastTab) && selected && rightAligned ? 0 : borderThinkness), y2 - 1);
1412 p->drawPoint(x1 + 1, y2 - 1);
1413 p->drawPoint(x1 + 2, y2);
1414 }
1415 break; }
1416 case QTabBar::RoundedEast: {
1417 if (!selected) {
1418 x2 -= 2;
1419 y1 += firstTab ? borderThinkness : 0;
1420 y2 -= lastTab ? borderThinkness : 0;
1421 }
1422
1423 p->fillRect(QRect(x1 + 2, y1 + 1, (x2 - x1) - 1, (y2 - y1) - 1), tab->palette.window());
1424
1425 // Delete border
1426 if (selected) {
1427 p->fillRect(QRect(x1 + 1, y1, 1, (y2 - 1)-y1),tab->palette.window());
1428 p->fillRect(QRect(x1, y1, 1, (y2-1)-y1), tab->palette.window());
1429 }
1430 // Top
1431 if (firstTab || selected || onlyOne || !previousSelected) {
1432 p->setPen(light);
1433 p->drawLine(x2 - 2, y1, x1 + ((onlyOne || firstTab) && selected && leftAligned ? 0 : borderThinkness), y1);
1434 p->drawPoint(x2 - 1, y1 + 1);
1435 }
1436 // Right
1437 {
1438 int beg = y1 + (previousSelected ? 0 : 2);
1439 int end = y2 - (nextSelected ? 0 : 2);
1440 p->setPen(shadow);
1441 p->drawLine(x2, beg, x2, end);
1442 p->setPen(dark);
1443 p->drawLine(x2 - 1, beg, x2 - 1, end);
1444 }
1445 // Bottom
1446 if (lastTab || selected || onlyOne || !nextSelected) {
1447 p->setPen(shadow);
1448 p->drawLine(x2 - 2, y2, x1 + ((onlyOne || lastTab) && selected && rightAligned ? 0 : borderThinkness), y2);
1449 p->drawPoint(x2 - 1, y2 - 1);
1450 p->setPen(dark);
1451 p->drawLine(x2 - 2, y2 - 1, x1 + ((onlyOne || lastTab) && selected && rightAligned ? 0 : borderThinkness), y2 - 1);
1452 }
1453 break; }
1454 }
1455 }
1456 break;
1457#endif // QT_CONFIG(tabbar)
1458 case CE_ToolBoxTabShape:
1459 qDrawShadePanel(p, opt->rect, opt->palette,
1460 opt->state & (State_Sunken | State_On), 1,
1461 &opt->palette.brush(QPalette::Button));
1462 break;
1463#if QT_CONFIG(splitter)
1464 case CE_Splitter:
1465 p->eraseRect(opt->rect);
1466 break;
1467#endif // QT_CONFIG(splitter)
1468#if QT_CONFIG(scrollbar)
1469 case CE_ScrollBarSubLine:
1470 case CE_ScrollBarAddLine: {
1471 if ((opt->state & State_Sunken)) {
1472 p->setPen(opt->palette.dark().color());
1473 p->setBrush(opt->palette.brush(QPalette::Button));
1474 p->drawRect(opt->rect.adjusted(0, 0, -1, -1));
1475 } else {
1476 QStyleOption buttonOpt = *opt;
1477 if (!(buttonOpt.state & State_Sunken))
1478 buttonOpt.state |= State_Raised;
1479 QPalette pal(opt->palette);
1480 pal.setColor(QPalette::Button, opt->palette.light().color());
1481 pal.setColor(QPalette::Light, opt->palette.button().color());
1482 qDrawWinButton(p, opt->rect, pal, opt->state & (State_Sunken | State_On),
1483 &opt->palette.brush(QPalette::Button));
1484 }
1485 PrimitiveElement arrow;
1486 if (opt->state & State_Horizontal) {
1487 if (ce == CE_ScrollBarAddLine)
1488 arrow = opt->direction == Qt::LeftToRight ? PE_IndicatorArrowRight : PE_IndicatorArrowLeft;
1489 else
1490 arrow = opt->direction == Qt::LeftToRight ? PE_IndicatorArrowLeft : PE_IndicatorArrowRight;
1491 } else {
1492 if (ce == CE_ScrollBarAddLine)
1493 arrow = PE_IndicatorArrowDown;
1494 else
1495 arrow = PE_IndicatorArrowUp;
1496 }
1497 QStyleOption arrowOpt = *opt;
1498 arrowOpt.rect = opt->rect.adjusted(4, 4, -4, -4);
1499 proxy()->drawPrimitive(arrow, &arrowOpt, p, widget);
1500 break; }
1501 case CE_ScrollBarAddPage:
1502 case CE_ScrollBarSubPage: {
1503 QBrush br;
1504 QBrush bg = p->background();
1505 Qt::BGMode bg_mode = p->backgroundMode();
1506 p->setPen(Qt::NoPen);
1507 p->setBackgroundMode(Qt::OpaqueMode);
1508
1509 if (opt->state & State_Sunken) {
1510 br = QBrush(opt->palette.shadow().color(), Qt::Dense4Pattern);
1511 p->setBackground(opt->palette.dark().color());
1512 p->setBrush(br);
1513 } else {
1514 const QBrush paletteBrush = opt->palette.brush(QPalette::Light);
1515 if (paletteBrush.style() == Qt::TexturePattern) {
1516 if (qHasPixmapTexture(paletteBrush))
1517 br = QBrush(paletteBrush.texture());
1518 else
1519 br = QBrush(paletteBrush.textureImage());
1520 } else
1521 br = QBrush(opt->palette.light().color(), Qt::Dense4Pattern);
1522 p->setBackground(opt->palette.window().color());
1523 p->setBrush(br);
1524 }
1525 p->drawRect(opt->rect);
1526 p->setBackground(bg);
1527 p->setBackgroundMode(bg_mode);
1528 break; }
1529 case CE_ScrollBarSlider:
1530 if (!(opt->state & State_Enabled)) {
1531 QBrush br;
1532 const QBrush paletteBrush = opt->palette.brush(QPalette::Light);
1533 if (paletteBrush.style() == Qt::TexturePattern) {
1534 if (qHasPixmapTexture(paletteBrush))
1535 br = QBrush(paletteBrush.texture());
1536 else
1537 br = QBrush(paletteBrush.textureImage());
1538 } else
1539 br = QBrush(opt->palette.light().color(), Qt::Dense4Pattern);
1540 p->setPen(Qt::NoPen);
1541 p->setBrush(br);
1542 p->setBackgroundMode(Qt::OpaqueMode);
1543 p->drawRect(opt->rect);
1544 } else {
1545 QStyleOptionButton buttonOpt;
1546 buttonOpt.QStyleOption::operator=(*opt);
1547 buttonOpt.state = State_Enabled | State_Raised;
1548
1549 QPalette pal(opt->palette);
1550 pal.setColor(QPalette::Button, opt->palette.light().color());
1551 pal.setColor(QPalette::Light, opt->palette.button().color());
1552 qDrawWinButton(p, opt->rect, pal, false, &opt->palette.brush(QPalette::Button));
1553 }
1554 break;
1555#endif // QT_CONFIG(scrollbar)
1556 case CE_HeaderSection: {
1557 QBrush fill;
1558 if (opt->state & State_On)
1559 fill = QBrush(opt->palette.light().color(), Qt::Dense4Pattern);
1560 else
1561 fill = opt->palette.brush(QPalette::Button);
1562
1563 if (opt->state & (State_Raised | State_Sunken)) {
1564 qDrawWinButton(p, opt->rect, opt->palette, opt->state & State_Sunken, &fill);
1565 } else {
1566 p->fillRect(opt->rect, fill);
1567 }
1568 break; }
1569#if QT_CONFIG(toolbar)
1570 case CE_ToolBar:
1571 if (const QStyleOptionToolBar *toolbar = qstyleoption_cast<const QStyleOptionToolBar *>(opt)) {
1572 // Reserve the beveled appearance only for mainwindow toolbars
1573 if (!(widget && qobject_cast<const QMainWindow*> (widget->parentWidget())))
1574 break;
1575
1576 QRect rect = opt->rect;
1577 bool paintLeftBorder = true;
1578 bool paintRightBorder = true;
1579 bool paintBottomBorder = true;
1580
1581 switch (toolbar->toolBarArea){
1582 case Qt::BottomToolBarArea :
1583 switch(toolbar->positionOfLine){
1584 case QStyleOptionToolBar::Beginning:
1585 case QStyleOptionToolBar::OnlyOne:
1586 paintBottomBorder = false;
1587 default:
1588 break;
1589 }
1590 Q_FALLTHROUGH(); // It continues in the end of the next case
1591 case Qt::TopToolBarArea :
1592 switch(toolbar->positionWithinLine){
1593 case QStyleOptionToolBar::Beginning:
1594 paintLeftBorder = false;
1595 break;
1596 case QStyleOptionToolBar::End:
1597 paintRightBorder = false;
1598 break;
1599 case QStyleOptionToolBar::OnlyOne:
1600 paintRightBorder = false;
1601 paintLeftBorder = false;
1602 default:
1603 break;
1604 }
1605 if(opt->direction == Qt::RightToLeft){ //reverse layout changes the order of Beginning/end
1606 bool tmp = paintLeftBorder;
1607 paintRightBorder=paintLeftBorder;
1608 paintLeftBorder=tmp;
1609 }
1610 break;
1611 case Qt::RightToolBarArea :
1612 switch (toolbar->positionOfLine){
1613 case QStyleOptionToolBar::Beginning:
1614 case QStyleOptionToolBar::OnlyOne:
1615 paintRightBorder = false;
1616 break;
1617 default:
1618 break;
1619 }
1620 break;
1621 case Qt::LeftToolBarArea :
1622 switch (toolbar->positionOfLine){
1623 case QStyleOptionToolBar::Beginning:
1624 case QStyleOptionToolBar::OnlyOne:
1625 paintLeftBorder = false;
1626 break;
1627 default:
1628 break;
1629 }
1630 break;
1631 default:
1632 break;
1633 }
1634
1635
1636 //draw top border
1637 p->setPen(QPen(opt->palette.light().color()));
1638 p->drawLine(rect.topLeft().x(),
1639 rect.topLeft().y(),
1640 rect.topRight().x(),
1641 rect.topRight().y());
1642
1643 if (paintLeftBorder){
1644 p->setPen(QPen(opt->palette.light().color()));
1645 p->drawLine(rect.topLeft().x(),
1646 rect.topLeft().y(),
1647 rect.bottomLeft().x(),
1648 rect.bottomLeft().y());
1649 }
1650
1651 if (paintRightBorder){
1652 p->setPen(QPen(opt->palette.dark().color()));
1653 p->drawLine(rect.topRight().x(),
1654 rect.topRight().y(),
1655 rect.bottomRight().x(),
1656 rect.bottomRight().y());
1657 }
1658
1659 if (paintBottomBorder){
1660 p->setPen(QPen(opt->palette.dark().color()));
1661 p->drawLine(rect.bottomLeft().x(),
1662 rect.bottomLeft().y(),
1663 rect.bottomRight().x(),
1664 rect.bottomRight().y());
1665 }
1666 }
1667 break;
1668
1669
1670#endif // QT_CONFIG(toolbar)
1671
1672 case CE_ProgressBarContents:
1673 if (const QStyleOptionProgressBar *pb = qstyleoption_cast<const QStyleOptionProgressBar *>(opt)) {
1674 QRect rect = pb->rect;
1675 if (!rect.isValid())
1676 return;
1677
1678 const bool vertical = pb->orientation == Qt::Vertical;
1679 const bool inverted = pb->invertedAppearance;
1680
1681 QMatrix m;
1682 if (vertical) {
1683 rect = QRect(rect.y(), rect.x(), rect.height(), rect.width()); // flip width and height
1684 m.rotate(90);
1685 m.translate(0, -(rect.height() + rect.y()*2));
1686 }
1687 QPalette pal2 = pb->palette;
1688 // Correct the highlight color if it is the same as the background
1689 if (pal2.highlight() == pal2.window())
1690 pal2.setColor(QPalette::Highlight, pb->palette.color(QPalette::Active,
1691 QPalette::Highlight));
1692 bool reverse = ((!vertical && (pb->direction == Qt::RightToLeft)) || vertical);
1693 if (inverted)
1694 reverse = !reverse;
1695 int w = rect.width();
1696 Q_D(const QWindowsStyle);
1697 if (pb->minimum == 0 && pb->maximum == 0) {
1698 const int unit_width = proxy()->pixelMetric(PM_ProgressBarChunkWidth, pb, widget);
1699 QStyleOptionProgressBar pbBits = *pb;
1700 Q_ASSERT(unit_width >0);
1701
1702 pbBits.rect = rect;
1703 pbBits.palette = pal2;
1704
1705 int step = 0;
1706 int chunkCount = w / unit_width + 1;
1707#if QT_CONFIG(animation)
1708 if (QProgressStyleAnimation *animation = qobject_cast<QProgressStyleAnimation*>(d->animation(opt->styleObject)))
1709 step = (animation->animationStep() / 3) % chunkCount;
1710 else
1711 d->startAnimation(new QProgressStyleAnimation(d->animationFps, opt->styleObject));
1712#else
1713 Q_UNUSED(d);
1714#endif
1715 int chunksInRow = 5;
1716 int myY = pbBits.rect.y();
1717 int myHeight = pbBits.rect.height();
1718 int chunksToDraw = chunksInRow;
1719
1720 if(step > chunkCount - 5)chunksToDraw = (chunkCount - step);
1721 p->save();
1722 p->setClipRect(m.mapRect(QRectF(rect)).toRect());
1723
1724 int x0 = reverse ? rect.left() + rect.width() - unit_width*(step) - unit_width : rect.left() + unit_width * step;
1725 int x = 0;
1726
1727 for (int i = 0; i < chunksToDraw ; ++i) {
1728 pbBits.rect.setRect(x0 + x, myY, unit_width, myHeight);
1729 pbBits.rect = m.mapRect(QRectF(pbBits.rect)).toRect();
1730 proxy()->drawPrimitive(PE_IndicatorProgressChunk, &pbBits, p, widget);
1731 x += reverse ? -unit_width : unit_width;
1732 }
1733 //Draw wrap-around chunks
1734 if( step > chunkCount-5){
1735 x0 = reverse ? rect.left() + rect.width() - unit_width : rect.left() ;
1736 x = 0;
1737 int chunksToDraw = step - (chunkCount - chunksInRow);
1738 for (int i = 0; i < chunksToDraw ; ++i) {
1739 pbBits.rect.setRect(x0 + x, myY, unit_width, myHeight);
1740 pbBits.rect = m.mapRect(QRectF(pbBits.rect)).toRect();
1741 proxy()->drawPrimitive(PE_IndicatorProgressChunk, &pbBits, p, widget);
1742 x += reverse ? -unit_width : unit_width;
1743 }
1744 }
1745 p->restore(); //restore state
1746 }
1747 else {
1748#if QT_CONFIG(animation)
1749 d->stopAnimation(opt->styleObject);
1750#endif
1751 QCommonStyle::drawControl(ce, opt, p, widget);
1752 }
1753 }
1754 break;
1755
1756#if QT_CONFIG(dockwidget)
1757 case CE_DockWidgetTitle:
1758
1759 if (const QStyleOptionDockWidget *dwOpt = qstyleoption_cast<const QStyleOptionDockWidget *>(opt)) {
1760 Q_D(const QWindowsStyle);
1761
1762 const bool verticalTitleBar = dwOpt->verticalTitleBar;
1763
1764 QRect rect = dwOpt->rect;
1765 QRect r = rect;
1766
1767 if (verticalTitleBar) {
1768 r = r.transposed();
1769
1770 p->save();
1771 p->translate(r.left(), r.top() + r.width());
1772 p->rotate(-90);
1773 p->translate(-r.left(), -r.top());
1774 }
1775
1776 bool floating = false;
1777 bool active = dwOpt->state & State_Active;
1778 QColor inactiveCaptionTextColor = d->inactiveCaptionText;
1779 if (dwOpt->movable) {
1780 QColor left, right;
1781
1782 //Titlebar gradient
1783 if (opt->state & QStyle::State_Window) {
1784 floating = true;
1785 if (active) {
1786 left = d->activeCaptionColor;
1787 right = d->activeGradientCaptionColor;
1788 } else {
1789 left = d->inactiveCaptionColor;
1790 right = d->inactiveGradientCaptionColor;
1791 }
1792 QBrush fillBrush(left);
1793 if (left != right) {
1794 QPoint p1(r.x(), r.top() + r.height()/2);
1795 QPoint p2(rect.right(), r.top() + r.height()/2);
1796 QLinearGradient lg(p1, p2);
1797 lg.setColorAt(0, left);
1798 lg.setColorAt(1, right);
1799 fillBrush = lg;
1800 }
1801 p->fillRect(r.adjusted(0, 0, 0, -3), fillBrush);
1802 }
1803 }
1804 if (!dwOpt->title.isEmpty()) {
1805 QFont oldFont = p->font();
1806 if (floating) {
1807 QFont font = oldFont;
1808 font.setBold(true);
1809 p->setFont(font);
1810 }
1811 QPalette palette = dwOpt->palette;
1812 palette.setColor(QPalette::Window, inactiveCaptionTextColor);
1813 QRect titleRect = subElementRect(SE_DockWidgetTitleBarText, opt, widget);
1814 if (verticalTitleBar) {
1815 titleRect = QRect(r.left() + rect.bottom()
1816 - titleRect.bottom(),
1817 r.top() + titleRect.left() - rect.left(),
1818 titleRect.height(), titleRect.width());
1819 }
1820 proxy()->drawItemText(p, titleRect,
1821 Qt::AlignLeft | Qt::AlignVCenter, palette,
1822 dwOpt->state & State_Enabled, dwOpt->title,
1823 floating ? (active ? QPalette::BrightText : QPalette::Window) : QPalette::WindowText);
1824 p->setFont(oldFont);
1825 }
1826 if (verticalTitleBar)
1827 p->restore();
1828 }
1829 return;
1830#endif // QT_CONFIG(dockwidget)
1831#if QT_CONFIG(combobox)
1832 case CE_ComboBoxLabel:
1833 if (const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(opt)) {
1834 if (cb->state & State_HasFocus) {
1835 p->setPen(cb->palette.highlightedText().color());
1836 p->setBackground(cb->palette.highlight());
1837 } else {
1838 p->setPen(cb->palette.text().color());
1839 p->setBackground(cb->palette.window());
1840 }
1841 }
1842 QCommonStyle::drawControl(ce, opt, p, widget);
1843 break;
1844#endif // QT_CONFIG(combobox)
1845 default:
1846 QCommonStyle::drawControl(ce, opt, p, widget);
1847 }
1848}
1849
1850/*! \reimp */
1851QRect QWindowsStyle::subElementRect(SubElement sr, const QStyleOption *opt, const QWidget *w) const
1852{
1853 QRect r;
1854 switch (sr) {
1855 case SE_SliderFocusRect:
1856 case SE_ToolBoxTabContents:
1857 r = visualRect(opt->direction, opt->rect, opt->rect);
1858 break;
1859 case SE_DockWidgetTitleBarText: {
1860 r = QCommonStyle::subElementRect(sr, opt, w);
1861 const QStyleOptionDockWidget *dwOpt
1862 = qstyleoption_cast<const QStyleOptionDockWidget*>(opt);
1863 const bool verticalTitleBar = dwOpt && dwOpt->verticalTitleBar;
1864 int m = proxy()->pixelMetric(PM_DockWidgetTitleMargin, opt, w);
1865 if (verticalTitleBar) {
1866 r.adjust(0, 0, 0, -m);
1867 } else {
1868 if (opt->direction == Qt::LeftToRight)
1869 r.adjust(m, 0, 0, 0);
1870 else
1871 r.adjust(0, 0, -m, 0);
1872 }
1873 break;
1874 }
1875 case SE_ProgressBarContents:
1876 r = QCommonStyle::subElementRect(SE_ProgressBarGroove, opt, w);
1877 r.adjust(3, 3, -3, -3);
1878 break;
1879 default:
1880 r = QCommonStyle::subElementRect(sr, opt, w);
1881 }
1882 return r;
1883}
1884
1885
1886/*! \reimp */
1887void QWindowsStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex *opt,
1888 QPainter *p, const QWidget *widget) const
1889{
1890 switch (cc) {
1891#if QT_CONFIG(slider)
1892 case CC_Slider:
1893 if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
1894 int thickness = proxy()->pixelMetric(PM_SliderControlThickness, slider, widget);
1895 int len = proxy()->pixelMetric(PM_SliderLength, slider, widget);
1896 int ticks = slider->tickPosition;
1897 QRect groove = proxy()->subControlRect(CC_Slider, slider, SC_SliderGroove, widget);
1898 QRect handle = proxy()->subControlRect(CC_Slider, slider, SC_SliderHandle, widget);
1899
1900 if ((slider->subControls & SC_SliderGroove) && groove.isValid()) {
1901 int mid = thickness / 2;
1902
1903 if (ticks & QSlider::TicksAbove)
1904 mid += len / 8;
1905 if (ticks & QSlider::TicksBelow)
1906 mid -= len / 8;
1907
1908 p->setPen(slider->palette.shadow().color());
1909 if (slider->orientation == Qt::Horizontal) {
1910 qDrawWinPanel(p, groove.x(), groove.y() + mid - 2,
1911 groove.width(), 4, slider->palette, true);
1912 p->drawLine(groove.x() + 1, groove.y() + mid - 1,
1913 groove.x() + groove.width() - 3, groove.y() + mid - 1);
1914 } else {
1915 qDrawWinPanel(p, groove.x() + mid - 2, groove.y(),
1916 4, groove.height(), slider->palette, true);
1917 p->drawLine(groove.x() + mid - 1, groove.y() + 1,
1918 groove.x() + mid - 1, groove.y() + groove.height() - 3);
1919 }
1920 }
1921
1922 if (slider->subControls & SC_SliderTickmarks) {
1923 QStyleOptionSlider tmpSlider = *slider;
1924 tmpSlider.subControls = SC_SliderTickmarks;
1925 QCommonStyle::drawComplexControl(cc, &tmpSlider, p, widget);
1926 }
1927
1928 if (slider->subControls & SC_SliderHandle) {
1929 // 4444440
1930 // 4333310
1931 // 4322210
1932 // 4322210
1933 // 4322210
1934 // 4322210
1935 // *43210*
1936 // **410**
1937 // ***0***
1938 const QColor c0 = slider->palette.shadow().color();
1939 const QColor c1 = slider->palette.dark().color();
1940 // const QColor c2 = g.button();
1941 const QColor c3 = slider->palette.midlight().color();
1942 const QColor c4 = slider->palette.light().color();
1943 QBrush handleBrush;
1944
1945 if (slider->state & State_Enabled) {
1946 handleBrush = slider->palette.color(QPalette::Button);
1947 } else {
1948 handleBrush = QBrush(slider->palette.color(QPalette::Button),
1949 Qt::Dense4Pattern);
1950 }
1951
1952
1953 int x = handle.x(), y = handle.y(),
1954 wi = handle.width(), he = handle.height();
1955
1956 int x1 = x;
1957 int x2 = x+wi-1;
1958 int y1 = y;
1959 int y2 = y+he-1;
1960
1961 Qt::Orientation orient = slider->orientation;
1962 bool tickAbove = slider->tickPosition == QSlider::TicksAbove;
1963 bool tickBelow = slider->tickPosition == QSlider::TicksBelow;
1964
1965 if (slider->state & State_HasFocus) {
1966 QStyleOptionFocusRect fropt;
1967 fropt.QStyleOption::operator=(*slider);
1968 fropt.rect = subElementRect(SE_SliderFocusRect, slider, widget);
1969 proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, p, widget);
1970 }
1971
1972 if ((tickAbove && tickBelow) || (!tickAbove && !tickBelow)) {
1973 Qt::BGMode oldMode = p->backgroundMode();
1974 p->setBackgroundMode(Qt::OpaqueMode);
1975 qDrawWinButton(p, QRect(x, y, wi, he), slider->palette, false,
1976 &handleBrush);
1977 p->setBackgroundMode(oldMode);
1978 return;
1979 }
1980
1981 QSliderDirection dir;
1982
1983 if (orient == Qt::Horizontal)
1984 if (tickAbove)
1985 dir = SlUp;
1986 else
1987 dir = SlDown;
1988 else
1989 if (tickAbove)
1990 dir = SlLeft;
1991 else
1992 dir = SlRight;
1993
1994 QPolygon a;
1995
1996 int d = 0;
1997 switch (dir) {
1998 case SlUp:
1999 y1 = y1 + wi/2;
2000 d = (wi + 1) / 2 - 1;
2001 a.setPoints(5, x1,y1, x1,y2, x2,y2, x2,y1, x1+d,y1-d);
2002 break;
2003 case SlDown:
2004 y2 = y2 - wi/2;
2005 d = (wi + 1) / 2 - 1;
2006 a.setPoints(5, x1,y1, x1,y2, x1+d,y2+d, x2,y2, x2,y1);
2007 break;
2008 case SlLeft:
2009 d = (he + 1) / 2 - 1;
2010 x1 = x1 + he/2;
2011 a.setPoints(5, x1,y1, x1-d,y1+d, x1,y2, x2,y2, x2,y1);
2012 break;
2013 case SlRight:
2014 d = (he + 1) / 2 - 1;
2015 x2 = x2 - he/2;
2016 a.setPoints(5, x1,y1, x1,y2, x2,y2, x2+d,y1+d, x2,y1);
2017 break;
2018 }
2019
2020 QBrush oldBrush = p->brush();
2021 bool oldQt4CompatiblePainting = p->testRenderHint(QPainter::Qt4CompatiblePainting);
2022 p->setPen(Qt::NoPen);
2023 p->setBrush(handleBrush);
2024 p->setRenderHint(QPainter::Qt4CompatiblePainting);
2025 Qt::BGMode oldMode = p->backgroundMode();
2026 p->setBackgroundMode(Qt::OpaqueMode);
2027 p->drawRect(x1, y1, x2-x1+1, y2-y1+1);
2028 p->drawPolygon(a);
2029 p->setBrush(oldBrush);
2030 p->setBackgroundMode(oldMode);
2031
2032 if (dir != SlUp) {
2033 p->setPen(c4);
2034 p->drawLine(x1, y1, x2, y1);
2035 p->setPen(c3);
2036 p->drawLine(x1, y1+1, x2, y1+1);
2037 }
2038 if (dir != SlLeft) {
2039 p->setPen(c3);
2040 p->drawLine(x1+1, y1+1, x1+1, y2);
2041 p->setPen(c4);
2042 p->drawLine(x1, y1, x1, y2);
2043 }
2044 if (dir != SlRight) {
2045 p->setPen(c0);
2046 p->drawLine(x2, y1, x2, y2);
2047 p->setPen(c1);
2048 p->drawLine(x2-1, y1+1, x2-1, y2-1);
2049 }
2050 if (dir != SlDown) {
2051 p->setPen(c0);
2052 p->drawLine(x1, y2, x2, y2);
2053 p->setPen(c1);
2054 p->drawLine(x1+1, y2-1, x2-1, y2-1);
2055 }
2056
2057 switch (dir) {
2058 case SlUp:
2059 p->setPen(c4);
2060 p->drawLine(x1, y1, x1+d, y1-d);
2061 p->setPen(c0);
2062 d = wi - d - 1;
2063 p->drawLine(x2, y1, x2-d, y1-d);
2064 d--;
2065 p->setPen(c3);
2066 p->drawLine(x1+1, y1, x1+1+d, y1-d);
2067 p->setPen(c1);
2068 p->drawLine(x2-1, y1, x2-1-d, y1-d);
2069 break;
2070 case SlDown:
2071 p->setPen(c4);
2072 p->drawLine(x1, y2, x1+d, y2+d);
2073 p->setPen(c0);
2074 d = wi - d - 1;
2075 p->drawLine(x2, y2, x2-d, y2+d);
2076 d--;
2077 p->setPen(c3);
2078 p->drawLine(x1+1, y2, x1+1+d, y2+d);
2079 p->setPen(c1);
2080 p->drawLine(x2-1, y2, x2-1-d, y2+d);
2081 break;
2082 case SlLeft:
2083 p->setPen(c4);
2084 p->drawLine(x1, y1, x1-d, y1+d);
2085 p->setPen(c0);
2086 d = he - d - 1;
2087 p->drawLine(x1, y2, x1-d, y2-d);
2088 d--;
2089 p->setPen(c3);
2090 p->drawLine(x1, y1+1, x1-d, y1+1+d);
2091 p->setPen(c1);
2092 p->drawLine(x1, y2-1, x1-d, y2-1-d);
2093 break;
2094 case SlRight:
2095 p->setPen(c4);
2096 p->drawLine(x2, y1, x2+d, y1+d);
2097 p->setPen(c0);
2098 d = he - d - 1;
2099 p->drawLine(x2, y2, x2+d, y2-d);
2100 d--;
2101 p->setPen(c3);
2102 p->drawLine(x2, y1+1, x2+d, y1+1+d);
2103 p->setPen(c1);
2104 p->drawLine(x2, y2-1, x2+d, y2-1-d);
2105 break;
2106 }
2107 p->setRenderHint(QPainter::Qt4CompatiblePainting, oldQt4CompatiblePainting);
2108 }
2109 }
2110 break;
2111#endif // QT_CONFIG(slider)
2112#if QT_CONFIG(scrollbar)
2113 case CC_ScrollBar:
2114 if (const QStyleOptionSlider *scrollbar = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
2115 QStyleOptionSlider newScrollbar = *scrollbar;
2116 if (scrollbar->minimum == scrollbar->maximum)
2117 newScrollbar.state &= ~State_Enabled; //do not draw the slider.
2118 QCommonStyle::drawComplexControl(cc, &newScrollbar, p, widget);
2119 }
2120 break;
2121#endif // QT_CONFIG(scrollbar)
2122#if QT_CONFIG(combobox)
2123 case CC_ComboBox:
2124 if (const QStyleOptionComboBox *cmb = qstyleoption_cast<const QStyleOptionComboBox *>(opt)) {
2125 QBrush editBrush = cmb->palette.brush(QPalette::Base);
2126 if ((cmb->subControls & SC_ComboBoxFrame)) {
2127 if (cmb->frame) {
2128 QPalette shadePal = opt->palette;
2129 shadePal.setColor(QPalette::Midlight, shadePal.button().color());
2130 qDrawWinPanel(p, opt->rect, shadePal, true, &editBrush);
2131 }
2132 else {
2133 p->fillRect(opt->rect, editBrush);
2134 }
2135 }
2136 if (cmb->subControls & SC_ComboBoxArrow) {
2137 State flags = State_None;
2138
2139 QRect ar = proxy()->subControlRect(CC_ComboBox, cmb, SC_ComboBoxArrow, widget);
2140 bool sunkenArrow = cmb->activeSubControls == SC_ComboBoxArrow
2141 && cmb->state & State_Sunken;
2142 if (sunkenArrow) {
2143 p->setPen(cmb->palette.dark().color());
2144 p->setBrush(cmb->palette.brush(QPalette::Button));
2145 p->drawRect(ar.adjusted(0,0,-1,-1));
2146 } else {
2147 // Make qDrawWinButton use the right colors for drawing the shade of the button
2148 QPalette pal(cmb->palette);
2149 pal.setColor(QPalette::Button, cmb->palette.light().color());
2150 pal.setColor(QPalette::Light, cmb->palette.button().color());
2151 qDrawWinButton(p, ar, pal, false,
2152 &cmb->palette.brush(QPalette::Button));
2153 }
2154
2155 ar.adjust(2, 2, -2, -2);
2156 if (opt->state & State_Enabled)
2157 flags |= State_Enabled;
2158 if (opt->state & State_HasFocus)
2159 flags |= State_HasFocus;
2160
2161 if (sunkenArrow)
2162 flags