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

source code of qtbase/src/widgets/styles/qwindowsstyle.cpp