Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qwindowsvistastyle.cpp
Go to the documentation of this file.
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
8#include <qscreen.h>
9#include <qstylehints.h>
10#include <qwindow.h>
11#include <private/qstyleanimation_p.h>
12#include <private/qstylehelper_p.h>
13#include <qpa/qplatformnativeinterface.h>
14#include <private/qapplication_p.h>
15#include <private/qsystemlibrary_p.h>
16#include <private/qwindowsthemecache_p.h>
17
18#include "qdrawutil.h" // for now
19#include <qbackingstore.h>
20
21
23
24using namespace Qt::StringLiterals;
25
26static const int windowsItemFrame = 2; // menu item frame width
27static const int windowsItemHMargin = 3; // menu item hor text margin
28static const int windowsItemVMargin = 4; // menu item ver text margin
29static const int windowsArrowHMargin = 6; // arrow horizontal margin
30static const int windowsRightBorder = 15; // right border on windows
31
32#ifndef TMT_CONTENTMARGINS
33# define TMT_CONTENTMARGINS 3602
34#endif
35#ifndef TMT_SIZINGMARGINS
36# define TMT_SIZINGMARGINS 3601
37#endif
38#ifndef LISS_NORMAL
39# define LISS_NORMAL 1
40# define LISS_HOT 2
41# define LISS_SELECTED 3
42# define LISS_DISABLED 4
43# define LISS_SELECTEDNOTFOCUS 5
44# define LISS_HOTSELECTED 6
45#endif
46#ifndef BP_COMMANDLINK
47# define BP_COMMANDLINK 6
48# define BP_COMMANDLINKGLYPH 7
49# define CMDLGS_NORMAL 1
50# define CMDLGS_HOT 2
51# define CMDLGS_PRESSED 3
52# define CMDLGS_DISABLED 4
53#endif
54
55// QWindowsVistaStylePrivate -------------------------------------------------------------------------
56// Static initializations
57HWND QWindowsVistaStylePrivate::m_vistaTreeViewHelper = nullptr;
58bool QWindowsVistaStylePrivate::useVistaTheme = false;
59Q_CONSTINIT QBasicAtomicInt QWindowsVistaStylePrivate::ref = Q_BASIC_ATOMIC_INITIALIZER(-1); // -1 based refcounting
60
61static void qt_add_rect(HRGN &winRegion, QRect r)
62{
63 HRGN rgn = CreateRectRgn(r.left(), r.top(), r.x() + r.width(), r.y() + r.height());
64 if (rgn) {
65 HRGN dest = CreateRectRgn(0,0,0,0);
66 int result = CombineRgn(dest, winRegion, rgn, RGN_OR);
67 if (result) {
68 DeleteObject(winRegion);
69 winRegion = dest;
70 }
71 DeleteObject(rgn);
72 }
73}
74
75static HRGN qt_hrgn_from_qregion(const QRegion &region)
76{
77 HRGN hRegion = CreateRectRgn(0,0,0,0);
78 if (region.rectCount() == 1) {
79 qt_add_rect(hRegion, region.boundingRect());
80 return hRegion;
81 }
82 for (const QRect &rect : region)
83 qt_add_rect(hRegion, rect);
84 return hRegion;
85}
86
88{
89 if (const auto *pb = qstyleoption_cast<const QStyleOptionProgressBar *>(option))
91 return Qt::Horizontal;
92}
93
94/* In order to obtain the correct VistaTreeViewTheme (arrows for PE_IndicatorBranch),
95 * we need to set the windows "explorer" theme explicitly on a native
96 * window and open the "TREEVIEW" theme handle passing its window handle
97 * in order to get Vista-style item view themes (particularly drawBackground()
98 * for selected items needs this).
99 * We invoke a service of the native Windows interface to create
100 * a non-visible window handle, open the theme on it and insert it into
101 * the cache so that it is found by QWindowsThemeData::handle() first.
102 */
103static inline HWND createTreeViewHelperWindow()
104{
106
107 HWND result = nullptr;
108 if (auto nativeWindowsApp = dynamic_cast<QWindowsApplication *>(QGuiApplicationPrivate::platformIntegration()))
109 result = nativeWindowsApp->createMessageWindow(QStringLiteral("QTreeViewThemeHelperWindowClass"),
110 QStringLiteral("QTreeViewThemeHelperWindow"));
111 return result;
112}
113
115
116static inline TransformType transformType(const QTransform &transform, qreal devicePixelRatio)
117{
119 return SimpleTransform;
120 if (transform.type() > QTransform::TxScale)
121 return ComplexTransform;
122 return qFuzzyCompare(transform.m11(), devicePixelRatio)
123 && qFuzzyCompare(transform.m22(), devicePixelRatio)
125}
126
127// QTBUG-60571: Exclude known fully opaque theme parts which produce values
128// invalid in ARGB32_Premultiplied (for example, 0x00ffffff).
129static inline bool isFullyOpaque(const QWindowsThemeData &themeData)
130{
131 return themeData.theme == QWindowsVistaStylePrivate::TaskDialogTheme && themeData.partId == TDLG_PRIMARYPANEL;
132}
133
134static inline QRectF scaleRect(const QRectF &r, qreal factor)
135{
136 return r.isValid() && factor > 1
137 ? QRectF(r.topLeft() * factor, r.size() * factor) : r;
138}
139
140static QRegion scaleRegion(const QRegion &region, qreal factor)
141{
142 if (region.isEmpty() || qFuzzyCompare(factor, qreal(1)))
143 return region;
145 for (const QRect &rect : region)
146 result += QRectF(QPointF(rect.topLeft()) * factor, QSizeF(rect.size() * factor)).toRect();
147 return result;
148}
149
150
151/* \internal
152 Checks if the theme engine can/should be used, or if we should fall back
153 to Windows style. For Windows 10, this will still return false for the
154 High Contrast themes.
155*/
157{
158 if (update)
159 useVistaTheme = IsThemeActive() && (IsAppThemed() || !QCoreApplication::instance());
160 return useVistaTheme;
161}
162
163/* \internal
164 Handles refcounting, and queries the theme engine for usage.
165*/
167{
168 if (ref.ref() && !force)
169 return;
170 if (!force) // -1 based atomic refcounting
171 ref.ref();
172
173 useVista(true);
174}
175
176/* \internal
177 Cleans up all static data.
178*/
180{
181 if (bufferBitmap) {
182 if (bufferDC && nullBitmap)
183 SelectObject(bufferDC, nullBitmap);
184 DeleteObject(bufferBitmap);
185 bufferBitmap = nullptr;
186 }
187
188 if (bufferDC)
189 DeleteDC(bufferDC);
190 bufferDC = nullptr;
191
192 if (ref.deref() && !force)
193 return;
194 if (!force) // -1 based atomic refcounting
195 ref.deref();
196
197 useVistaTheme = false;
199}
200
202{
203 BOOL animEnabled = false;
204 if (SystemParametersInfo(SPI_GETCLIENTAREAANIMATION, 0, &animEnabled, 0))
205 {
206 if (animEnabled)
207 return true;
208 }
209 return false;
210}
211
213{
214 switch (pm) {
216 return QWindowsThemeData::themeSize(widget, nullptr, QWindowsVistaStylePrivate::ButtonTheme, BP_CHECKBOX, CBS_UNCHECKEDNORMAL).width();
218 return QWindowsThemeData::themeSize(widget, nullptr, QWindowsVistaStylePrivate::ButtonTheme, BP_CHECKBOX, CBS_UNCHECKEDNORMAL).height();
220 return QWindowsThemeData::themeSize(widget, nullptr, QWindowsVistaStylePrivate::ButtonTheme, BP_RADIOBUTTON, RBS_UNCHECKEDNORMAL).width();
222 return QWindowsThemeData::themeSize(widget, nullptr, QWindowsVistaStylePrivate::ButtonTheme, BP_RADIOBUTTON, RBS_UNCHECKEDNORMAL).height();
230 return QWindowsStylePrivate::pixelMetricFromSystemDp(QStyle::PM_TitleBarHeight, option, widget);
232 return QWindowsThemeData::themeSize(widget, nullptr, QWindowsVistaStylePrivate::WindowTheme, WP_FRAMELEFT, FS_ACTIVE).width();
234 return QWindowsThemeData::themeSize(widget, nullptr, QWindowsVistaStylePrivate::WindowTheme, WP_SMALLFRAMERIGHT, FS_ACTIVE).width();
235 default:
236 break;
237 }
238 return QWindowsVistaStylePrivate::InvalidMetric;
239}
240
242{
243 switch (pm) {
245 return 5;
247 return 18;
250 return 0;
252 return 3;
253 default:
254 break;
255 }
256
257 return QWindowsVistaStylePrivate::InvalidMetric;
258}
259
260bool QWindowsVistaStylePrivate::initVistaTreeViewTheming()
261{
262 if (m_vistaTreeViewHelper)
263 return true;
264
265 m_vistaTreeViewHelper = createTreeViewHelperWindow();
266 if (!m_vistaTreeViewHelper) {
267 qWarning("Unable to create the treeview helper window.");
268 return false;
269 }
270 if (FAILED(SetWindowTheme(m_vistaTreeViewHelper, L"explorer", nullptr))) {
271 qErrnoWarning("SetWindowTheme() failed.");
272 cleanupVistaTreeViewTheming();
273 return false;
274 }
275 return true;
276}
277
278void QWindowsVistaStylePrivate::cleanupVistaTreeViewTheming()
279{
280 if (m_vistaTreeViewHelper) {
281 DestroyWindow(m_vistaTreeViewHelper);
282 m_vistaTreeViewHelper = nullptr;
283 }
284}
285
286/* \internal
287 Closes all open theme data handles to ensure that we don't leak
288 resources, and that we don't refer to old handles when for
289 example the user changes the theme style.
290*/
292{
294 QWindowsVistaStylePrivate::cleanupVistaTreeViewTheming();
295}
296
297HTHEME QWindowsVistaStylePrivate::createTheme(int theme, HWND hwnd)
298{
299 if (theme == VistaTreeViewTheme && QWindowsVistaStylePrivate::initVistaTreeViewTheming())
300 hwnd = QWindowsVistaStylePrivate::m_vistaTreeViewHelper;
301 return QWindowsThemeCache::createTheme(theme, hwnd);
302}
303
305{
306 if (QBackingStore *backingStore = widget->backingStore())
307 return backingStore;
308 if (const QWidget *topLevel = widget->nativeParentWidget())
309 if (QBackingStore *topLevelBackingStore = topLevel->backingStore())
310 return topLevelBackingStore;
311 return nullptr;
312}
313
315{
316 if (QBackingStore *backingStore = backingStoreForWidget(widget)) {
318 if (nativeInterface)
319 return static_cast<HDC>(nativeInterface->nativeResourceForBackingStore(QByteArrayLiteral("getDC"), backingStore));
320 }
321 return nullptr;
322}
323
328
330{
331 if (!widget)
332 return false;
333 const QWidget *parent1 = widget->parentWidget();
334 // Exclude dialogs or other toplevels parented on item views.
335 if (!parent1 || parent1->isWindow())
336 return false;
337 const QWidget *parent2 = parent1->parentWidget();
338 return parent2 && widget->inherits("QLineEdit")
339 && parent2->inherits("QAbstractItemView");
340}
341
342// Returns whether base color is set for this widget
344{
345 uint resolveMask = option->palette.resolveMask();
346 if (widget) {
347 // Since spin box includes a line edit we need to resolve the palette mask also from
348 // the parent, as while the color is always correct on the palette supplied by panel,
349 // the mask can still be empty. If either mask specifies custom base color, use that.
350#if QT_CONFIG(spinbox)
351 if (const QAbstractSpinBox *spinbox = qobject_cast<QAbstractSpinBox*>(widget->parentWidget()))
352 resolveMask |= spinbox->palette().resolveMask();
353#endif // QT_CONFIG(spinbox)
354 }
355 return (resolveMask & (1 << QPalette::Base)) != 0;
356}
357
365{
366 if (widget) {
367 if (const HWND hwnd = QApplicationPrivate::getHWNDForWidget(const_cast<QWidget *>(widget)))
368 return hwnd;
369 }
370
371 // Find top level with native window (there might be dialogs that do not have one).
372 const auto allWindows = QGuiApplication::allWindows();
373 for (const QWindow *window : allWindows) {
374 if (window->isTopLevel() && window->type() != Qt::Desktop && window->handle() != nullptr)
375 return reinterpret_cast<HWND>(window->winId());
376 }
377
378 return GetDesktopWindow();
379}
380
387{
388 // If we already have a HBITMAP which is of adequate size, just return that
389 if (bufferBitmap) {
390 if (bufferW >= w && bufferH >= h)
391 return bufferBitmap;
392 // Not big enough, discard the old one
393 if (bufferDC && nullBitmap)
394 SelectObject(bufferDC, nullBitmap);
395 DeleteObject(bufferBitmap);
396 bufferBitmap = nullptr;
397 }
398
399 w = qMax(bufferW, w);
400 h = qMax(bufferH, h);
401
402 if (!bufferDC) {
403 HDC displayDC = GetDC(nullptr);
404 bufferDC = CreateCompatibleDC(displayDC);
405 ReleaseDC(nullptr, displayDC);
406 }
407
408 // Define the header
409 BITMAPINFO bmi;
410 memset(&bmi, 0, sizeof(bmi));
411 bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
412 bmi.bmiHeader.biWidth = w;
413 bmi.bmiHeader.biHeight = -h;
414 bmi.bmiHeader.biPlanes = 1;
415 bmi.bmiHeader.biBitCount = 32;
416 bmi.bmiHeader.biCompression = BI_RGB;
417
418 // Create the pixmap
419 bufferPixels = nullptr;
420 bufferBitmap = CreateDIBSection(bufferDC, &bmi, DIB_RGB_COLORS, reinterpret_cast<void **>(&bufferPixels), nullptr, 0);
421 GdiFlush();
422 nullBitmap = static_cast<HBITMAP>(SelectObject(bufferDC, bufferBitmap));
423
424 if (Q_UNLIKELY(!bufferBitmap)) {
425 qErrnoWarning("QWindowsVistaStylePrivate::buffer(%dx%d), CreateDIBSection() failed.", w, h);
426 bufferW = 0;
427 bufferH = 0;
428 return nullptr;
429 }
430 if (Q_UNLIKELY(!bufferPixels)) {
431 qErrnoWarning("QWindowsVistaStylePrivate::buffer(%dx%d), CreateDIBSection() did not allocate pixel data.", w, h);
432 bufferW = 0;
433 bufferH = 0;
434 return nullptr;
435 }
436 bufferW = w;
437 bufferH = h;
438#ifdef DEBUG_XP_STYLE
439 qDebug("Creating new dib section (%d, %d)", w, h);
440#endif
441 return bufferBitmap;
442}
443
451{
452 return IsThemeBackgroundPartiallyTransparent(themeData.handle(), themeData.partId,
453 themeData.stateId);
454}
455
456
461{
462 HRGN hRgn = nullptr;
463 const qreal factor = QWindowsStylePrivate::nativeMetricScaleFactor(themeData.widget);
464 RECT rect = themeData.toRECT(QRect(themeData.rect.topLeft() / factor, themeData.rect.size() / factor));
465 if (!SUCCEEDED(GetThemeBackgroundRegion(themeData.handle(), bufferHDC(), themeData.partId,
466 themeData.stateId, &rect, &hRgn))) {
467 return QRegion();
468 }
469
470 HRGN dest = CreateRectRgn(0, 0, 0, 0);
471 const bool success = CombineRgn(dest, hRgn, nullptr, RGN_COPY) != ERROR;
472
474
475 if (success) {
476 QVarLengthArray<char> buf(256);
477 RGNDATA *rd = reinterpret_cast<RGNDATA *>(buf.data());
478 if (GetRegionData(dest, buf.size(), rd) == 0) {
479 const auto numBytes = GetRegionData(dest, 0, nullptr);
480 if (numBytes > 0) {
481 buf.resize(numBytes);
482 rd = reinterpret_cast<RGNDATA *>(buf.data());
483 if (GetRegionData(dest, numBytes, rd) == 0)
484 rd = nullptr;
485 } else {
486 rd = nullptr;
487 }
488 }
489 if (rd) {
490 RECT *r = reinterpret_cast<RECT *>(rd->Buffer);
491 for (uint i = 0; i < rd->rdh.nCount; ++i) {
492 QRect rect;
493 rect.setCoords(int(r->left * factor), int(r->top * factor),
494 int((r->right - 1) * factor), int((r->bottom - 1) * factor));
495 ++r;
496 region |= rect;
497 }
498 }
499 }
500
501 DeleteObject(hRgn);
502 DeleteObject(dest);
503
504 return region;
505}
506
512{
513 const int startX = rect.left();
514 const int startY = rect.top();
515 const int w = rect.width();
516 const int h = rect.height();
517
518 int firstAlpha = -1;
519 for (int y = startY; y < h/2; ++y) {
520 auto buffer = reinterpret_cast<const DWORD *>(bufferPixels) + (y * bufferW);
521 for (int x = startX; x < w; ++x, ++buffer) {
522 int alpha = (*buffer) >> 24;
523 if (firstAlpha == -1)
524 firstAlpha = alpha;
525 else if (alpha != firstAlpha)
526 return true;
527 }
528 }
529 return false;
530}
531
541{
542 const int startX = rect.left();
543 const int startY = rect.top();
544 const int w = rect.width();
545 const int h = rect.height();
546 bool hasFixedAlphaValue = false;
547
548 for (int y = startY; y < h; ++y) {
549 auto buffer = reinterpret_cast<DWORD *>(bufferPixels) + (y * bufferW);
550 for (int x = startX; x < w; ++x, ++buffer) {
551 uint pixel = *buffer;
552 int alpha = qAlpha(pixel);
553 if (qRed(pixel) > alpha || qGreen(pixel) > alpha || qBlue(pixel) > alpha) {
554 *buffer |= 0xff000000;
555 hasFixedAlphaValue = true;
556 }
557 }
558 }
559 return hasFixedAlphaValue;
560}
561
572{
573 const int startX = rect.left();
574 const int startY = rect.top();
575 const int w = rect.width();
576 const int h = rect.height();
577 bool valueChange = false;
578
579 // Flip the alphas, so that 255-alpha pixels are 0, and 0-alpha are 255.
580 for (int y = startY; y < h; ++y) {
581 auto buffer = reinterpret_cast<DWORD *>(bufferPixels) + (y * bufferW);
582 for (int x = startX; x < w; ++x, ++buffer) {
583 if (allPixels) {
584 *buffer |= 0xFF000000;
585 continue;
586 }
587 unsigned int alphaValue = (*buffer) & 0xFF000000;
588 if (alphaValue == 0xFF000000) {
589 *buffer = 0;
590 valueChange = true;
591 } else if (alphaValue == 0) {
592 *buffer |= 0xFF000000;
593 valueChange = true;
594 }
595 }
596 }
597 return valueChange;
598}
599
612{
613 if (themeData.rect.isEmpty())
614 return true;
615
616 QPainter *painter = themeData.painter;
617 Q_ASSERT_X(painter != nullptr, "QWindowsVistaStylePrivate::drawBackground()", "Trying to draw a theme part without a painter");
618 if (!painter || !painter->isActive())
619 return false;
620
621 painter->save();
622
623 // Access paintDevice via engine since the painter may
624 // return the clip device which can still be a widget device in case of grabWidget().
625
626 bool translucentToplevel = false;
627 const QPaintDevice *paintDevice = painter->device();
628 const qreal aditionalDevicePixelRatio = themeData.widget ? themeData.widget->devicePixelRatio() : qreal(1);
629 if (paintDevice->devType() == QInternal::Widget) {
630 const QWidget *window = static_cast<const QWidget *>(paintDevice)->window();
631 translucentToplevel = window->testAttribute(Qt::WA_TranslucentBackground);
632 }
633
634 const TransformType tt = transformType(painter->deviceTransform(), aditionalDevicePixelRatio);
635
636 bool canDrawDirectly = false;
637 if (themeData.widget && painter->opacity() == 1.0 && !themeData.rotate
638 && !isFullyOpaque(themeData)
639 && tt != ComplexTransform && !themeData.mirrorVertically && !themeData.invertPixels
640 && !translucentToplevel) {
641 // Draw on backing store DC only for real widgets or backing store images.
642 const QPaintDevice *enginePaintDevice = painter->paintEngine()->paintDevice();
643 switch (enginePaintDevice->devType()) {
645 canDrawDirectly = true;
646 break;
647 case QInternal::Image:
648 // Ensure the backing store has received as resize and is initialized.
649 if (QBackingStore *bs = backingStoreForWidget(themeData.widget)) {
650 if (bs->size().isValid() && bs->paintDevice() == enginePaintDevice)
651 canDrawDirectly = true;
652 }
653 break;
654 }
655 }
656
657 const HDC dc = canDrawDirectly ? hdcForWidgetBackingStore(themeData.widget) : nullptr;
658 const bool result = dc && qFuzzyCompare(correctionFactor, qreal(1))
659 ? drawBackgroundDirectly(dc, themeData, aditionalDevicePixelRatio)
660 : drawBackgroundThruNativeBuffer(themeData, aditionalDevicePixelRatio, correctionFactor);
661 painter->restore();
662 return result;
663}
664
670bool QWindowsVistaStylePrivate::drawBackgroundDirectly(HDC dc, QWindowsThemeData &themeData, qreal additionalDevicePixelRatio)
671{
672 QPainter *painter = themeData.painter;
673
674 const auto &deviceTransform = painter->deviceTransform();
675 const QPointF redirectionDelta(deviceTransform.dx(), deviceTransform.dy());
676 const QRect area = scaleRect(QRectF(themeData.rect), additionalDevicePixelRatio).translated(redirectionDelta).toRect();
677
678 QRegion sysRgn = painter->paintEngine()->systemClip();
679 if (sysRgn.isEmpty())
680 sysRgn = area;
681 else
682 sysRgn &= area;
683 if (painter->hasClipping())
684 sysRgn &= scaleRegion(painter->clipRegion(), additionalDevicePixelRatio).translated(redirectionDelta.toPoint());
685 HRGN hrgn = qt_hrgn_from_qregion(sysRgn);
686 SelectClipRgn(dc, hrgn);
687
688#ifdef DEBUG_XP_STYLE
689 printf("---[ DIRECT PAINTING ]------------------> Name(%-10s) Part(%d) State(%d)\n",
690 qPrintable(themeData.name), themeData.partId, themeData.stateId);
691 showProperties(themeData);
692#endif
693
694 RECT drawRECT = themeData.toRECT(area);
695 DTBGOPTS drawOptions;
696 memset(&drawOptions, 0, sizeof(drawOptions));
697 drawOptions.dwSize = sizeof(drawOptions);
698 drawOptions.rcClip = themeData.toRECT(sysRgn.boundingRect());
699 drawOptions.dwFlags = DTBG_CLIPRECT
700 | (themeData.noBorder ? DTBG_OMITBORDER : 0)
701 | (themeData.noContent ? DTBG_OMITCONTENT : 0)
702 | (themeData.mirrorHorizontally ? DTBG_MIRRORDC : 0);
703
704 const HRESULT result = DrawThemeBackgroundEx(themeData.handle(), dc, themeData.partId, themeData.stateId, &(drawRECT), &drawOptions);
705 SelectClipRgn(dc, nullptr);
706 DeleteObject(hrgn);
707 return SUCCEEDED(result);
708}
709
723 qreal additionalDevicePixelRatio,
724 qreal correctionFactor)
725{
726 QPainter *painter = themeData.painter;
727 QRectF rectF = scaleRect(QRectF(themeData.rect), additionalDevicePixelRatio);
728
729 if ((themeData.rotate + 90) % 180 == 0) { // Catch 90,270,etc.. degree flips.
730 rectF = QRectF(0, 0, rectF.height(), rectF.width());
731 }
732 rectF.moveTo(0, 0);
733
734 const bool hasCorrectionFactor = !qFuzzyCompare(correctionFactor, qreal(1));
735 QRect rect = rectF.toRect();
736 const QRect drawRect = hasCorrectionFactor
737 ? QRectF(rectF.topLeft() / correctionFactor, rectF.size() / correctionFactor).toRect()
738 : rect;
739 int partId = themeData.partId;
740 int stateId = themeData.stateId;
741 int w = rect.width();
742 int h = rect.height();
743
744 // Values initialized later, either from cached values, or from function calls
745 AlphaChannelType alphaType = UnknownAlpha;
746 bool stateHasData = true; // We assume so;
747 bool hasAlpha = false;
748 bool partIsTransparent;
749 bool potentialInvalidAlpha;
750
751 QString pixmapCacheKey = QStringLiteral("$qt_xp_");
752 pixmapCacheKey.append(themeName(themeData.theme));
753 pixmapCacheKey.append(QLatin1Char('p'));
754 pixmapCacheKey.append(QString::number(partId));
755 pixmapCacheKey.append(QLatin1Char('s'));
756 pixmapCacheKey.append(QString::number(stateId));
757 pixmapCacheKey.append(QLatin1Char('s'));
758 pixmapCacheKey.append(themeData.noBorder ? QLatin1Char('0') : QLatin1Char('1'));
759 pixmapCacheKey.append(QLatin1Char('b'));
760 pixmapCacheKey.append(themeData.noContent ? QLatin1Char('0') : QLatin1Char('1'));
761 pixmapCacheKey.append(QString::number(w));
762 pixmapCacheKey.append(QLatin1Char('w'));
763 pixmapCacheKey.append(QString::number(h));
764 pixmapCacheKey.append(QLatin1Char('h'));
765 pixmapCacheKey.append(QString::number(additionalDevicePixelRatio));
766 pixmapCacheKey.append(QLatin1Char('d'));
767 if (hasCorrectionFactor) {
768 pixmapCacheKey.append(QLatin1Char('c'));
769 pixmapCacheKey.append(QString::number(correctionFactor));
770 }
771
772 QPixmap cachedPixmap;
773 ThemeMapKey key(themeData);
774 ThemeMapData data = alphaCache.value(key);
775
776 bool haveCachedPixmap = false;
777 bool isCached = data.dataValid;
778 if (isCached) {
779 partIsTransparent = data.partIsTransparent;
780 hasAlpha = data.hasAlphaChannel;
781 alphaType = data.alphaType;
782 potentialInvalidAlpha = data.hadInvalidAlpha;
783
784 haveCachedPixmap = QPixmapCache::find(pixmapCacheKey, &cachedPixmap);
785
786#ifdef DEBUG_XP_STYLE
787 char buf[25];
788 ::sprintf(buf, "+ Pixmap(%3d, %3d) ]", w, h);
789 printf("---[ CACHED %s--------> Name(%-10s) Part(%d) State(%d)\n",
790 haveCachedPixmap ? buf : "]-------------------",
791 qPrintable(themeData.name), themeData.partId, themeData.stateId);
792#endif
793 } else {
794 // Not cached, so get values from Theme Engine
795 BOOL tmt_borderonly = false;
796 COLORREF tmt_transparentcolor = 0x0;
797 PROPERTYORIGIN proporigin = PO_NOTFOUND;
798 GetThemeBool(themeData.handle(), themeData.partId, themeData.stateId, TMT_BORDERONLY, &tmt_borderonly);
799 GetThemeColor(themeData.handle(), themeData.partId, themeData.stateId, TMT_TRANSPARENTCOLOR, &tmt_transparentcolor);
800 GetThemePropertyOrigin(themeData.handle(), themeData.partId, themeData.stateId, TMT_CAPTIONMARGINS, &proporigin);
801
802 partIsTransparent = isTransparent(themeData);
803
804 potentialInvalidAlpha = false;
805 GetThemePropertyOrigin(themeData.handle(), themeData.partId, themeData.stateId, TMT_GLYPHTYPE, &proporigin);
806 if (proporigin == PO_PART || proporigin == PO_STATE) {
807 int tmt_glyphtype = GT_NONE;
808 GetThemeEnumValue(themeData.handle(), themeData.partId, themeData.stateId, TMT_GLYPHTYPE, &tmt_glyphtype);
809 potentialInvalidAlpha = partIsTransparent && tmt_glyphtype == GT_IMAGEGLYPH;
810 }
811
812#ifdef DEBUG_XP_STYLE
813 printf("---[ NOT CACHED ]-----------------------> Name(%-10s) Part(%d) State(%d)\n",
814 qPrintable(themeData.name), themeData.partId, themeData.stateId);
815 printf("-->partIsTransparen = %d\n", partIsTransparent);
816 printf("-->potentialInvalidAlpha = %d\n", potentialInvalidAlpha);
817 showProperties(themeData);
818#endif
819 }
820 bool wasAlphaSwapped = false;
821 bool wasAlphaFixed = false;
822
823 // OLD PSDK Workaround ------------------------------------------------------------------------
824 // See if we need extra clipping for the older PSDK, which does
825 // not have a DrawThemeBackgroundEx function for DTGB_OMITBORDER
826 // and DTGB_OMITCONTENT
827 bool addBorderContentClipping = false;
828 QRegion extraClip;
829 QRect area = drawRect;
830 if (themeData.noBorder || themeData.noContent) {
831 extraClip = area;
832 // We are running on a system where the uxtheme.dll does not have
833 // the DrawThemeBackgroundEx function, so we need to clip away
834 // borders or contents manually.
835
836 int borderSize = 0;
837 PROPERTYORIGIN origin = PO_NOTFOUND;
838 GetThemePropertyOrigin(themeData.handle(), themeData.partId, themeData.stateId, TMT_BORDERSIZE, &origin);
839 GetThemeInt(themeData.handle(), themeData.partId, themeData.stateId, TMT_BORDERSIZE, &borderSize);
840 borderSize *= additionalDevicePixelRatio;
841
842 // Clip away border region
843 if ((origin == PO_CLASS || origin == PO_PART || origin == PO_STATE) && borderSize > 0) {
844 if (themeData.noBorder) {
845 extraClip &= area;
846 area = area.adjusted(-borderSize, -borderSize, borderSize, borderSize);
847 }
848
849 // Clip away content region
850 if (themeData.noContent) {
851 QRegion content = area.adjusted(borderSize, borderSize, -borderSize, -borderSize);
852 extraClip ^= content;
853 }
854 }
855 addBorderContentClipping = (themeData.noBorder | themeData.noContent);
856 }
857
858 QImage img;
859 if (!haveCachedPixmap) { // If the pixmap is not cached, generate it! -------------------------
860 if (!buffer(drawRect.width(), drawRect.height())) // Ensure a buffer of at least (w, h) in size
861 return false;
862 HDC dc = bufferHDC();
863
864 // Clear the buffer
865 if (alphaType != NoAlpha) {
866 // Consider have separate "memset" function for small chunks for more speedup
867 memset(bufferPixels, 0x00, bufferW * drawRect.height() * 4);
868 }
869
870 // Difference between area and rect
871 int dx = area.x() - drawRect.x();
872 int dy = area.y() - drawRect.y();
873
874 // Adjust so painting rect starts from Origo
875 rect.moveTo(0,0);
876 area.moveTo(dx,dy);
877 DTBGOPTS drawOptions;
878 drawOptions.dwSize = sizeof(drawOptions);
879 drawOptions.rcClip = themeData.toRECT(rect);
880 drawOptions.dwFlags = DTBG_CLIPRECT
881 | (themeData.noBorder ? DTBG_OMITBORDER : 0)
882 | (themeData.noContent ? DTBG_OMITCONTENT : 0);
883
884 // Drawing the part into the backing store
885 RECT wRect(themeData.toRECT(area));
886 DrawThemeBackgroundEx(themeData.handle(), dc, themeData.partId, themeData.stateId, &wRect, &drawOptions);
887
888 // If not cached, analyze the buffer data to figure
889 // out alpha type, and if it contains data
890 if (!isCached) {
891 // SHORTCUT: If the part's state has no data, cache it for NOOP later
892 if (!stateHasData) {
893 memset(static_cast<void *>(&data), 0, sizeof(data));
894 data.dataValid = true;
895 alphaCache.insert(key, data);
896 return true;
897 }
899 if (!hasAlpha && partIsTransparent)
900 potentialInvalidAlpha = true;
901#if defined(DEBUG_XP_STYLE) && 1
902 dumpNativeDIB(drawRect.width(), drawRect.height());
903#endif
904 }
905
906 // Fix alpha values, if needed
907 if (potentialInvalidAlpha)
908 wasAlphaFixed = fixAlphaChannel(drawRect);
909
911 if ((partIsTransparent && !wasAlphaSwapped) || (!partIsTransparent && hasAlpha)) {
913 alphaType = RealAlpha;
914 } else if (wasAlphaSwapped) {
916 alphaType = MaskAlpha;
917 } else {
919 // The image data we got from the theme engine does not have any transparency,
920 // thus the alpha channel is set to 0.
921 // However, Format_RGB32 requires the alpha part to be set to 0xff, thus
922 // we must flip it from 0x00 to 0xff
923 swapAlphaChannel(rect, true);
924 alphaType = NoAlpha;
925 }
926#if defined(DEBUG_XP_STYLE) && 1
927 printf("Image format is: %s\n", alphaType == RealAlpha ? "Real Alpha" : alphaType == MaskAlpha ? "Masked Alpha" : "No Alpha");
928#endif
929 img = QImage(bufferPixels, bufferW, bufferH, format);
930 if (themeData.invertPixels)
931 img.invertPixels();
932
933 if (hasCorrectionFactor)
934 img = img.scaled(img.size() * correctionFactor, Qt::KeepAspectRatio, Qt::SmoothTransformation);
935 img.setDevicePixelRatio(additionalDevicePixelRatio);
936 }
937
938 // Blitting backing store
939 bool useRegion = partIsTransparent && !hasAlpha && !wasAlphaSwapped;
940
941 QRegion newRegion;
942 QRegion oldRegion;
943 if (useRegion) {
944 newRegion = region(themeData);
945 oldRegion = painter->clipRegion();
946 painter->setClipRegion(newRegion);
947#if defined(DEBUG_XP_STYLE) && 0
948 printf("Using region:\n");
949 for (const QRect &r : newRegion)
950 printf(" (%d, %d, %d, %d)\n", r.x(), r.y(), r.right(), r.bottom());
951#endif
952 }
953
954 if (addBorderContentClipping)
955 painter->setClipRegion(scaleRegion(extraClip, 1.0 / additionalDevicePixelRatio), Qt::IntersectClip);
956
957 if (!themeData.mirrorHorizontally && !themeData.mirrorVertically && !themeData.rotate) {
958 if (!haveCachedPixmap)
959 painter->drawImage(themeData.rect, img, rect);
960 else
961 painter->drawPixmap(themeData.rect, cachedPixmap);
962 } else {
963 // This is _slow_!
964 // Make a copy containing only the necessary data, and mirror
965 // on all wanted axes. Then draw the copy.
966 // If cached, the normal pixmap is cached, instead of caching
967 // all possible orientations for each part and state.
968 QImage imgCopy;
969 if (!haveCachedPixmap)
970 imgCopy = img.copy(rect);
971 else
972 imgCopy = cachedPixmap.toImage();
973
974 if (themeData.rotate) {
975 QTransform rotMatrix;
976 rotMatrix.rotate(themeData.rotate);
977 imgCopy = imgCopy.transformed(rotMatrix);
978 }
979 if (themeData.mirrorHorizontally || themeData.mirrorVertically)
980 imgCopy = imgCopy.mirrored(themeData.mirrorHorizontally, themeData.mirrorVertically);
981 painter->drawImage(themeData.rect, imgCopy);
982 }
983
984 if (useRegion || addBorderContentClipping) {
985 if (oldRegion.isEmpty())
986 painter->setClipping(false);
987 else
988 painter->setClipRegion(oldRegion);
989 }
990
991 // Cache the pixmap to avoid expensive swapAlphaChannel() calls
992 if (!haveCachedPixmap && w && h) {
994 QPixmapCache::insert(pixmapCacheKey, pix);
995#ifdef DEBUG_XP_STYLE
996 printf("+++Adding pixmap to cache, size(%d, %d), wasAlphaSwapped(%d), wasAlphaFixed(%d), name(%s)\n",
997 w, h, wasAlphaSwapped, wasAlphaFixed, qPrintable(pixmapCacheKey));
998#endif
999 }
1000
1001 // Add to theme part cache
1002 if (!isCached) {
1003 memset(static_cast<void *>(&data), 0, sizeof(data));
1004 data.dataValid = true;
1005 data.partIsTransparent = partIsTransparent;
1006 data.alphaType = alphaType;
1007 data.hasAlphaChannel = hasAlpha;
1008 data.wasAlphaSwapped = wasAlphaSwapped;
1009 data.hadInvalidAlpha = wasAlphaFixed;
1010 alphaCache.insert(key, data);
1011 }
1012 return true;
1013}
1014
1023{
1024 Q_Q(const QWindowsVistaStyle);
1025 static bool animationTimeOverride = q->dynamicPropertyNames().contains("_qt_animation_time");
1026 if (animationTimeOverride)
1027 return q->property("_qt_animation_time").toTime();
1028 return QTime::currentTime();
1029}
1030
1031/* \internal
1032 Checks and returns the style object
1033*/
1035 return option ? option->styleObject : nullptr;
1036}
1037
1038/* \internal
1039 Checks if we can animate on a style option
1040*/
1042 return option
1043 && option->styleObject
1044 && !option->styleObject->property("_q_no_animation").toBool();
1045}
1046
1048{
1049 const qreal devicePixelRatio = widget
1050 ? widget->devicePixelRatioF() : qApp->devicePixelRatio();
1051 QImage result(option->rect.size() * devicePixelRatio, QImage::Format_ARGB32_Premultiplied);
1052 result.setDevicePixelRatio(devicePixelRatio);
1053 result.fill(0);
1054 return result;
1055}
1056
1057/* \internal
1058 Used by animations to clone a styleoption and shift its offset
1059*/
1061 QStyleOption *styleOption = nullptr;
1062 if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider*>(option))
1063 styleOption = new QStyleOptionSlider(*slider);
1064 else if (const QStyleOptionSpinBox *spinbox = qstyleoption_cast<const QStyleOptionSpinBox*>(option))
1065 styleOption = new QStyleOptionSpinBox(*spinbox);
1066 else if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast<const QStyleOptionGroupBox*>(option))
1067 styleOption = new QStyleOptionGroupBox(*groupBox);
1068 else if (const QStyleOptionComboBox *combo = qstyleoption_cast<const QStyleOptionComboBox*>(option))
1069 styleOption = new QStyleOptionComboBox(*combo);
1070 else if (const QStyleOptionButton *button = qstyleoption_cast<const QStyleOptionButton*>(option))
1071 styleOption = new QStyleOptionButton(*button);
1072 else
1073 styleOption = new QStyleOption(*option);
1074 styleOption->rect = QRect(QPoint(0,0), option->rect.size());
1075 return styleOption;
1076}
1077
1078/* \internal
1079 Used by animations to delete cloned styleoption
1080*/
1082{
1083 if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider*>(option))
1084 delete slider;
1085 else if (const QStyleOptionSpinBox *spinbox = qstyleoption_cast<const QStyleOptionSpinBox*>(option))
1086 delete spinbox;
1087 else if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast<const QStyleOptionGroupBox*>(option))
1088 delete groupBox;
1089 else if (const QStyleOptionComboBox *combo = qstyleoption_cast<const QStyleOptionComboBox*>(option))
1090 delete combo;
1091 else if (const QStyleOptionButton *button = qstyleoption_cast<const QStyleOptionButton*>(option))
1092 delete button;
1093 else
1094 delete option;
1095}
1096
1099 QStyle::SubControl subControl,
1100 bool isTitleBarActive, int part,
1101 QWindowsThemeData *theme)
1102{
1103 theme->rect = proxy->subControlRect(QStyle::CC_TitleBar, option, subControl, widget);
1104 theme->partId = part;
1105 if (widget && !widget->isEnabled())
1106 theme->stateId = RBS_DISABLED;
1107 else if (option->activeSubControls == subControl && option->state.testFlag(QStyle::State_Sunken))
1108 theme->stateId = RBS_PUSHED;
1109 else if (option->activeSubControls == subControl && option->state.testFlag(QStyle::State_MouseOver))
1110 theme->stateId = RBS_HOT;
1111 else if (!isTitleBarActive)
1112 theme->stateId = RBS_INACTIVE;
1113 else
1114 theme->stateId = RBS_NORMAL;
1115}
1116
1117#if QT_CONFIG(mdiarea)
1118// Helper for drawing MDI buttons into the corner widget of QMenuBar in case a
1119// QMdiSubWindow is maximized.
1120static void populateMdiButtonTheme(const QStyle *proxy, const QWidget *widget,
1122 QStyle::SubControl subControl, int part,
1123 QWindowsThemeData *theme)
1124{
1125 theme->partId = part;
1126 theme->rect = proxy->subControlRect(QStyle::CC_MdiControls, option, subControl, widget);
1127 if (!option->state.testFlag(QStyle::State_Enabled))
1128 theme->stateId = CBS_INACTIVE;
1129 else if (option->state.testFlag(QStyle::State_Sunken) && option->activeSubControls.testFlag(subControl))
1130 theme->stateId = CBS_PUSHED;
1131 else if (option->state.testFlag(QStyle::State_MouseOver) && option->activeSubControls.testFlag(subControl))
1132 theme->stateId = CBS_HOT;
1133 else
1134 theme->stateId = CBS_NORMAL;
1135}
1136
1137// Calculate an small (max 2), empirical correction factor for scaling up
1138// WP_MDICLOSEBUTTON, WP_MDIRESTOREBUTTON, WP_MDIMINBUTTON, which are too
1139// small on High DPI screens (QTBUG-75927).
1140static qreal mdiButtonCorrectionFactor(QWindowsThemeData &theme, const QPaintDevice *pd = nullptr)
1141{
1142 const auto dpr = pd ? pd->devicePixelRatio() : qApp->devicePixelRatio();
1143 const QSizeF nativeSize = QSizeF(theme.size()) / dpr;
1144 const QSizeF requestedSize(theme.rect.size());
1145 const auto rawFactor = qMin(requestedSize.width() / nativeSize.width(),
1146 requestedSize.height() / nativeSize.height());
1147 const auto factor = rawFactor >= qreal(2) ? qreal(2) : qreal(1);
1148 return factor;
1149}
1150#endif // QT_CONFIG(mdiarea)
1151
1152/*
1153 This function is used by subControlRect to check if a button
1154 should be drawn for the given subControl given a set of window flags.
1155*/
1157
1158 bool isMinimized = tb->titleBarState & Qt::WindowMinimized;
1159 bool isMaximized = tb->titleBarState & Qt::WindowMaximized;
1160 const auto flags = tb->titleBarFlags;
1161 bool retVal = false;
1162 switch (sc) {
1165 retVal = true;
1166 break;
1168 if (!isMinimized && (flags & Qt::WindowMinimizeButtonHint))
1169 retVal = true;
1170 break;
1172 if (isMinimized && (flags & Qt::WindowMinimizeButtonHint))
1173 retVal = true;
1174 else if (isMaximized && (flags & Qt::WindowMaximizeButtonHint))
1175 retVal = true;
1176 break;
1178 if (!isMaximized && (flags & Qt::WindowMaximizeButtonHint))
1179 retVal = true;
1180 break;
1182 if (!isMinimized && flags & Qt::WindowShadeButtonHint)
1183 retVal = true;
1184 break;
1186 if (isMinimized && flags & Qt::WindowShadeButtonHint)
1187 retVal = true;
1188 break;
1191 retVal = true;
1192 break;
1195 retVal = true;
1196 break;
1197 default :
1198 retVal = true;
1199 }
1200 return retVal;
1201}
1202
1203//convert Qt state flags to uxtheme button states
1204static int buttonStateId(int flags, int partId)
1205{
1206 int stateId = 0;
1207 if (partId == BP_RADIOBUTTON || partId == BP_CHECKBOX) {
1209 stateId = RBS_UNCHECKEDDISABLED;
1210 else if (flags & QStyle::State_Sunken)
1211 stateId = RBS_UNCHECKEDPRESSED;
1212 else if (flags & QStyle::State_MouseOver)
1213 stateId = RBS_UNCHECKEDHOT;
1214 else
1215 stateId = RBS_UNCHECKEDNORMAL;
1216
1217 if (flags & QStyle::State_On)
1218 stateId += RBS_CHECKEDNORMAL-1;
1219
1220 } else if (partId == BP_PUSHBUTTON) {
1222 stateId = PBS_DISABLED;
1224 stateId = PBS_PRESSED;
1225 else if (flags & QStyle::State_MouseOver)
1226 stateId = PBS_HOT;
1227 else
1228 stateId = PBS_NORMAL;
1229 } else {
1230 Q_ASSERT(1);
1231 }
1232 return stateId;
1233}
1234
1236 const QStyleOption *option,
1237 const QWidget *widget)
1238{
1239 bool result = false;
1240 switch (element) {
1243 result = true;
1244 break;
1245 // QTBUG-40634, do not animate when color is set in palette for PE_PanelLineEdit.
1248 break;
1249 default:
1250 break;
1251 }
1252 return result;
1253}
1254
1275
1283
1288
1289
1320void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOption *option,
1321 QPainter *painter, const QWidget *widget) const
1322{
1324 QWindowsStyle::drawPrimitive(element, option, painter, widget);
1325 return;
1326 }
1327
1328 QWindowsVistaStylePrivate *d = const_cast<QWindowsVistaStylePrivate*>(d_func());
1329
1330 int state = option->state;
1331 QRect rect = option->rect;
1332
1333 if ((state & State_Enabled) && d->transitionsEnabled() && canAnimate(option)) {
1334 if (supportsStateTransition(element, option, widget)) {
1335 // Retrieve and update the dynamic properties tracking
1336 // the previous state of the widget:
1337 QObject *styleObject = option->styleObject;
1338 styleObject->setProperty("_q_no_animation", true);
1339 int oldState = styleObject->property("_q_stylestate").toInt();
1340 QRect oldRect = styleObject->property("_q_stylerect").toRect();
1341 QRect newRect = rect;
1342 styleObject->setProperty("_q_stylestate", int(option->state));
1343 styleObject->setProperty("_q_stylerect", option->rect);
1344
1345 bool doTransition = oldState &&
1346 ((state & State_Sunken) != (oldState & State_Sunken) ||
1347 (state & State_On) != (oldState & State_On) ||
1348 (state & State_MouseOver) != (oldState & State_MouseOver));
1349
1350 if (oldRect != newRect ||
1351 (state & State_Enabled) != (oldState & State_Enabled) ||
1352 (state & State_Active) != (oldState & State_Active))
1353 d->stopAnimation(styleObject);
1354
1355 if (state & State_ReadOnly && element == PE_FrameLineEdit) // Do not animate read only line edits
1356 doTransition = false;
1357
1358 if (doTransition) {
1360 styleOption->state = QStyle::State(oldState);
1361
1362 QWindowsVistaAnimation *animate = qobject_cast<QWindowsVistaAnimation *>(d->animation(styleObject));
1364
1365 // We create separate images for the initial and final transition states and store them in the
1366 // Transition object.
1368 QPainter startPainter(&startImage);
1369
1371 QPainter endPainter(&endImage);
1372
1373 // If we have a running animation on the widget already, we will use that to paint the initial
1374 // state of the new transition, this ensures a smooth transition from a current animation such as a
1375 // pulsating default button into the intended target state.
1376 if (!animate)
1377 proxy()->drawPrimitive(element, styleOption, &startPainter, widget);
1378 else
1379 animate->paint(&startPainter, styleOption);
1380
1381 transition->setStartImage(startImage);
1382
1383 // The end state of the transition is simply the result we would have painted
1384 // if the style was not animated.
1385 styleOption->styleObject = nullptr;
1386 styleOption->state = option->state;
1387 proxy()->drawPrimitive(element, styleOption, &endPainter, widget);
1388
1389 transition->setEndImage(endImage);
1390
1391 HTHEME theme;
1392 int partId;
1393 DWORD duration;
1394 int fromState = 0;
1395 int toState = 0;
1396
1397 //translate state flags to UXTHEME states :
1398 if (element == PE_FrameLineEdit) {
1399 theme = OpenThemeData(nullptr, L"Edit");
1400 partId = EP_EDITBORDER_NOSCROLL;
1401
1402 if (oldState & State_HasFocus)
1403 fromState = ETS_SELECTED;
1404 else if (oldState & State_MouseOver)
1405 fromState = ETS_HOT;
1406 else
1407 fromState = ETS_NORMAL;
1408
1409 if (state & State_HasFocus)
1410 toState = ETS_SELECTED;
1411 else if (state & State_MouseOver)
1412 toState = ETS_HOT;
1413 else
1414 toState = ETS_NORMAL;
1415
1416 } else {
1417 theme = OpenThemeData(nullptr, L"Button");
1418 if (element == PE_IndicatorRadioButton)
1419 partId = BP_RADIOBUTTON;
1420 else if (element == PE_IndicatorCheckBox)
1421 partId = BP_CHECKBOX;
1422 else
1423 partId = BP_PUSHBUTTON;
1424
1425 fromState = buttonStateId(oldState, partId);
1426 toState = buttonStateId(option->state, partId);
1427 }
1428
1429 // Retrieve the transition time between the states from the system.
1430 if (theme
1431 && SUCCEEDED(GetThemeTransitionDuration(theme, partId, fromState, toState,
1432 TMT_TRANSITIONDURATIONS, &duration))) {
1433 transition->setDuration(int(duration));
1434 }
1435 transition->setStartTime(d->animationTime());
1436
1438 d->startAnimation(transition);
1439 }
1440 styleObject->setProperty("_q_no_animation", false);
1441 }
1442 }
1443
1444 int themeNumber = -1;
1445 int partId = 0;
1446 int stateId = 0;
1447 bool hMirrored = false;
1448 bool vMirrored = false;
1449 bool noBorder = false;
1450 bool noContent = false;
1451 int rotate = 0;
1452
1453 switch (element) {
1454 case PE_PanelButtonCommand:
1455 if (const auto *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) {
1456 QBrush fill;
1457 if (!(state & State_Sunken) && (state & State_On))
1458 fill = QBrush(option->palette.light().color(), Qt::Dense4Pattern);
1459 else
1460 fill = option->palette.brush(QPalette::Button);
1461 if (btn->features & QStyleOptionButton::DefaultButton && state & State_Sunken) {
1462 painter->setPen(option->palette.dark().color());
1464 painter->drawRect(rect.adjusted(0, 0, -1, -1));
1465 } else if (state & (State_Raised | State_On | State_Sunken)) {
1466 qDrawWinButton(painter, rect, option->palette, state & (State_Sunken | State_On),
1467 &fill);
1468 } else {
1470 }
1471 }
1472 break;
1473
1474 case PE_PanelButtonTool:
1475#if QT_CONFIG(dockwidget)
1476 if (widget && widget->inherits("QDockWidgetTitleButton")) {
1477 if (const QWidget *dw = widget->parentWidget())
1478 if (dw->isWindow()) {
1479 return;
1480 }
1481 }
1482#endif // QT_CONFIG(dockwidget)
1484 partId = TP_BUTTON;
1485 if (!(option->state & State_Enabled))
1486 stateId = TS_DISABLED;
1487 else if (option->state & State_Sunken)
1488 stateId = TS_PRESSED;
1489 else if (option->state & State_MouseOver)
1490 stateId = option->state & State_On ? TS_HOTCHECKED : TS_HOT;
1491 else if (option->state & State_On)
1492 stateId = TS_CHECKED;
1493 else if (!(option->state & State_AutoRaise))
1494 stateId = TS_HOT;
1495 else
1496 stateId = TS_NORMAL;
1497
1498 break;
1499
1500 case PE_IndicatorHeaderArrow:
1501 if (const auto *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) {
1502 int stateId = HSAS_SORTEDDOWN;
1503 if (header->sortIndicator & QStyleOptionHeader::SortDown)
1504 stateId = HSAS_SORTEDUP; //note that the uxtheme sort down indicator is the inverse of ours
1507 HP_HEADERSORTARROW, stateId, option->rect);
1508 d->drawBackground(theme);
1509 return;
1510 }
1511 break;
1512
1513 case PE_IndicatorCheckBox:
1514 if (auto *animate =
1515 qobject_cast<QWindowsVistaAnimation *>(d->animation(styleObject(option)))) {
1516 animate->paint(painter, option);
1517 return;
1518 } else {
1520 partId = BP_CHECKBOX;
1521
1522 if (!(option->state & State_Enabled))
1523 stateId = CBS_UNCHECKEDDISABLED;
1524 else if (option->state & State_Sunken)
1525 stateId = CBS_UNCHECKEDPRESSED;
1526 else if (option->state & State_MouseOver)
1527 stateId = CBS_UNCHECKEDHOT;
1528 else
1529 stateId = CBS_UNCHECKEDNORMAL;
1530
1531 if (option->state & State_On)
1532 stateId += CBS_CHECKEDNORMAL-1;
1533 else if (option->state & State_NoChange)
1534 stateId += CBS_MIXEDNORMAL-1;
1535 }
1536 break;
1537
1538 case PE_IndicatorItemViewItemCheck: {
1540 button.QStyleOption::operator=(*option);
1541 button.state &= ~State_MouseOver;
1542 proxy()->drawPrimitive(PE_IndicatorCheckBox, &button, painter, widget);
1543 return;
1544 }
1545
1546 case PE_IndicatorBranch: {
1548 static int decoration_size = 0;
1549 if (!decoration_size && theme.isValid()) {
1550 QWindowsThemeData themeSize = theme;
1551 themeSize.partId = TVP_HOTGLYPH;
1552 themeSize.stateId = GLPS_OPENED;
1553 const QSizeF size = themeSize.size() * QWindowsStylePrivate::nativeMetricScaleFactor(widget);
1554 decoration_size = qRound(qMax(size.width(), size.height()));
1555 }
1556 int mid_h = option->rect.x() + option->rect.width() / 2;
1557 int mid_v = option->rect.y() + option->rect.height() / 2;
1558 if (option->state & State_Children) {
1559 int delta = decoration_size / 2;
1560 theme.rect = QRect(mid_h - delta, mid_v - delta, decoration_size, decoration_size);
1561 theme.partId = option->state & State_MouseOver ? TVP_HOTGLYPH : TVP_GLYPH;
1562 theme.stateId = option->state & QStyle::State_Open ? GLPS_OPENED : GLPS_CLOSED;
1563 if (option->direction == Qt::RightToLeft)
1564 theme.mirrorHorizontally = true;
1565 d->drawBackground(theme);
1566 }
1567 return;
1568 }
1569
1570 case PE_PanelButtonBevel:
1571 if (QWindowsVistaAnimation *animate =
1572 qobject_cast<QWindowsVistaAnimation *>(d->animation(styleObject(option)))) {
1573 animate->paint(painter, option);
1574 return;
1575 }
1576
1578 partId = BP_PUSHBUTTON;
1579 if (!(option->state & State_Enabled))
1580 stateId = PBS_DISABLED;
1581 else if ((option->state & State_Sunken) || (option->state & State_On))
1582 stateId = PBS_PRESSED;
1583 else if (option->state & State_MouseOver)
1584 stateId = PBS_HOT;
1585 else
1586 stateId = PBS_NORMAL;
1587 break;
1588
1589 case PE_IndicatorRadioButton:
1590 if (QWindowsVistaAnimation *animate =
1591 qobject_cast<QWindowsVistaAnimation *>(d->animation(styleObject(option)))) {
1592 animate->paint(painter, option);
1593 return;
1594 } else {
1596 partId = BP_RADIOBUTTON;
1597
1598 if (!(option->state & State_Enabled))
1599 stateId = RBS_UNCHECKEDDISABLED;
1600 else if (option->state & State_Sunken)
1601 stateId = RBS_UNCHECKEDPRESSED;
1602 else if (option->state & State_MouseOver)
1603 stateId = RBS_UNCHECKEDHOT;
1604 else
1605 stateId = RBS_UNCHECKEDNORMAL;
1606
1607 if (option->state & State_On)
1608 stateId += RBS_CHECKEDNORMAL-1;
1609 }
1610 break;
1611
1612 case PE_Frame:
1613#if QT_CONFIG(accessibility)
1614 if (QStyleHelper::isInstanceOf(option->styleObject, QAccessible::EditableText)
1615 || QStyleHelper::isInstanceOf(option->styleObject, QAccessible::StaticText) ||
1616#else
1617 if (
1618#endif
1619 (widget && widget->inherits("QTextEdit"))) {
1620 painter->save();
1621 int stateId = ETS_NORMAL;
1622 if (!(state & State_Enabled))
1623 stateId = ETS_DISABLED;
1624 else if (state & State_ReadOnly)
1625 stateId = ETS_READONLY;
1626 else if (state & State_HasFocus)
1627 stateId = ETS_SELECTED;
1628 QWindowsThemeData theme(widget, painter,
1629 QWindowsVistaStylePrivate::EditTheme,
1630 EP_EDITBORDER_HVSCROLL, stateId, option->rect);
1631 // Since EP_EDITBORDER_HVSCROLL does not us borderfill, theme.noContent cannot be used for clipping
1632 int borderSize = 1;
1633 GetThemeInt(theme.handle(), theme.partId, theme.stateId, TMT_BORDERSIZE, &borderSize);
1634 QRegion clipRegion = option->rect;
1635 QRegion content = option->rect.adjusted(borderSize, borderSize, -borderSize, -borderSize);
1636 clipRegion ^= content;
1637 painter->setClipRegion(clipRegion);
1638 d->drawBackground(theme);
1639 painter->restore();
1640 return;
1641 } else {
1642 if (option->state & State_Raised)
1643 return;
1644
1645 themeNumber = QWindowsVistaStylePrivate::ListViewTheme;
1646 partId = LVP_LISTGROUP;
1647 QWindowsThemeData theme(widget, nullptr, themeNumber, partId);
1648
1649 if (!(option->state & State_Enabled))
1650 stateId = ETS_DISABLED;
1651 else
1652 stateId = ETS_NORMAL;
1653
1654 int fillType;
1655
1656 if (GetThemeEnumValue(theme.handle(), partId, stateId, TMT_BGTYPE, &fillType) == S_OK) {
1657 if (fillType == BT_BORDERFILL) {
1658 COLORREF bcRef;
1659 GetThemeColor(theme.handle(), partId, stateId, TMT_BORDERCOLOR, &bcRef);
1660 QColor bordercolor(qRgb(GetRValue(bcRef), GetGValue(bcRef), GetBValue(bcRef)));
1661 QPen oldPen = painter->pen();
1662
1663 // Inner white border
1664 painter->setPen(QPen(option->palette.base().color(), 0));
1665 const qreal dpi = QStyleHelper::dpi(option);
1666 const auto topLevelAdjustment = QStyleHelper::dpiScaled(0.5, dpi);
1667 const auto bottomRightAdjustment = QStyleHelper::dpiScaled(-1, dpi);
1668 painter->drawRect(QRectF(option->rect).adjusted(topLevelAdjustment, topLevelAdjustment,
1669 bottomRightAdjustment, bottomRightAdjustment));
1670 // Outer dark border
1671 painter->setPen(QPen(bordercolor, 0));
1672 painter->drawRect(QRectF(option->rect).adjusted(0, 0, -topLevelAdjustment, -topLevelAdjustment));
1673 painter->setPen(oldPen);
1674 }
1675
1676 if (fillType == BT_BORDERFILL || fillType == BT_NONE)
1677 return;
1678 }
1679 }
1680 break;
1681
1682 case PE_FrameMenu: {
1683 int stateId = option->state & State_Active ? MB_ACTIVE : MB_INACTIVE;
1686 MENU_POPUPBORDERS, stateId, option->rect);
1687 d->drawBackground(theme);
1688 return;
1689 }
1690
1691 case PE_PanelMenuBar:
1692 break;
1693
1694#if QT_CONFIG(dockwidget)
1695 case PE_IndicatorDockWidgetResizeHandle:
1696 return;
1697
1698 case PE_FrameDockWidget:
1699 if (const auto *frm = qstyleoption_cast<const QStyleOptionFrame *>(option)) {
1701 if (option->state & State_Active)
1702 stateId = FS_ACTIVE;
1703 else
1704 stateId = FS_INACTIVE;
1705
1706 int fwidth = proxy()->pixelMetric(PM_DockWidgetFrameWidth, frm, widget);
1707
1708 QWindowsThemeData theme(widget, painter, themeNumber, 0, stateId);
1709
1710 if (!theme.isValid())
1711 break;
1712
1713 theme.rect = QRect(frm->rect.x(), frm->rect.y(), frm->rect.x()+fwidth, frm->rect.height()-fwidth);
1714 theme.partId = WP_SMALLFRAMELEFT;
1715 d->drawBackground(theme);
1716 theme.rect = QRect(frm->rect.width()-fwidth, frm->rect.y(), fwidth, frm->rect.height()-fwidth);
1717 theme.partId = WP_SMALLFRAMERIGHT;
1718 d->drawBackground(theme);
1719 theme.rect = QRect(frm->rect.x(), frm->rect.bottom()-fwidth+1, frm->rect.width(), fwidth);
1720 theme.partId = WP_SMALLFRAMEBOTTOM;
1721 d->drawBackground(theme);
1722 return;
1723 }
1724 break;
1725#endif // QT_CONFIG(dockwidget)
1726
1727 case PE_FrameTabWidget:
1728 if (const auto *tab = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(option)) {
1730 partId = TABP_PANE;
1731
1732 if (widget) {
1733 bool useGradient = true;
1734 const int maxlength = 256;
1735 wchar_t themeFileName[maxlength];
1736 wchar_t themeColor[maxlength];
1737 // Due to a a scaling issue with the XP Silver theme, tab gradients are not used with it
1738 if (GetCurrentThemeName(themeFileName, maxlength, themeColor, maxlength, nullptr, 0) == S_OK) {
1739 wchar_t *offset = nullptr;
1740 if ((offset = wcsrchr(themeFileName, QChar(QLatin1Char('\\')).unicode())) != nullptr) {
1741 offset++;
1742 if (!lstrcmp(offset, L"Luna.msstyles") && !lstrcmp(offset, L"Metallic"))
1743 useGradient = false;
1744 }
1745 }
1746 // This should work, but currently there's an error in the ::drawBackgroundDirectly()
1747 // code, when using the HDC directly..
1748 if (useGradient) {
1749 QStyleOptionTabWidgetFrame frameOpt = *tab;
1750 frameOpt.rect = widget->rect();
1751 QRect contentsRect = subElementRect(SE_TabWidgetTabContents, &frameOpt, widget);
1752 QRegion reg = option->rect;
1753 reg -= contentsRect;
1754 painter->setClipRegion(reg);
1755 QWindowsThemeData theme(widget, painter, themeNumber, partId, stateId, rect);
1756 theme.mirrorHorizontally = hMirrored;
1757 theme.mirrorVertically = vMirrored;
1758 d->drawBackground(theme);
1759 painter->setClipRect(contentsRect);
1760 partId = TABP_BODY;
1761 }
1762 }
1763 switch (tab->shape) {
1766 break;
1769 vMirrored = true;
1770 break;
1773 rotate = 90;
1774 break;
1777 rotate = 90;
1778 hMirrored = true;
1779 break;
1780 default:
1781 break;
1782 }
1783 }
1784 break;
1785
1786 case PE_FrameStatusBarItem:
1788 partId = SP_PANE;
1789 break;
1790
1791 case PE_FrameWindow:
1792 if (const auto *frm = qstyleoption_cast<const QStyleOptionFrame *>(option)) {
1794 if (option->state & State_Active)
1795 stateId = FS_ACTIVE;
1796 else
1797 stateId = FS_INACTIVE;
1798
1799 int fwidth = int((frm->lineWidth + frm->midLineWidth) / QWindowsStylePrivate::nativeMetricScaleFactor(widget));
1800
1801 QWindowsThemeData theme(widget, painter, themeNumber, 0, stateId);
1802 if (!theme.isValid())
1803 break;
1804
1805 // May fail due to too-large buffers for large widgets, fall back to Windows style.
1806 theme.rect = QRect(option->rect.x(), option->rect.y()+fwidth, option->rect.x()+fwidth, option->rect.height()-fwidth);
1807 theme.partId = WP_FRAMELEFT;
1808 if (!d->drawBackground(theme)) {
1809 QWindowsStyle::drawPrimitive(element, option, painter, widget);
1810 return;
1811 }
1812 theme.rect = QRect(option->rect.width()-fwidth, option->rect.y()+fwidth, fwidth, option->rect.height()-fwidth);
1813 theme.partId = WP_FRAMERIGHT;
1814 if (!d->drawBackground(theme)) {
1815 QWindowsStyle::drawPrimitive(element, option, painter, widget);
1816 return;
1817 }
1818 theme.rect = QRect(option->rect.x(), option->rect.height()-fwidth, option->rect.width(), fwidth);
1819 theme.partId = WP_FRAMEBOTTOM;
1820 if (!d->drawBackground(theme)) {
1821 QWindowsStyle::drawPrimitive(element, option, painter, widget);
1822 return;
1823 }
1824 theme.rect = QRect(option->rect.x(), option->rect.y(), option->rect.width(), option->rect.y()+fwidth);
1825 theme.partId = WP_CAPTION;
1826 if (!d->drawBackground(theme))
1827 QWindowsStyle::drawPrimitive(element, option, painter, widget);
1828 return;
1829 }
1830 break;
1831
1832 case PE_PanelLineEdit:
1833 if (const auto *panel = qstyleoption_cast<const QStyleOptionFrame *>(option)) {
1834 bool isEnabled = state & State_Enabled;
1837 } else {
1838 int partId = EP_BACKGROUND;
1839 int stateId = EBS_NORMAL;
1840 if (!isEnabled)
1841 stateId = EBS_DISABLED;
1842 else if (option->state & State_ReadOnly)
1843 stateId = EBS_READONLY;
1844 else if (option->state & State_MouseOver)
1845 stateId = EBS_HOT;
1846
1848 partId, stateId, rect);
1849 if (!theme.isValid()) {
1850 QWindowsStyle::drawPrimitive(element, option, painter, widget);
1851 return;
1852 }
1853 int bgType;
1854 GetThemeEnumValue(theme.handle(), partId, stateId, TMT_BGTYPE, &bgType);
1855 if (bgType == BT_IMAGEFILE) {
1856 d->drawBackground(theme);
1857 } else {
1858 QBrush fillColor = option->palette.brush(QPalette::Base);
1859 if (!isEnabled) {
1860 PROPERTYORIGIN origin = PO_NOTFOUND;
1861 GetThemePropertyOrigin(theme.handle(), theme.partId, theme.stateId, TMT_FILLCOLOR, &origin);
1862 // Use only if the fill property comes from our part
1863 if ((origin == PO_PART || origin == PO_STATE)) {
1864 COLORREF bgRef;
1865 GetThemeColor(theme.handle(), partId, stateId, TMT_FILLCOLOR, &bgRef);
1866 fillColor = QBrush(qRgb(GetRValue(bgRef), GetGValue(bgRef), GetBValue(bgRef)));
1867 }
1868 }
1869 painter->fillRect(option->rect, fillColor);
1870 }
1871 }
1872 if (panel->lineWidth > 0)
1873 proxy()->drawPrimitive(PE_FrameLineEdit, panel, painter, widget);
1874 }
1875 return;
1876
1877 case PE_IndicatorButtonDropDown:
1879 partId = TP_SPLITBUTTONDROPDOWN;
1880 if (!(option->state & State_Enabled))
1881 stateId = TS_DISABLED;
1882 else if (option->state & State_Sunken)
1883 stateId = TS_PRESSED;
1884 else if (option->state & State_MouseOver)
1885 stateId = option->state & State_On ? TS_HOTCHECKED : TS_HOT;
1886 else if (option->state & State_On)
1887 stateId = TS_CHECKED;
1888 else if (!(option->state & State_AutoRaise))
1889 stateId = TS_HOT;
1890 else
1891 stateId = TS_NORMAL;
1892 if (option->direction == Qt::RightToLeft)
1893 hMirrored = true;
1894 break;
1895
1896 case PE_FrameLineEdit:
1897 if (QWindowsVistaAnimation *animate = qobject_cast<QWindowsVistaAnimation *>(d->animation(styleObject(option)))) {
1898 animate->paint(painter, option);
1899 } else {
1901 // we try to check if this lineedit is a delegate on a QAbstractItemView-derived class.
1902 QPen oldPen = painter->pen();
1903 // Inner white border
1904 painter->setPen(QPen(option->palette.base().color(), 1));
1905 painter->drawRect(option->rect.adjusted(1, 1, -2, -2));
1906 // Outer dark border
1907 painter->setPen(QPen(option->palette.shadow().color(), 1));
1908 painter->drawRect(option->rect.adjusted(0, 0, -1, -1));
1909 painter->setPen(oldPen);
1910 return;
1911 }
1912 int stateId = ETS_NORMAL;
1913 if (!(state & State_Enabled))
1914 stateId = ETS_DISABLED;
1915 else if (state & State_ReadOnly)
1916 stateId = ETS_READONLY;
1917 else if (state & State_HasFocus)
1918 stateId = ETS_SELECTED;
1919 else if (state & State_MouseOver)
1920 stateId = ETS_HOT;
1923 EP_EDITBORDER_NOSCROLL, stateId, option->rect);
1924 theme.noContent = true;
1925 painter->save();
1926 QRegion clipRegion = option->rect;
1927 clipRegion -= option->rect.adjusted(2, 2, -2, -2);
1928 painter->setClipRegion(clipRegion);
1929 d->drawBackground(theme);
1930 painter->restore();
1931 }
1932 return;
1933
1934 case PE_FrameGroupBox:
1936 partId = BP_GROUPBOX;
1937 if (!(option->state & State_Enabled))
1938 stateId = GBS_DISABLED;
1939 else
1940 stateId = GBS_NORMAL;
1941 if (const auto *frame = qstyleoption_cast<const QStyleOptionFrame *>(option)) {
1942 if (frame->features & QStyleOptionFrame::Flat) {
1943 // Windows XP does not have a theme part for a flat GroupBox, paint it with the windows style
1944 QRect fr = frame->rect;
1945 QPoint p1(fr.x(), fr.y() + 1);
1946 QPoint p2(fr.x() + fr.width(), p1.y() + 1);
1947 rect = QRect(p1, p2);
1948 themeNumber = -1;
1949 }
1950 }
1951 break;
1952
1953 case PE_IndicatorToolBarHandle: {
1954 QWindowsThemeData theme;
1955 QRect rect;
1956 if (option->state & State_Horizontal) {
1959 RP_GRIPPER, ETS_NORMAL, option->rect.adjusted(0, 1, -2, -2));
1960 rect = option->rect.adjusted(0, 1, 0, -2);
1961 rect.setWidth(4);
1962 } else {
1964 RP_GRIPPERVERT, ETS_NORMAL, option->rect.adjusted(0, 1, -2, -2));
1965 rect = option->rect.adjusted(1, 0, -1, 0);
1966 rect.setHeight(4);
1967 }
1968 theme.rect = rect;
1969 d->drawBackground(theme);
1970 return;
1971 }
1972
1973 case PE_IndicatorToolBarSeparator: {
1974 QPen pen = painter->pen();
1975 int margin = 3;
1976 painter->setPen(option->palette.window().color().darker(114));
1977 if (option->state & State_Horizontal) {
1978 int x1 = option->rect.center().x();
1979 painter->drawLine(QPoint(x1, option->rect.top() + margin), QPoint(x1, option->rect.bottom() - margin));
1980 } else {
1981 int y1 = option->rect.center().y();
1982 painter->drawLine(QPoint(option->rect.left() + margin, y1), QPoint(option->rect.right() - margin, y1));
1983 }
1984 painter->setPen(pen);
1985 return;
1986 }
1987
1988 case PE_PanelTipLabel: {
1991 TTP_STANDARD, TTSS_NORMAL, option->rect);
1992 d->drawBackground(theme);
1993 return;
1994 }
1995
1996 case PE_FrameTabBarBase:
1997 if (const auto *tbb = qstyleoption_cast<const QStyleOptionTabBarBase *>(option)) {
1998 painter->save();
1999 switch (tbb->shape) {
2001 painter->setPen(QPen(tbb->palette.dark(), 0));
2002 painter->drawLine(tbb->rect.topLeft(), tbb->rect.topRight());
2003 break;
2005 painter->setPen(QPen(tbb->palette.dark(), 0));
2006 painter->drawLine(tbb->rect.left(), tbb->rect.top(), tbb->rect.left(), tbb->rect.bottom());
2007 break;
2009 painter->setPen(QPen(tbb->palette.dark(), 0));
2010 painter->drawLine(tbb->rect.left(), tbb->rect.top(),
2011 tbb->rect.right(), tbb->rect.top());
2012 break;
2014 painter->setPen(QPen(tbb->palette.dark(), 0));
2015 painter->drawLine(tbb->rect.topLeft(), tbb->rect.bottomLeft());
2016 break;
2021 painter->restore();
2022 QWindowsStyle::drawPrimitive(element, option, painter, widget);
2023 return;
2024 }
2025 painter->restore();
2026 }
2027 return;
2028
2029 case PE_Widget: {
2030#if QT_CONFIG(dialogbuttonbox)
2031 const QDialogButtonBox *buttonBox = nullptr;
2032 if (qobject_cast<const QMessageBox *> (widget))
2033 buttonBox = widget->findChild<const QDialogButtonBox *>(QLatin1String("qt_msgbox_buttonbox"));
2034#if QT_CONFIG(inputdialog)
2035 else if (qobject_cast<const QInputDialog *> (widget))
2036 buttonBox = widget->findChild<const QDialogButtonBox *>(QLatin1String("qt_inputdlg_buttonbox"));
2037#endif // QT_CONFIG(inputdialog)
2038 if (buttonBox) {
2039 //draw white panel part
2042 TDLG_PRIMARYPANEL, 0, option->rect);
2043 QRect toprect = option->rect;
2044 toprect.setBottom(buttonBox->geometry().top());
2045 theme.rect = toprect;
2046 d->drawBackground(theme);
2047
2048 //draw bottom panel part
2049 QRect buttonRect = option->rect;
2050 buttonRect.setTop(buttonBox->geometry().top());
2051 theme.rect = buttonRect;
2052 theme.partId = TDLG_SECONDARYPANEL;
2053 d->drawBackground(theme);
2054 }
2055#endif
2056 return;
2057 }
2058
2059 case PE_PanelItemViewItem: {
2060 const QStyleOptionViewItem *vopt;
2061 bool newStyle = true;
2064 if (const QAbstractItemView *view = qobject_cast<const QAbstractItemView *>(widget)) {
2065 newStyle = !qobject_cast<const QTableView*>(view);
2066 selectionBehavior = view->selectionBehavior();
2067 selectionMode = view->selectionMode();
2068#if QT_CONFIG(accessibility)
2069 } else if (!widget) {
2070 newStyle = !QStyleHelper::hasAncestor(option->styleObject, QAccessible::MenuItem) ;
2071#endif
2072 }
2073
2074 if (newStyle && (vopt = qstyleoption_cast<const QStyleOptionViewItem *>(option))) {
2075 bool selected = vopt->state & QStyle::State_Selected;
2076 const bool hover = selectionMode != QAbstractItemView::NoSelection && (vopt->state & QStyle::State_MouseOver);
2077 bool active = vopt->state & QStyle::State_Active;
2078
2079 if (vopt->features & QStyleOptionViewItem::Alternate)
2080 painter->fillRect(vopt->rect, vopt->palette.alternateBase());
2081
2084 if (cg == QPalette::Normal && !(vopt->state & QStyle::State_Active))
2085 cg = QPalette::Inactive;
2086
2088 itemRect.setTop(vopt->rect.top());
2089 itemRect.setBottom(vopt->rect.bottom());
2090
2091 QSize sectionSize = itemRect.size();
2092 if (vopt->showDecorationSelected)
2093 sectionSize = vopt->rect.size();
2094
2095 if (selectionBehavior == QAbstractItemView::SelectRows)
2096 sectionSize.setWidth(vopt->rect.width());
2098
2099 if (vopt->backgroundBrush.style() != Qt::NoBrush) {
2100 const QPointF oldBrushOrigin = painter->brushOrigin();
2101 painter->setBrushOrigin(vopt->rect.topLeft());
2102 painter->fillRect(vopt->rect, vopt->backgroundBrush);
2103 painter->setBrushOrigin(oldBrushOrigin);
2104 }
2105
2106 if (hover || selected) {
2107 if (sectionSize.width() > 0 && sectionSize.height() > 0) {
2108 QString key = QString::fromLatin1("qvdelegate-%1-%2-%3-%4-%5").arg(sectionSize.width())
2109 .arg(sectionSize.height()).arg(selected).arg(active).arg(hover);
2110 if (!QPixmapCache::find(key, &pixmap)) {
2111 pixmap = QPixmap(sectionSize);
2112 pixmap.fill(Qt::transparent);
2113
2114 int state;
2115 if (selected && hover)
2117 else if (selected && !active)
2119 else if (selected)
2121 else
2122 state = LISS_HOT;
2123
2124 QPainter pixmapPainter(&pixmap);
2125
2126 QWindowsThemeData theme(widget, &pixmapPainter,
2128 LVP_LISTITEM, state, QRect(0, 0, sectionSize.width(), sectionSize.height()));
2129
2130 if (!theme.isValid())
2131 break;
2132
2133 d->drawBackground(theme);
2135 }
2136 }
2137
2138 if (vopt->showDecorationSelected) {
2139 const int frame = 2; //Assumes a 2 pixel pixmap border
2140 QRect srcRect = QRect(0, 0, sectionSize.width(), sectionSize.height());
2141 QRect pixmapRect = vopt->rect;
2142 bool reverse = vopt->direction == Qt::RightToLeft;
2143 bool leftSection = vopt->viewItemPosition == QStyleOptionViewItem::Beginning;
2144 bool rightSection = vopt->viewItemPosition == QStyleOptionViewItem::End;
2145 if (vopt->viewItemPosition == QStyleOptionViewItem::OnlyOne
2146 || vopt->viewItemPosition == QStyleOptionViewItem::Invalid)
2147 painter->drawPixmap(pixmapRect.topLeft(), pixmap);
2148 else if (reverse ? rightSection : leftSection){
2149 painter->drawPixmap(QRect(pixmapRect.topLeft(),
2150 QSize(frame, pixmapRect.height())), pixmap,
2151 QRect(QPoint(0, 0), QSize(frame, pixmapRect.height())));
2152 painter->drawPixmap(pixmapRect.adjusted(frame, 0, 0, 0),
2153 pixmap, srcRect.adjusted(frame, 0, -frame, 0));
2154 } else if (reverse ? leftSection : rightSection) {
2155 painter->drawPixmap(QRect(pixmapRect.topRight() - QPoint(frame - 1, 0),
2156 QSize(frame, pixmapRect.height())), pixmap,
2157 QRect(QPoint(pixmapRect.width() - frame, 0),
2158 QSize(frame, pixmapRect.height())));
2159 painter->drawPixmap(pixmapRect.adjusted(0, 0, -frame, 0),
2160 pixmap, srcRect.adjusted(frame, 0, -frame, 0));
2161 } else if (vopt->viewItemPosition == QStyleOptionViewItem::Middle)
2162 painter->drawPixmap(pixmapRect, pixmap,
2163 srcRect.adjusted(frame, 0, -frame, 0));
2164 } else {
2165 if (vopt->text.isEmpty() && vopt->icon.isNull())
2166 break;
2167 painter->drawPixmap(itemRect.topLeft(), pixmap);
2168 }
2169 }
2170 return;
2171 }
2172 break;
2173 }
2174
2175 default:
2176 break;
2177 }
2178
2179 QWindowsThemeData theme(widget, painter, themeNumber, partId, stateId, rect);
2180
2181 if (!theme.isValid()) {
2182 QWindowsStyle::drawPrimitive(element, option, painter, widget);
2183 return;
2184 }
2185
2186 theme.mirrorHorizontally = hMirrored;
2187 theme.mirrorVertically = vMirrored;
2188 theme.noBorder = noBorder;
2189 theme.noContent = noContent;
2190 theme.rotate = rotate;
2191
2192 d->drawBackground(theme);
2193}
2194
2197 QStyleHintReturn *returnData) const
2198{
2199 QWindowsVistaStylePrivate *d = const_cast<QWindowsVistaStylePrivate*>(d_func());
2200
2201 int ret = 0;
2202 switch (hint) {
2203 case SH_EtchDisabledText:
2204 ret = (qobject_cast<const QLabel*>(widget) != 0);
2205 break;
2206
2207 case SH_SpinControls_DisableOnBounds:
2208 ret = 0;
2209 break;
2210
2211 case SH_TitleBar_AutoRaise:
2212 case SH_TitleBar_NoBorder:
2213 ret = 1;
2214 break;
2215
2216 case SH_GroupBox_TextLabelColor:
2217 if (!widget || widget->isEnabled())
2219 else
2220 ret = d->groupBoxTextColorDisabled;
2221 break;
2222
2223 case SH_WindowFrame_Mask: {
2224 ret = 1;
2225 auto *mask = qstyleoption_cast<QStyleHintReturnMask *>(returnData);
2226 const auto *titlebar = qstyleoption_cast<const QStyleOptionTitleBar *>(option);
2227 if (mask && titlebar) {
2228 // Note certain themes will not return the whole window frame but only the titlebar part when
2229 // queried This function needs to return the entire window mask, hence we will only fetch the mask for the
2230 // titlebar itself and add the remaining part of the window rect at the bottom.
2231 int tbHeight = proxy()->pixelMetric(PM_TitleBarHeight, option, widget);
2232 QRect titleBarRect = option->rect;
2233 titleBarRect.setHeight(tbHeight);
2234 QWindowsThemeData themeData;
2235 if (titlebar->titleBarState & Qt::WindowMinimized) {
2236 themeData = QWindowsThemeData(widget, nullptr,
2238 WP_MINCAPTION, CS_ACTIVE, titleBarRect);
2239 } else
2240 themeData = QWindowsThemeData(widget, nullptr,
2242 WP_CAPTION, CS_ACTIVE, titleBarRect);
2243 mask->region = d->region(themeData) +
2244 QRect(0, tbHeight, option->rect.width(), option->rect.height() - tbHeight);
2245 }
2246 break;
2247 }
2248
2249#if QT_CONFIG(rubberband)
2250 case SH_RubberBand_Mask:
2251 if (qstyleoption_cast<const QStyleOptionRubberBand *>(option))
2252 ret = 0;
2253 break;
2254#endif // QT_CONFIG(rubberband)
2255
2256 case SH_MessageBox_CenterButtons:
2257 ret = false;
2258 break;
2259
2260 case SH_ToolTip_Mask:
2261 if (option) {
2262 if (QStyleHintReturnMask *mask = qstyleoption_cast<QStyleHintReturnMask*>(returnData)) {
2263 ret = true;
2264 QWindowsThemeData themeData(widget, nullptr,
2266 TTP_STANDARD, TTSS_NORMAL, option->rect);
2267 mask->region = d->region(themeData);
2268 }
2269 }
2270 break;
2271
2272 case SH_Table_GridLineColor:
2273 if (option)
2274 ret = int(option->palette.color(QPalette::Base).darker(118).rgba());
2275 else
2276 ret = -1;
2277 break;
2278
2279 case SH_Header_ArrowAlignment:
2281 break;
2282
2283 case SH_ItemView_DrawDelegateFrame:
2284 ret = 1;
2285 break;
2286
2287 default:
2288 ret = QWindowsStyle::styleHint(hint, option, widget, returnData);
2289 break;
2290 }
2291
2292 return ret;
2293}
2294
2295
2301void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption *option,
2302 QPainter *painter, const QWidget *widget) const
2303{
2305 QWindowsStyle::drawControl(element, option, painter, widget);
2306 return;
2307 }
2308
2309 QWindowsVistaStylePrivate *d = const_cast<QWindowsVistaStylePrivate*>(d_func());
2310
2311 bool selected = option->state & State_Selected;
2312 bool pressed = option->state & State_Sunken;
2313 bool disabled = !(option->state & State_Enabled);
2314
2315 int state = option->state;
2316 int themeNumber = -1;
2317
2318 QRect rect(option->rect);
2319 State flags = option->state;
2320 int partId = 0;
2321 int stateId = 0;
2322
2323 if (d->transitionsEnabled() && canAnimate(option)) {
2324 if (element == CE_PushButtonBevel) {
2325 QRect oldRect;
2326 QRect newRect;
2327
2328 QObject *styleObject = option->styleObject;
2329
2330 int oldState = styleObject->property("_q_stylestate").toInt();
2331 oldRect = styleObject->property("_q_stylerect").toRect();
2332 newRect = option->rect;
2333 styleObject->setProperty("_q_stylestate", int(option->state));
2334 styleObject->setProperty("_q_stylerect", option->rect);
2335
2336 bool wasDefault = false;
2337 bool isDefault = false;
2338 if (const QStyleOptionButton *button = qstyleoption_cast<const QStyleOptionButton *>(option)) {
2339 wasDefault = styleObject->property("_q_isdefault").toBool();
2340 isDefault = button->features & QStyleOptionButton::DefaultButton;
2341 styleObject->setProperty("_q_isdefault", isDefault);
2342 }
2343
2344 bool doTransition = ((state & State_Sunken) != (oldState & State_Sunken) ||
2345 (state & State_On) != (oldState & State_On) ||
2346 (state & State_MouseOver) != (oldState & State_MouseOver));
2347
2348 if (oldRect != newRect || (wasDefault && !isDefault)) {
2349 doTransition = false;
2350 d->stopAnimation(styleObject);
2351 }
2352
2353 if (doTransition) {
2354 styleObject->setProperty("_q_no_animation", true);
2355
2357 QWindowsVistaAnimation *anim = qobject_cast<QWindowsVistaAnimation *>(d->animation(styleObject));
2359 styleOption->state = QStyle::State(oldState);
2360
2362 QPainter startPainter(&startImage);
2363
2364 // Use current state of existing animation if already one is running
2365 if (!anim) {
2366 proxy()->drawControl(element, styleOption, &startPainter, widget);
2367 } else {
2368 anim->paint(&startPainter, styleOption);
2369 d->stopAnimation(styleObject);
2370 }
2371
2372 t->setStartImage(startImage);
2374 QPainter endPainter(&endImage);
2375 styleOption->state = option->state;
2376 proxy()->drawControl(element, styleOption, &endPainter, widget);
2377 t->setEndImage(endImage);
2378
2379
2380 DWORD duration = 0;
2381 const HTHEME theme = OpenThemeData(nullptr, L"Button");
2382
2383 int fromState = buttonStateId(oldState, BP_PUSHBUTTON);
2384 int toState = buttonStateId(option->state, BP_PUSHBUTTON);
2385 if (GetThemeTransitionDuration(theme, BP_PUSHBUTTON, fromState, toState, TMT_TRANSITIONDURATIONS, &duration) == S_OK)
2386 t->setDuration(int(duration));
2387 else
2388 t->setDuration(0);
2389 t->setStartTime(d->animationTime());
2390 styleObject->setProperty("_q_no_animation", false);
2391
2393 d->startAnimation(t);
2394 }
2395
2396 QWindowsVistaAnimation *anim = qobject_cast<QWindowsVistaAnimation *>(d->animation(styleObject));
2397 if (anim) {
2398 anim->paint(painter, option);
2399 return;
2400 }
2401
2402 }
2403 }
2404
2405 bool hMirrored = false;
2406 bool vMirrored = false;
2407 int rotate = 0;
2408
2409 switch (element) {
2410 case CE_PushButtonBevel:
2411 if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) {
2413 partId = BP_PUSHBUTTON;
2415 partId = BP_COMMANDLINK;
2416 bool justFlat = (btn->features & QStyleOptionButton::Flat) && !(flags & (State_On|State_Sunken));
2417 if (!(flags & State_Enabled) && !(btn->features & QStyleOptionButton::Flat))
2418 stateId = PBS_DISABLED;
2419 else if (justFlat)
2420 ;
2421 else if (flags & (State_Sunken | State_On))
2422 stateId = PBS_PRESSED;
2423 else if (flags & State_MouseOver)
2424 stateId = PBS_HOT;
2425 else if (btn->features & QStyleOptionButton::DefaultButton && (state & State_Active))
2426 stateId = PBS_DEFAULTED;
2427 else
2428 stateId = PBS_NORMAL;
2429
2430 if (!justFlat) {
2431
2432 if (d->transitionsEnabled() && (btn->features & QStyleOptionButton::DefaultButton) &&
2433 !(state & (State_Sunken | State_On)) && !(state & State_MouseOver) &&
2434 (state & State_Enabled) && (state & State_Active))
2435 {
2436 QWindowsVistaAnimation *anim = qobject_cast<QWindowsVistaAnimation *>(d->animation(styleObject(option)));
2437
2438 if (!anim) {
2440 QImage alternateImage = createAnimationBuffer(option, widget);
2441
2443
2444 QPainter startPainter(&startImage);
2445 stateId = PBS_DEFAULTED;
2446 QWindowsThemeData theme(widget, &startPainter, themeNumber, partId, stateId, rect);
2447 d->drawBackground(theme);
2448
2449 QPainter alternatePainter(&alternateImage);
2450 theme.stateId = PBS_DEFAULTED_ANIMATING;
2451 theme.painter = &alternatePainter;
2452 d->drawBackground(theme);
2453
2454 pulse->setStartImage(startImage);
2455 pulse->setEndImage(alternateImage);
2456 pulse->setStartTime(d->animationTime());
2457 pulse->setDuration(2000);
2458 d->startAnimation(pulse);
2459 anim = pulse;
2460 }
2461
2462 if (anim)
2463 anim->paint(painter, option);
2464 else {
2465 QWindowsThemeData theme(widget, painter, themeNumber, partId, stateId, rect);
2466 d->drawBackground(theme);
2467 }
2468 }
2469 else {
2470 QWindowsThemeData theme(widget, painter, themeNumber, partId, stateId, rect);
2471 d->drawBackground(theme);
2472 }
2473 }
2474
2476 int mbiw = 0, mbih = 0;
2478 TP_DROPDOWNBUTTON);
2479 if (theme.isValid()) {
2480 const QSizeF size = theme.size() * QStyleHelper::dpiScaled(1, option);
2481 if (!size.isEmpty()) {
2482 mbiw = qRound(size.width());
2483 mbih = qRound(size.height());
2484 }
2485 }
2486 QRect ir = subElementRect(SE_PushButtonContents, option, nullptr);
2487 QStyleOptionButton newBtn = *btn;
2488 newBtn.rect = QStyle::visualRect(option->direction, option->rect,
2489 QRect(ir.right() - mbiw - 2,
2490 option->rect.top() + (option->rect.height()/2) - (mbih/2),
2491 mbiw + 1, mbih + 1));
2492 proxy()->drawPrimitive(PE_IndicatorArrowDown, &newBtn, painter, widget);
2493 }
2494 }
2495 return;
2496
2497 case CE_SizeGrip: {
2499 partId = SP_GRIPPER;
2500 QWindowsThemeData theme(nullptr, painter, themeNumber, partId);
2501 QSize size = (theme.size() * QWindowsStylePrivate::nativeMetricScaleFactor(widget)).toSize();
2502 size.rheight()--;
2503 if (const auto *sg = qstyleoption_cast<const QStyleOptionSizeGrip *>(option)) {
2504 switch (sg->corner) {
2506 rect = QRect(QPoint(rect.right() - size.width(), rect.bottom() - size.height()), size);
2507 break;
2509 rect = QRect(QPoint(rect.left() + 1, rect.bottom() - size.height()), size);
2510 hMirrored = true;
2511 break;
2512 case Qt::TopRightCorner:
2513 rect = QRect(QPoint(rect.right() - size.width(), rect.top() + 1), size);
2514 vMirrored = true;
2515 break;
2516 case Qt::TopLeftCorner:
2517 rect = QRect(rect.topLeft() + QPoint(1, 1), size);
2518 hMirrored = vMirrored = true;
2519 }
2520 }
2521 break;
2522 }
2523
2524 case CE_Splitter:
2525 painter->eraseRect(option->rect);
2526 return;
2527
2528 case CE_TabBarTab:
2529 if (const auto *tab = qstyleoption_cast<const QStyleOptionTab *>(option))
2530 stateId = tab->state & State_Enabled ? TIS_NORMAL : TIS_DISABLED;
2531 break;
2532
2533 case CE_TabBarTabShape:
2534 if (const auto *tab = qstyleoption_cast<const QStyleOptionTab *>(option)) {
2536 const bool isDisabled = !(tab->state & State_Enabled);
2537 const bool hasFocus = tab->state & State_HasFocus;
2538 const bool isHot = tab->state & State_MouseOver;
2539 const bool selected = tab->state & State_Selected;
2540 bool lastTab = tab->position == QStyleOptionTab::End;
2541 bool firstTab = tab->position == QStyleOptionTab::Beginning;
2542 const bool onlyOne = tab->position == QStyleOptionTab::OnlyOneTab;
2543 const bool leftAligned = proxy()->styleHint(SH_TabBar_Alignment, tab, widget) == Qt::AlignLeft;
2544 const bool centerAligned = proxy()->styleHint(SH_TabBar_Alignment, tab, widget) == Qt::AlignCenter;
2545 const int borderThickness = proxy()->pixelMetric(PM_DefaultFrameWidth, option, widget);
2546 const int tabOverlap = proxy()->pixelMetric(PM_TabBarTabOverlap, option, widget);
2547
2548 if (isDisabled)
2549 stateId = TIS_DISABLED;
2550 else if (selected)
2551 stateId = TIS_SELECTED;
2552 else if (hasFocus)
2553 stateId = TIS_FOCUSED;
2554 else if (isHot)
2555 stateId = TIS_HOT;
2556 else
2557 stateId = TIS_NORMAL;
2558
2559 // Selecting proper part depending on position
2560 if (firstTab || onlyOne) {
2561 if (leftAligned)
2562 partId = TABP_TABITEMLEFTEDGE;
2563 else if (centerAligned)
2564 partId = TABP_TABITEM;
2565 else // rightAligned
2566 partId = TABP_TABITEMRIGHTEDGE;
2567 } else {
2568 partId = TABP_TABITEM;
2569 }
2570
2571 if (tab->direction == Qt::RightToLeft
2572 && (tab->shape == QTabBar::RoundedNorth || tab->shape == QTabBar::RoundedSouth)) {
2573 bool temp = firstTab;
2574 firstTab = lastTab;
2575 lastTab = temp;
2576 }
2577
2578 const bool begin = firstTab || onlyOne;
2579 const bool end = lastTab || onlyOne;
2580
2581 switch (tab->shape) {
2583 if (selected)
2584 rect.adjust(begin ? 0 : -tabOverlap, 0, end ? 0 : tabOverlap, borderThickness);
2585 else
2586 rect.adjust(begin? tabOverlap : 0, tabOverlap, end ? -tabOverlap : 0, 0);
2587 break;
2589 //vMirrored = true;
2590 rotate = 180; // Not 100% correct, but works
2591 if (selected)
2592 rect.adjust(begin ? 0 : -tabOverlap , -borderThickness, end ? 0 : tabOverlap, 0);
2593 else
2594 rect.adjust(begin ? tabOverlap : 0, 0, end ? -tabOverlap : 0 , -tabOverlap);
2595 break;
2597 rotate = 90;
2598 if (selected)
2599 rect.adjust(-borderThickness, begin ? 0 : -tabOverlap, 0, end ? 0 : tabOverlap);
2600 else
2601 rect.adjust(0, begin ? tabOverlap : 0, -tabOverlap, end ? -tabOverlap : 0);
2602 break;
2604 hMirrored = true;
2605 rotate = 90;
2606 if (selected)
2607 rect.adjust(0, begin ? 0 : -tabOverlap, borderThickness, end ? 0 : tabOverlap);
2608 else
2609 rect.adjust(tabOverlap, begin ? tabOverlap : 0, 0, end ? -tabOverlap : 0);
2610 break;
2611 default:
2612 themeNumber = -1; // Do our own painting for triangular
2613 break;
2614 }
2615
2616 if (!selected) {
2617 switch (tab->shape) {
2619 rect.adjust(0,0, 0,-1);
2620 break;
2622 rect.adjust(0,1, 0,0);
2623 break;
2625 rect.adjust( 1,0, 0,0);
2626 break;
2628 rect.adjust(0,0, -1,0);
2629 break;
2630 default:
2631 break;
2632 }
2633 }
2634 }
2635 break;
2636
2637 case CE_ProgressBarGroove: {
2639 if (const auto *pb = qstyleoption_cast<const QStyleOptionProgressBar *>(option))
2640 if (!(pb->state & QStyle::State_Horizontal))
2641 orient = Qt::Vertical;
2642
2643 partId = (orient == Qt::Horizontal) ? PP_BAR : PP_BARVERT;
2645 stateId = 1;
2646 break;
2647 }
2648
2649 case CE_ProgressBarContents:
2650 if (const auto *bar = qstyleoption_cast<const QStyleOptionProgressBar *>(option)) {
2651 bool isIndeterminate = (bar->minimum == 0 && bar->maximum == 0);
2652 const bool vertical = !(bar->state & QStyle::State_Horizontal);
2653 const bool inverted = bar->invertedAppearance;
2654
2655 if (isIndeterminate || (bar->progress > 0 && (bar->progress < bar->maximum) && d->transitionsEnabled())) {
2656 if (!d->animation(styleObject(option)))
2657 d->startAnimation(new QProgressStyleAnimation(d->animationFps, styleObject(option)));
2658 } else {
2659 d->stopAnimation(styleObject(option));
2660 }
2661
2664 vertical ? PP_FILLVERT : PP_FILL);
2665 theme.rect = option->rect;
2666 bool reverse = (bar->direction == Qt::LeftToRight && inverted) || (bar->direction == Qt::RightToLeft && !inverted);
2667 QTime current = d->animationTime();
2668
2669 if (isIndeterminate) {
2670 if (auto *progressAnimation = qobject_cast<QProgressStyleAnimation *>(d->animation(styleObject(option)))) {
2671 int glowSize = 120;
2672 int animationWidth = glowSize * 2 + (vertical ? theme.rect.height() : theme.rect.width());
2673 int animOffset = progressAnimation->startTime().msecsTo(current) / 4;
2674 if (animOffset > animationWidth)
2675 progressAnimation->setStartTime(d->animationTime());
2676 painter->save();
2677 painter->setClipRect(theme.rect);
2678 QRect animRect;
2679 QSize pixmapSize(14, 14);
2680 if (vertical) {
2681 animRect = QRect(theme.rect.left(),
2682 inverted ? rect.top() - glowSize + animOffset :
2683 rect.bottom() + glowSize - animOffset,
2684 rect.width(), glowSize);
2685 pixmapSize.setHeight(animRect.height());
2686 } else {
2687 animRect = QRect(rect.left() - glowSize + animOffset,
2688 rect.top(), glowSize, rect.height());
2689 animRect = QStyle::visualRect(reverse ? Qt::RightToLeft : Qt::LeftToRight,
2690 option->rect, animRect);
2691 pixmapSize.setWidth(animRect.width());
2692 }
2693 QString name = QString::fromLatin1("qiprogress-%1-%2").arg(pixmapSize.width()).arg(pixmapSize.height());
2695 if (!QPixmapCache::find(name, &pixmap)) {
2696 QImage image(pixmapSize, QImage::Format_ARGB32);
2697 image.fill(Qt::transparent);
2698 QPainter imagePainter(&image);
2699 theme.painter = &imagePainter;
2700 theme.partId = vertical ? PP_FILLVERT : PP_FILL;
2701 theme.rect = QRect(QPoint(0,0), animRect.size());
2702 QLinearGradient alphaGradient(0, 0, vertical ? 0 : image.width(),
2703 vertical ? image.height() : 0);
2704 alphaGradient.setColorAt(0, QColor(0, 0, 0, 0));
2705 alphaGradient.setColorAt(0.5, QColor(0, 0, 0, 220));
2706 alphaGradient.setColorAt(1, QColor(0, 0, 0, 0));
2707 imagePainter.fillRect(image.rect(), alphaGradient);
2708 imagePainter.setCompositionMode(QPainter::CompositionMode_SourceIn);
2709 d->drawBackground(theme);
2710 imagePainter.end();
2713 }
2714 painter->drawPixmap(animRect, pixmap);
2715 painter->restore();
2716 }
2717 } else {
2718 qint64 progress = qMax<qint64>(bar->progress, bar->minimum); // workaround for bug in QProgressBar
2719
2720 if (vertical) {
2721 int maxHeight = option->rect.height();
2722 int minHeight = 0;
2723 double vc6_workaround = ((progress - qint64(bar->minimum)) / qMax(double(1.0), double(qint64(bar->maximum) - qint64(bar->minimum))) * maxHeight);
2724 int height = isIndeterminate ? maxHeight: qMax(int(vc6_workaround), minHeight);
2725 theme.rect.setHeight(height);
2726 if (!inverted)
2727 theme.rect.moveTop(rect.height() - theme.rect.height());
2728 } else {
2729 int maxWidth = option->rect.width();
2730 int minWidth = 0;
2731 double vc6_workaround = ((progress - qint64(bar->minimum)) / qMax(double(1.0), double(qint64(bar->maximum) - qint64(bar->minimum))) * maxWidth);
2732 int width = isIndeterminate ? maxWidth : qMax(int(vc6_workaround), minWidth);
2733 theme.rect.setWidth(width);
2735 option->rect, theme.rect);
2736 }
2737 d->drawBackground(theme);
2738
2739 if (QProgressStyleAnimation *a = qobject_cast<QProgressStyleAnimation *>(d->animation(styleObject(option)))) {
2740 int glowSize = 140;
2741 int animationWidth = glowSize * 2 + (vertical ? theme.rect.height() : theme.rect.width());
2742 int animOffset = a->startTime().msecsTo(current) / 4;
2743 theme.partId = vertical ? PP_MOVEOVERLAYVERT : PP_MOVEOVERLAY;
2744 if (animOffset > animationWidth) {
2745 if (bar->progress < bar->maximum)
2746 a->setStartTime(d->animationTime());
2747 else
2748 d->stopAnimation(styleObject(option)); //we stop the glow motion only after it has
2749 //moved out of view
2750 }
2751 painter->save();
2752 painter->setClipRect(theme.rect);
2753 if (vertical) {
2754 theme.rect = QRect(theme.rect.left(),
2755 inverted ? rect.top() - glowSize + animOffset :
2756 rect.bottom() + glowSize - animOffset,
2757 rect.width(), glowSize);
2758 } else {
2759 theme.rect = QRect(rect.left() - glowSize + animOffset,rect.top(), glowSize, rect.height());
2760 theme.rect = QStyle::visualRect(reverse ? Qt::RightToLeft : Qt::LeftToRight, option->rect, theme.rect);
2761 }
2762 d->drawBackground(theme);
2763 painter->restore();
2764 }
2765 }
2766 }
2767 return;
2768
2769 case CE_MenuBarItem:
2770 if (const auto *mbi = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) {
2771 if (mbi->menuItemType == QStyleOptionMenuItem::DefaultItem)
2772 break;
2773
2775 QPixmap pix = mbi->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize, option, widget), QIcon::Normal);
2776
2778 if (!proxy()->styleHint(SH_UnderlineShortcut, mbi, widget))
2780
2781 if (widget && mbi->palette.color(QPalette::Window) != Qt::transparent) { // Not needed for QtQuick Controls
2782 //The rect adjustment is a workaround for the menu not really filling its background.
2785 MENU_BARBACKGROUND, 0, option->rect.adjusted(-1, 0, 2, 1));
2786 d->drawBackground(theme);
2787
2788 int stateId = MBI_NORMAL;
2789 if (disabled)
2790 stateId = MBI_DISABLED;
2791 else if (pressed)
2792 stateId = MBI_PUSHED;
2793 else if (selected)
2794 stateId = MBI_HOT;
2795
2798 MENU_BARITEM, stateId, option->rect);
2799 d->drawBackground(theme2);
2800 }
2801
2802 if (!pix.isNull())
2803 drawItemPixmap(painter, mbi->rect, alignment, pix);
2804 else
2805 drawItemText(painter, mbi->rect, alignment, mbi->palette, mbi->state & State_Enabled, mbi->text, textRole);
2806 }
2807 return;
2808
2809#if QT_CONFIG(menu)
2810 case CE_MenuEmptyArea:
2811 if (const auto *menuitem = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) {
2812 QBrush fill = menuitem->palette.brush((menuitem->state & State_Selected) ?
2815 break;
2816 }
2817 return;
2818
2819 case CE_MenuItem:
2820 if (const auto *menuitem = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) {
2821 // windows always has a check column, regardless whether we have an icon or not
2822 const qreal factor = QWindowsVistaStylePrivate::nativeMetricScaleFactor(widget);
2823 int checkcol = qRound(qreal(25) * factor);
2824 const int gutterWidth = qRound(qreal(3) * factor);
2825 {
2827 MENU_POPUPCHECKBACKGROUND, MBI_HOT);
2828 QWindowsThemeData themeSize = theme;
2829 themeSize.partId = MENU_POPUPCHECK;
2830 themeSize.stateId = 0;
2831 const QSizeF size = themeSize.size() * QWindowsStylePrivate::nativeMetricScaleFactor(widget);
2832 const QMarginsF margins = themeSize.margins() * QWindowsStylePrivate::nativeMetricScaleFactor(widget);
2833 checkcol = qMax(menuitem->maxIconWidth, qRound(gutterWidth + size.width() + margins.left() + margins.right()));
2834 }
2835 QRect rect = option->rect;
2836
2837 //draw vertical menu line
2838 if (option->direction == Qt::LeftToRight)
2839 checkcol += rect.x();
2840 QPoint p1 = QStyle::visualPos(option->direction, menuitem->rect, QPoint(checkcol, rect.top()));
2841 QPoint p2 = QStyle::visualPos(option->direction, menuitem->rect, QPoint(checkcol, rect.bottom()));
2842 QRect gutterRect(p1.x(), p1.y(), gutterWidth, p2.y() - p1.y() + 1);
2844 MENU_POPUPGUTTER, stateId, gutterRect);
2845 d->drawBackground(theme2);
2846
2847 int x, y, w, h;
2848 menuitem->rect.getRect(&x, &y, &w, &h);
2849 int tab = menuitem->reservedShortcutWidth;
2850 bool dis = !(menuitem->state & State_Enabled);
2851 bool checked = menuitem->checkType != QStyleOptionMenuItem::NotCheckable
2852 ? menuitem->checked : false;
2853 bool act = menuitem->state & State_Selected;
2854
2855 if (menuitem->menuItemType == QStyleOptionMenuItem::Separator) {
2856 int yoff = y-2 + h / 2;
2857 const int separatorSize = qRound(qreal(6) * QWindowsStylePrivate::nativeMetricScaleFactor(widget));
2858 QPoint p1 = QPoint(x + checkcol, yoff);
2859 QPoint p2 = QPoint(x + w + separatorSize, yoff);
2860 stateId = MBI_HOT;
2861 QRect subRect(p1.x() + (gutterWidth - menuitem->rect.x()), p1.y(),
2862 p2.x() - p1.x(), separatorSize);
2863 subRect = QStyle::visualRect(option->direction, option->rect, subRect );
2866 MENU_POPUPSEPARATOR, stateId, subRect);
2867 d->drawBackground(theme2);
2868 return;
2869 }
2870
2871 QRect vCheckRect = visualRect(option->direction, menuitem->rect, QRect(menuitem->rect.x(),
2872 menuitem->rect.y(), checkcol - (gutterWidth + menuitem->rect.x()), menuitem->rect.height()));
2873
2874 if (act) {
2875 stateId = dis ? MBI_DISABLED : MBI_HOT;
2878 MENU_POPUPITEM, stateId, option->rect);
2879 d->drawBackground(theme2);
2880 }
2881
2882 if (checked) {
2885 MENU_POPUPCHECKBACKGROUND,
2886 menuitem->icon.isNull() ? MBI_HOT : MBI_PUSHED, vCheckRect);
2887 QWindowsThemeData themeSize = theme;
2888 themeSize.partId = MENU_POPUPCHECK;
2889 themeSize.stateId = 0;
2890 const QSizeF size = themeSize.size() * QWindowsStylePrivate::nativeMetricScaleFactor(widget);
2891 const QMarginsF margins = themeSize.margins() * QWindowsStylePrivate::nativeMetricScaleFactor(widget);
2892 QRect checkRect(0, 0, qRound(size.width() + margins.left() + margins.right()),
2893 qRound(size.height() + margins.bottom() + margins.top()));
2894 checkRect.moveCenter(vCheckRect.center());
2895 theme.rect = checkRect;
2896
2897 d->drawBackground(theme);
2898
2899 if (menuitem->icon.isNull()) {
2900 checkRect = QRect(QPoint(0, 0), size.toSize());
2901 checkRect.moveCenter(theme.rect.center());
2902 theme.rect = checkRect;
2903
2904 theme.partId = MENU_POPUPCHECK;
2905 bool bullet = menuitem->checkType & QStyleOptionMenuItem::Exclusive;
2906 if (dis)
2907 theme.stateId = bullet ? MC_BULLETDISABLED: MC_CHECKMARKDISABLED;
2908 else
2909 theme.stateId = bullet ? MC_BULLETNORMAL: MC_CHECKMARKNORMAL;
2910 d->drawBackground(theme);
2911 }
2912 }
2913
2914 if (!menuitem->icon.isNull()) {
2916 if (act && !dis)
2918 const auto size = proxy()->pixelMetric(PM_SmallIconSize, option, widget);
2919 const auto dpr = painter->device()->devicePixelRatio();
2920 const auto pixmap = menuitem->icon.pixmap({size, size}, dpr, mode,
2921 checked ? QIcon::On : QIcon::Off);
2922 QRect pmr(QPoint(0, 0), pixmap.deviceIndependentSize().toSize());
2923 pmr.moveCenter(vCheckRect.center());
2924 painter->setPen(menuitem->palette.text().color());
2925 painter->drawPixmap(pmr.topLeft(), pixmap);
2926 }
2927
2928 painter->setPen(menuitem->palette.buttonText().color());
2929
2930 const QColor textColor = menuitem->palette.text().color();
2931 if (dis)
2932 painter->setPen(textColor);
2933
2934 int xm = windowsItemFrame + checkcol + windowsItemHMargin + (gutterWidth - menuitem->rect.x()) - 1;
2935 int xpos = menuitem->rect.x() + xm;
2936 QRect textRect(xpos, y + windowsItemVMargin, w - xm - windowsRightBorder - tab + 1, h - 2 * windowsItemVMargin);
2937 QRect vTextRect = visualRect(option->direction, menuitem->rect, textRect);
2938 QString s = menuitem->text;
2939 if (!s.isEmpty()) { // draw text
2940 painter->save();
2941 int t = s.indexOf(QLatin1Char('\t'));
2943 if (!proxy()->styleHint(SH_UnderlineShortcut, menuitem, widget))
2944 text_flags |= Qt::TextHideMnemonic;
2945 text_flags |= Qt::AlignLeft;
2946 if (t >= 0) {
2947 QRect vShortcutRect = visualRect(option->direction, menuitem->rect,
2948 QRect(textRect.topRight(), QPoint(menuitem->rect.right(), textRect.bottom())));
2949 painter->drawText(vShortcutRect, text_flags, s.mid(t + 1));
2950 s = s.left(t);
2951 }
2952 QFont font = menuitem->font;
2953 if (menuitem->menuItemType == QStyleOptionMenuItem::DefaultItem)
2954 font.setBold(true);
2956 painter->setPen(textColor);
2957 painter->drawText(vTextRect, text_flags, s.left(t));
2958 painter->restore();
2959 }
2960 if (menuitem->menuItemType == QStyleOptionMenuItem::SubMenu) {// draw sub menu arrow
2961 int dim = (h - 2 * windowsItemFrame) / 2;
2962 PrimitiveElement arrow;
2963 arrow = (option->direction == Qt::RightToLeft) ? PE_IndicatorArrowLeft : PE_IndicatorArrowRight;
2964 xpos = x + w - windowsArrowHMargin - windowsItemFrame - dim;
2965 QRect vSubMenuRect = visualRect(option->direction, menuitem->rect, QRect(xpos, y + h / 2 - dim / 2, dim, dim));
2966 QStyleOptionMenuItem newMI = *menuitem;
2967 newMI.rect = vSubMenuRect;
2968 newMI.state = dis ? State_None : State_Enabled;
2969 proxy()->drawPrimitive(arrow, &newMI, painter, widget);
2970 }
2971 }
2972 return;
2973#endif // QT_CONFIG(menu)
2974
2975 case CE_HeaderSection:
2976 if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) {
2977 partId = HP_HEADERITEM;
2978 if (flags & State_Sunken)
2979 stateId = HIS_PRESSED;
2980 else if (flags & State_MouseOver)
2981 stateId = HIS_HOT;
2982 else
2983 stateId = HIS_NORMAL;
2984
2985 if (header->sortIndicator != QStyleOptionHeader::None)
2986 stateId += 3;
2987
2990 partId, stateId, option->rect);
2991 d->drawBackground(theme);
2992 }
2993 return;
2994
2995 case CE_MenuBarEmptyArea: {
2996 stateId = MBI_NORMAL;
2997 if (!(state & State_Enabled))
2998 stateId = MBI_DISABLED;
3000 MENU_BARBACKGROUND, stateId, option->rect);
3001 d->drawBackground(theme);
3002 return;
3003 }
3004
3005 case CE_ToolBar:
3006 if (const auto *toolbar = qstyleoption_cast<const QStyleOptionToolBar *>(option)) {
3007 QPalette pal = option->palette;
3008 pal.setColor(QPalette::Dark, option->palette.window().color().darker(130));
3009 QStyleOptionToolBar copyOpt = *toolbar;
3010 copyOpt.palette = pal;
3011 QWindowsStyle::drawControl(element, &copyOpt, painter, widget);
3012 }
3013 return;
3014
3015#if QT_CONFIG(dockwidget)
3016 case CE_DockWidgetTitle:
3017 if (const auto *dwOpt = qstyleoption_cast<const QStyleOptionDockWidget *>(option)) {
3018 QRect rect = option->rect;
3019 const QDockWidget *dw = qobject_cast<const QDockWidget *>(widget);
3020 bool isFloating = dw && dw->isFloating();
3021 int buttonMargin = 4;
3022 int mw = proxy()->pixelMetric(QStyle::PM_DockWidgetTitleMargin, dwOpt, widget);
3023 int fw = proxy()->pixelMetric(PM_DockWidgetFrameWidth, dwOpt, widget);
3024
3025 const bool verticalTitleBar = dwOpt->verticalTitleBar;
3026
3027 if (verticalTitleBar) {
3028 rect = rect.transposed();
3029
3030 painter->translate(rect.left() - 1, rect.top() + rect.width());
3031 painter->rotate(-90);
3032 painter->translate(-rect.left() + 1, -rect.top());
3033 }
3034
3035 QRect r = option->rect.adjusted(0, 2, -1, -3);
3036 QRect titleRect = r;
3037
3038 if (dwOpt->closable) {
3039 QSize sz = proxy()->standardIcon(QStyle::SP_TitleBarCloseButton, dwOpt, widget).actualSize(QSize(10, 10));
3040 titleRect.adjust(0, 0, -sz.width() - mw - buttonMargin, 0);
3041 }
3042
3043 if (dwOpt->floatable) {
3044 QSize sz = proxy()->standardIcon(QStyle::SP_TitleBarMaxButton, dwOpt, widget).actualSize(QSize(10, 10));
3045 titleRect.adjust(0, 0, -sz.width() - mw - buttonMargin, 0);
3046 }
3047
3048 if (isFloating) {
3049 titleRect.adjust(0, -fw, 0, 0);
3051 titleRect.adjust(titleRect.height() + mw, 0, 0, 0);
3052 } else {
3053 titleRect.adjust(mw, 0, 0, 0);
3054 if (!dwOpt->floatable && !dwOpt->closable)
3055 titleRect.adjust(0, 0, -mw, 0);
3056 }
3057
3058 if (!verticalTitleBar)
3059 titleRect = visualRect(dwOpt->direction, r, titleRect);
3060
3061 if (isFloating) {
3062 const bool isActive = dwOpt->state & State_Active;
3064 if (isActive)
3065 stateId = CS_ACTIVE;
3066 else
3067 stateId = CS_INACTIVE;
3068
3069 int titleHeight = rect.height() - 2;
3070 rect = rect.adjusted(-fw, -fw, fw, 0);
3071
3072 QWindowsThemeData theme(widget, painter, themeNumber, 0, stateId);
3073 if (!theme.isValid())
3074 break;
3075
3076 // Draw small type title bar
3077 theme.rect = rect;
3078 theme.partId = WP_SMALLCAPTION;
3079 d->drawBackground(theme);
3080
3081 // Figure out maximal button space on title bar
3082
3083 QIcon ico = widget->windowIcon();
3084 bool hasIcon = (ico.cacheKey() != QApplication::windowIcon().cacheKey());
3085 if (hasIcon) {
3086 QPixmap pxIco = ico.pixmap(titleHeight);
3087 if (!verticalTitleBar && dwOpt->direction == Qt::RightToLeft)
3088 painter->drawPixmap(rect.width() - titleHeight - pxIco.width(), rect.bottom() - titleHeight - 2, pxIco);
3089 else
3090 painter->drawPixmap(fw, rect.bottom() - titleHeight - 2, pxIco);
3091 }
3092 if (!dwOpt->title.isEmpty()) {
3093 QPen oldPen = painter->pen();
3094 QFont oldFont = painter->font();
3095 QFont titleFont = oldFont;
3096 titleFont.setBold(true);
3097 painter->setFont(titleFont);
3098 QString titleText
3099 = painter->fontMetrics().elidedText(dwOpt->title, Qt::ElideRight, titleRect.width());
3100
3101 int result = TST_NONE;
3102 GetThemeEnumValue(theme.handle(), WP_SMALLCAPTION, isActive ? CS_ACTIVE : CS_INACTIVE, TMT_TEXTSHADOWTYPE, &result);
3103 if (result != TST_NONE) {
3104 COLORREF textShadowRef;
3105 GetThemeColor(theme.handle(), WP_SMALLCAPTION, isActive ? CS_ACTIVE : CS_INACTIVE, TMT_TEXTSHADOWCOLOR, &textShadowRef);
3106 QColor textShadow = qRgb(GetRValue(textShadowRef), GetGValue(textShadowRef), GetBValue(textShadowRef));
3107 painter->setPen(textShadow);
3108 drawItemText(painter, titleRect.adjusted(1, 1, 1, 1),
3110 dwOpt->state & State_Enabled, titleText);
3111 }
3112
3113 COLORREF captionText = GetSysColor(isActive ? COLOR_CAPTIONTEXT : COLOR_INACTIVECAPTIONTEXT);
3114 QColor textColor = qRgb(GetRValue(captionText), GetGValue(captionText), GetBValue(captionText));
3115 painter->setPen(textColor);
3116 drawItemText(painter, titleRect,
3118 dwOpt->state & State_Enabled, titleText);
3119 painter->setFont(oldFont);
3120 painter->setPen(oldPen);
3121 }
3122 } else {
3123 painter->setBrush(option->palette.window().color().darker(110));
3124 painter->setPen(option->palette.window().color().darker(130));
3125 painter->drawRect(rect.adjusted(0, 1, -1, -3));
3126
3127 if (!dwOpt->title.isEmpty()) {
3128 QString titleText = painter->fontMetrics().elidedText(dwOpt->title, Qt::ElideRight,
3129 verticalTitleBar ? titleRect.height() : titleRect.width());
3130 const int indent = 4;
3131 drawItemText(painter, rect.adjusted(indent + 1, 1, -indent - 1, -1),
3133 dwOpt->palette,
3134 dwOpt->state & State_Enabled, titleText,
3136 }
3137 }
3138 }
3139 return;
3140#endif // QT_CONFIG(dockwidget)
3141
3142#if QT_CONFIG(rubberband)
3143 case CE_RubberBand:
3144 if (qstyleoption_cast<const QStyleOptionRubberBand *>(option)) {
3145 QColor highlight = option->palette.color(QPalette::Active, QPalette::Highlight);
3146 painter->save();
3147 painter->setPen(highlight.darker(120));
3148 QColor dimHighlight(qMin(highlight.red()/2 + 110, 255),
3149 qMin(highlight.green()/2 + 110, 255),
3150 qMin(highlight.blue()/2 + 110, 255),
3151 (widget && widget->isWindow())? 255 : 127);
3152 painter->setBrush(dimHighlight);
3153 painter->drawRect(option->rect.adjusted(0, 0, -1, -1));
3154 painter->restore();
3155 return;
3156 }
3157 break;
3158#endif // QT_CONFIG(rubberband)
3159
3160 case CE_HeaderEmptyArea:
3161 if (option->state & State_Horizontal) {
3163 stateId = HIS_NORMAL;
3164 } else {
3165 QWindowsStyle::drawControl(CE_HeaderEmptyArea, option, painter, widget);
3166 return;
3167 }
3168 break;
3169
3170#if QT_CONFIG(itemviews)
3171 case CE_ItemViewItem: {
3172 const QStyleOptionViewItem *vopt;
3173 const QAbstractItemView *view = qobject_cast<const QAbstractItemView *>(widget);
3174 bool newStyle = true;
3175
3176 if (qobject_cast<const QTableView*>(widget))
3177 newStyle = false;
3178
3179 QWindowsThemeData theme(widget, painter, themeNumber, partId, stateId, rect);
3180
3181 if (newStyle && view && (vopt = qstyleoption_cast<const QStyleOptionViewItem *>(option))) {
3182 /*
3183 // We cannot currently get the correct selection color for "explorer style" views
3184 COLORREF cref = 0;
3185 QWindowsThemeData theme(d->treeViewHelper(), 0, QLatin1String("LISTVIEW"), 0, 0);
3186 unsigned int res = GetThemeColor(theme.handle(), LVP_LISTITEM, LISS_SELECTED, TMT_TEXTCOLOR, &cref);
3187 QColor textColor(GetRValue(cref), GetGValue(cref), GetBValue(cref));
3188 */
3189 QPalette palette = vopt->palette;
3191 // Note that setting a saturated color here results in ugly XOR colors in the focus rect
3192 palette.setColor(QPalette::All, QPalette::Highlight, palette.base().color().darker(108));
3193 QStyleOptionViewItem adjustedOption = *vopt;
3194 adjustedOption.palette = palette;
3195 // We hide the focusrect in singleselection as it is not required
3196 if ((view->selectionMode() == QAbstractItemView::SingleSelection)
3197 && !(vopt->state & State_KeyboardFocusChange))
3198 adjustedOption.state &= ~State_HasFocus;
3199 if (!theme.isValid()) {
3200 QWindowsStyle::drawControl(element, &adjustedOption, painter, widget);
3201 return;
3202 }
3203 } else {
3204 if (!theme.isValid()) {
3205 QWindowsStyle::drawControl(element, option, painter, widget);
3206 return;
3207 }
3208 }
3209
3210 theme.rotate = rotate;
3211 theme.mirrorHorizontally = hMirrored;
3212 theme.mirrorVertically = vMirrored;
3213 d->drawBackground(theme);
3214 return;
3215 }
3216#endif // QT_CONFIG(itemviews)
3217
3218#if QT_CONFIG(combobox)
3219 case CE_ComboBoxLabel:
3221 return;
3222#endif // QT_CONFIG(combobox)
3223
3224 default:
3225 break;
3226 }
3227
3228 QWindowsThemeData theme(widget, painter, themeNumber, partId, stateId, rect);
3229
3230 if (!theme.isValid()) {
3231 QWindowsStyle::drawControl(element, option, painter, widget);
3232 return;
3233 }
3234
3235 theme.rotate = rotate;
3236 theme.mirrorHorizontally = hMirrored;
3237 theme.mirrorVertically = vMirrored;
3238
3239 d->drawBackground(theme);
3240}
3241
3248 QPainter *painter, const QWidget *widget) const
3249{
3250 QWindowsVistaStylePrivate *d = const_cast<QWindowsVistaStylePrivate*>(d_func());
3251
3253 QWindowsStyle::drawComplexControl(control, option, painter, widget);
3254 return;
3255 }
3256
3257 State state = option->state;
3258 SubControls sub = option->subControls;
3259 QRect r = option->rect;
3260
3261 int partId = 0;
3262 int stateId = 0;
3263
3264 State flags = option->state;
3266 flags |= State_MouseOver;
3267
3268 if (d->transitionsEnabled() && canAnimate(option))
3269 {
3270 if (control == CC_ScrollBar || control == CC_SpinBox || control == CC_ComboBox) {
3271 QObject *styleObject = option->styleObject; // Can be widget or qquickitem
3272
3273 int oldState = styleObject->property("_q_stylestate").toInt();
3274 int oldActiveControls = styleObject->property("_q_stylecontrols").toInt();
3275
3276 QRect oldRect = styleObject->property("_q_stylerect").toRect();
3277 styleObject->setProperty("_q_stylestate", int(option->state));
3278 styleObject->setProperty("_q_stylecontrols", int(option->activeSubControls));
3279 styleObject->setProperty("_q_stylerect", option->rect);
3280
3281 bool doTransition = ((state & State_Sunken) != (oldState & State_Sunken)
3282 || (state & State_On) != (oldState & State_On)
3283 || (state & State_MouseOver) != (oldState & State_MouseOver)
3284 || oldActiveControls != int(option->activeSubControls));
3285
3286 if (qstyleoption_cast<const QStyleOptionSlider *>(option)) {
3287 QRect oldSliderPos = styleObject->property("_q_stylesliderpos").toRect();
3288 QRect currentPos = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget);
3289 styleObject->setProperty("_q_stylesliderpos", currentPos);
3290 if (oldSliderPos != currentPos) {
3291 doTransition = false;
3292 d->stopAnimation(styleObject);
3293 }
3294 } else if (control == CC_SpinBox) {
3295 //spinboxes have a transition when focus changes
3296 if (!doTransition)
3297 doTransition = (state & State_HasFocus) != (oldState & State_HasFocus);
3298 }
3299
3300 if (oldRect != option->rect) {
3301 doTransition = false;
3302 d->stopAnimation(styleObject);
3303 }
3304
3305 if (doTransition) {
3307 QPainter startPainter(&startImage);
3308
3310 QPainter endPainter(&endImage);
3311
3312 QWindowsVistaAnimation *anim = qobject_cast<QWindowsVistaAnimation *>(d->animation(styleObject));
3314
3315 // Draw the image that ends the animation by using the current styleoption
3316 QStyleOptionComplex *styleOption = qstyleoption_cast<QStyleOptionComplex*>(clonedAnimationStyleOption(option));
3317
3318 styleObject->setProperty("_q_no_animation", true);
3319
3320 // Draw transition source
3321 if (!anim) {
3322 styleOption->state = QStyle::State(oldState);
3323 styleOption->activeSubControls = QStyle::SubControl(oldActiveControls);
3324 proxy()->drawComplexControl(control, styleOption, &startPainter, widget);
3325 } else {
3326 anim->paint(&startPainter, option);
3327 }
3328 t->setStartImage(startImage);
3329
3330 // Draw transition target
3331 styleOption->state = option->state;
3332 styleOption->activeSubControls = option->activeSubControls;
3333 proxy()->drawComplexControl(control, styleOption, &endPainter, widget);
3334
3335 styleObject->setProperty("_q_no_animation", false);
3336
3337 t->setEndImage(endImage);
3338 t->setStartTime(d->animationTime());
3339
3340 if (option->state & State_MouseOver || option->state & State_Sunken)
3341 t->setDuration(150);
3342 else
3343 t->setDuration(500);
3344
3346 d->startAnimation(t);
3347 }
3348 if (QWindowsVistaAnimation *anim = qobject_cast<QWindowsVistaAnimation *>(d->animation(styleObject))) {
3349 anim->paint(painter, option);
3350 return;
3351 }
3352 }
3353 }
3354
3355 switch (control) {
3356
3357#if QT_CONFIG(slider)
3358 case CC_Slider:
3359 if (const auto *slider = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
3361 QRect slrect = slider->rect;
3362 QRegion tickreg = slrect;
3363 if (sub & SC_SliderGroove) {
3364 theme.rect = proxy()->subControlRect(CC_Slider, option, SC_SliderGroove, widget);
3365 if (slider->orientation == Qt::Horizontal) {
3366 partId = TKP_TRACK;
3367 stateId = TRS_NORMAL;
3368 theme.rect = QRect(slrect.left(), theme.rect.center().y() - 2, slrect.width(), 4);
3369 } else {
3370 partId = TKP_TRACKVERT;
3371 stateId = TRVS_NORMAL;
3372 theme.rect = QRect(theme.rect.center().x() - 2, slrect.top(), 4, slrect.height());
3373 }
3374 theme.partId = partId;
3375 theme.stateId = stateId;
3376 d->drawBackground(theme);
3377 tickreg -= theme.rect;
3378 }
3379 if (sub & SC_SliderTickmarks) {
3380 int tickOffset = proxy()->pixelMetric(PM_SliderTickmarkOffset, slider, widget);
3381 int ticks = slider->tickPosition;
3382 int thickness = proxy()->pixelMetric(PM_SliderControlThickness, slider, widget);
3383 int len = proxy()->pixelMetric(PM_SliderLength, slider, widget);
3384 int available = proxy()->pixelMetric(PM_SliderSpaceAvailable, slider, widget);
3385 int interval = slider->tickInterval;
3386 if (interval <= 0) {
3387 interval = slider->singleStep;
3388 if (QStyle::sliderPositionFromValue(slider->minimum, slider->maximum, interval,
3389 available)
3390 - QStyle::sliderPositionFromValue(slider->minimum, slider->maximum,
3391 0, available) < 3)
3392 interval = slider->pageStep;
3393 }
3394 if (!interval)
3395 interval = 1;
3396 int fudge = len / 2;
3397 int pos;
3398 int bothOffset = (ticks & QSlider::TicksAbove && ticks & QSlider::TicksBelow) ? 1 : 0;
3399 painter->setPen(d->sliderTickColor);
3400 QVarLengthArray<QLine, 32> lines;
3401 int v = slider->minimum;
3402 while (v <= slider->maximum + 1) {
3403 if (v == slider->maximum + 1 && interval == 1)
3404 break;
3405 const int v_ = qMin(v, slider->maximum);
3406 int tickLength = (v_ == slider->minimum || v_ >= slider->maximum) ? 4 : 3;
3407 pos = QStyle::sliderPositionFromValue(slider->minimum, slider->maximum,
3408 v_, available) + fudge;
3409 if (slider->orientation == Qt::Horizontal) {
3410 if (ticks & QSlider::TicksAbove) {
3411 lines.append(QLine(pos, tickOffset - 1 - bothOffset,
3412 pos, tickOffset - 1 - bothOffset - tickLength));
3413 }
3414
3415 if (ticks & QSlider::TicksBelow) {
3416 lines.append(QLine(pos, tickOffset + thickness + bothOffset,
3417 pos, tickOffset + thickness + bothOffset + tickLength));
3418 }
3419 } else {
3420 if (ticks & QSlider::TicksAbove) {
3421 lines.append(QLine(tickOffset - 1 - bothOffset, pos,
3422 tickOffset - 1 - bothOffset - tickLength, pos));
3423 }
3424
3425 if (ticks & QSlider::TicksBelow) {
3426 lines.append(QLine(tickOffset + thickness + bothOffset, pos,
3427 tickOffset + thickness + bothOffset + tickLength, pos));
3428 }
3429 }
3430 // in the case where maximum is max int
3431 int nextInterval = v + interval;
3432 if (nextInterval < v)
3433 break;
3434 v = nextInterval;
3435 }
3436 if (!lines.isEmpty()) {
3437 painter->save();
3438 painter->translate(slrect.topLeft());
3439 painter->drawLines(lines.constData(), lines.size());
3440 painter->restore();
3441 }
3442 }
3443 if (sub & SC_SliderHandle) {
3444 theme.rect = proxy()->subControlRect(CC_Slider, option, SC_SliderHandle, widget);
3445 if (slider->orientation == Qt::Horizontal) {
3446 if (slider->tickPosition == QSlider::TicksAbove)
3447 partId = TKP_THUMBTOP;
3448 else if (slider->tickPosition == QSlider::TicksBelow)
3449 partId = TKP_THUMBBOTTOM;
3450 else
3451 partId = TKP_THUMB;
3452
3453 if (!(slider->state & State_Enabled))
3454 stateId = TUS_DISABLED;
3455 else if (slider->activeSubControls & SC_SliderHandle && (slider->state & State_Sunken))
3456 stateId = TUS_PRESSED;
3457 else if (slider->activeSubControls & SC_SliderHandle && (slider->state & State_MouseOver))
3458 stateId = TUS_HOT;
3459 else if (flags & State_HasFocus)
3460 stateId = TUS_FOCUSED;
3461 else
3462 stateId = TUS_NORMAL;
3463 } else {
3464 if (slider->tickPosition == QSlider::TicksLeft)
3465 partId = TKP_THUMBLEFT;
3466 else if (slider->tickPosition == QSlider::TicksRight)
3467 partId = TKP_THUMBRIGHT;
3468 else
3469 partId = TKP_THUMBVERT;
3470
3471 if (!(slider->state & State_Enabled))
3472 stateId = TUVS_DISABLED;
3473 else if (slider->activeSubControls & SC_SliderHandle && (slider->state & State_Sunken))
3474 stateId = TUVS_PRESSED;
3475 else if (slider->activeSubControls & SC_SliderHandle && (slider->state & State_MouseOver))
3476 stateId = TUVS_HOT;
3477 else if (flags & State_HasFocus)
3478 stateId = TUVS_FOCUSED;
3479 else
3480 stateId = TUVS_NORMAL;
3481 }
3482 theme.partId = partId;
3483 theme.stateId = stateId;
3484 d->drawBackground(theme);
3485 }
3486 if (slider->state & State_HasFocus) {
3488 fropt.QStyleOption::operator=(*slider);
3489 fropt.rect = subElementRect(SE_SliderFocusRect, slider, widget);
3490 proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget);
3491 }
3492 }
3493 break;
3494#endif
3495
3496#if QT_CONFIG(toolbutton)
3497 case CC_ToolButton:
3498 if (const auto *toolbutton = qstyleoption_cast<const QStyleOptionToolButton *>(option)) {
3499 QRect button, menuarea;
3500 button = proxy()->subControlRect(control, toolbutton, SC_ToolButton, widget);
3501 menuarea = proxy()->subControlRect(control, toolbutton, SC_ToolButtonMenu, widget);
3502
3503 State bflags = toolbutton->state & ~State_Sunken;
3504 State mflags = bflags;
3505 bool autoRaise = flags & State_AutoRaise;
3506 if (autoRaise) {
3507 if (!(bflags & State_MouseOver) || !(bflags & State_Enabled))
3508 bflags &= ~State_Raised;
3509 }
3510
3511 if (toolbutton->state & State_Sunken) {
3512 if (toolbutton->activeSubControls & SC_ToolButton) {
3513 bflags |= State_Sunken;
3514 mflags |= State_MouseOver | State_Sunken;
3515 } else if (toolbutton->activeSubControls & SC_ToolButtonMenu) {
3516 mflags |= State_Sunken;
3517 bflags |= State_MouseOver;
3518 }
3519 }
3520
3521 QStyleOption tool = *toolbutton;
3522 if (toolbutton->subControls & SC_ToolButton) {
3523 if (flags & (State_Sunken | State_On | State_Raised) || !autoRaise) {
3524 if (toolbutton->features & QStyleOptionToolButton::MenuButtonPopup && autoRaise) {
3526 theme.partId = TP_SPLITBUTTON;
3527 theme.rect = button;
3528 if (!(bflags & State_Enabled))
3529 stateId = TS_DISABLED;
3530 else if (bflags & State_Sunken)
3531 stateId = TS_PRESSED;
3532 else if (bflags & State_MouseOver || !(flags & State_AutoRaise))
3533 stateId = flags & State_On ? TS_HOTCHECKED : TS_HOT;
3534 else if (bflags & State_On)
3535 stateId = TS_CHECKED;
3536 else
3537 stateId = TS_NORMAL;
3538 if (option->direction == Qt::RightToLeft)
3539 theme.mirrorHorizontally = true;
3540 theme.stateId = stateId;
3541 d->drawBackground(theme);
3542 } else {
3543 tool.rect = option->rect;
3544 tool.state = bflags;
3545 if (autoRaise) // for tool bars
3546 proxy()->drawPrimitive(PE_PanelButtonTool, &tool, painter, widget);
3547 else
3548 proxy()->drawPrimitive(PE_PanelButtonBevel, &tool, painter, widget);
3549 }
3550 }
3551 }
3552
3553 if (toolbutton->state & State_HasFocus) {
3555 fr.QStyleOption::operator=(*toolbutton);
3556 fr.rect.adjust(3, 3, -3, -3);
3557 if (toolbutton->features & QStyleOptionToolButton::MenuButtonPopup)
3558 fr.rect.adjust(0, 0, -proxy()->pixelMetric(QStyle::PM_MenuButtonIndicator,
3559 toolbutton, widget), 0);
3560 proxy()->drawPrimitive(PE_FrameFocusRect, &fr, painter, widget);
3561 }
3562 QStyleOptionToolButton label = *toolbutton;
3563 label.state = bflags;
3564 int fw = 2;
3565 if (!autoRaise)
3566 label.state &= ~State_Sunken;
3567 label.rect = button.adjusted(fw, fw, -fw, -fw);
3568 proxy()->drawControl(CE_ToolButtonLabel, &label, painter, widget);
3569
3570 if (toolbutton->subControls & SC_ToolButtonMenu) {
3571 tool.rect = menuarea;
3572 tool.state = mflags;
3573 if (autoRaise) {
3574 proxy()->drawPrimitive(PE_IndicatorButtonDropDown, &tool, painter, widget);
3575 } else {
3576 tool.state = mflags;
3577 menuarea.adjust(-2, 0, 0, 0);
3578 // Draw menu button
3579 if ((bflags & State_Sunken) != (mflags & State_Sunken)){
3580 painter->save();
3581 painter->setClipRect(menuarea);
3582 tool.rect = option->rect;
3583 proxy()->drawPrimitive(PE_PanelButtonBevel, &tool, painter, nullptr);
3584 painter->restore();
3585 }
3586 // Draw arrow
3587 painter->save();
3588 painter->setPen(option->palette.dark().color());
3589 painter->drawLine(menuarea.left(), menuarea.top() + 3,
3590 menuarea.left(), menuarea.bottom() - 3);
3591 painter->setPen(option->palette.light().color());
3592 painter->drawLine(menuarea.left() - 1, menuarea.top() + 3,
3593 menuarea.left() - 1, menuarea.bottom() - 3);
3594
3595 tool.rect = menuarea.adjusted(2, 3, -2, -1);
3596 proxy()->drawPrimitive(PE_IndicatorArrowDown, &tool, painter, widget);
3597 painter->restore();
3598 }
3599 } else if (toolbutton->features & QStyleOptionToolButton::HasMenu) {
3600 int mbi = proxy()->pixelMetric(PM_MenuButtonIndicator, toolbutton, widget);
3601 QRect ir = toolbutton->rect;
3602 QStyleOptionToolButton newBtn = *toolbutton;
3603 newBtn.rect = QRect(ir.right() + 4 - mbi, ir.height() - mbi + 4, mbi - 5, mbi - 5);
3604 proxy()->drawPrimitive(PE_IndicatorArrowDown, &newBtn, painter, widget);
3605 }
3606 }
3607 break;
3608#endif // QT_CONFIG(toolbutton)
3609
3610 case CC_TitleBar:
3611 if (const auto *tb = qstyleoption_cast<const QStyleOptionTitleBar *>(option)) {
3612 const qreal factor = QWindowsStylePrivate::nativeMetricScaleFactor(widget);
3613 bool isActive = tb->titleBarState & QStyle::State_Active;
3615 if (sub & SC_TitleBarLabel) {
3616 partId = (tb->titleBarState & Qt::WindowMinimized) ? WP_MINCAPTION : WP_CAPTION;
3617 theme.rect = option->rect;
3618 if (widget && !widget->isEnabled())
3619 stateId = CS_DISABLED;
3620 else if (isActive)
3621 stateId = CS_ACTIVE;
3622 else
3623 stateId = CS_INACTIVE;
3624
3625 theme.partId = partId;
3626 theme.stateId = stateId;
3627 d->drawBackground(theme);
3628
3629 QRect ir = proxy()->subControlRect(CC_TitleBar, tb, SC_TitleBarLabel, widget);
3630
3631 int result = TST_NONE;
3632 GetThemeEnumValue(theme.handle(), WP_CAPTION, isActive ? CS_ACTIVE : CS_INACTIVE, TMT_TEXTSHADOWTYPE, &result);
3633 if (result != TST_NONE) {
3634 COLORREF textShadowRef;
3635 GetThemeColor(theme.handle(), WP_CAPTION, isActive ? CS_ACTIVE : CS_INACTIVE, TMT_TEXTSHADOWCOLOR, &textShadowRef);
3636 QColor textShadow = qRgb(GetRValue(textShadowRef), GetGValue(textShadowRef), GetBValue(textShadowRef));
3637 painter->setPen(textShadow);
3638 painter->drawText(int(ir.x() + 3 * factor), int(ir.y() + 2 * factor),
3639 int(ir.width() - 1 * factor), ir.height(),
3641 }
3642 COLORREF captionText = GetSysColor(isActive ? COLOR_CAPTIONTEXT : COLOR_INACTIVECAPTIONTEXT);
3643 QColor textColor = qRgb(GetRValue(captionText), GetGValue(captionText), GetBValue(captionText));
3644 painter->setPen(textColor);
3645 painter->drawText(int(ir.x() + 2 * factor), int(ir.y() + 1 * factor),
3646 int(ir.width() - 2 * factor), ir.height(),
3648 }
3649 if (sub & SC_TitleBarSysMenu && tb->titleBarFlags & Qt::WindowSystemMenuHint) {
3650 theme.rect = proxy()->subControlRect(CC_TitleBar, option, SC_TitleBarSysMenu, widget);
3651 partId = WP_SYSBUTTON;
3652 if ((widget && !widget->isEnabled()) || !isActive)
3653 stateId = SBS_DISABLED;
3654 else if (option->activeSubControls == SC_TitleBarSysMenu && (option->state & State_Sunken))
3655 stateId = SBS_PUSHED;
3656 else if (option->activeSubControls == SC_TitleBarSysMenu && (option->state & State_MouseOver))
3657 stateId = SBS_HOT;
3658 else
3659 stateId = SBS_NORMAL;
3660 if (!tb->icon.isNull()) {
3661 tb->icon.paint(painter, theme.rect);
3662 } else {
3663 theme.partId = partId;
3664 theme.stateId = stateId;
3665 if (theme.size().isEmpty()) {
3666 int iconSize = proxy()->pixelMetric(PM_SmallIconSize, tb, widget);
3667 QPixmap pm = proxy()->standardIcon(SP_TitleBarMenuButton, tb, widget).pixmap(iconSize, iconSize);
3668 painter->save();
3669 drawItemPixmap(painter, theme.rect, Qt::AlignCenter, pm);
3670 painter->restore();
3671 } else {
3672 d->drawBackground(theme);
3673 }
3674 }
3675 }
3676
3677 if (sub & SC_TitleBarMinButton && tb->titleBarFlags & Qt::WindowMinimizeButtonHint
3678 && !(tb->titleBarState & Qt::WindowMinimized)) {
3679 populateTitleBarButtonTheme(proxy(), widget, option, SC_TitleBarMinButton, isActive, WP_MINBUTTON, &theme);
3680 d->drawBackground(theme);
3681 }
3682 if (sub & SC_TitleBarMaxButton && tb->titleBarFlags & Qt::WindowMaximizeButtonHint
3683 && !(tb->titleBarState & Qt::WindowMaximized)) {
3684 populateTitleBarButtonTheme(proxy(), widget, option, SC_TitleBarMaxButton, isActive, WP_MAXBUTTON, &theme);
3685 d->drawBackground(theme);
3686 }
3687 if (sub & SC_TitleBarContextHelpButton
3688 && tb->titleBarFlags & Qt::WindowContextHelpButtonHint) {
3689 populateTitleBarButtonTheme(proxy(), widget, option, SC_TitleBarContextHelpButton, isActive, WP_HELPBUTTON, &theme);
3690 d->drawBackground(theme);
3691 }
3692 bool drawNormalButton = (sub & SC_TitleBarNormalButton)
3693 && (((tb->titleBarFlags & Qt::WindowMinimizeButtonHint)
3694 && (tb->titleBarState & Qt::WindowMinimized))
3695 || ((tb->titleBarFlags & Qt::WindowMaximizeButtonHint)
3696 && (tb->titleBarState & Qt::WindowMaximized)));
3697 if (drawNormalButton) {
3698 populateTitleBarButtonTheme(proxy(), widget, option, SC_TitleBarNormalButton, isActive, WP_RESTOREBUTTON, &theme);
3699 d->drawBackground(theme);
3700 }
3701 if (sub & SC_TitleBarShadeButton && tb->titleBarFlags & Qt::WindowShadeButtonHint
3702 && !(tb->titleBarState & Qt::WindowMinimized)) {
3703 populateTitleBarButtonTheme(proxy(), widget, option, SC_TitleBarShadeButton, isActive, WP_MINBUTTON, &theme);
3704 d->drawBackground(theme);
3705 }
3706 if (sub & SC_TitleBarUnshadeButton && tb->titleBarFlags & Qt::WindowShadeButtonHint
3707 && tb->titleBarState & Qt::WindowMinimized) {
3708 populateTitleBarButtonTheme(proxy(), widget, option, SC_TitleBarUnshadeButton, isActive, WP_RESTOREBUTTON, &theme);
3709 d->drawBackground(theme);
3710 }
3711 if (sub & SC_TitleBarCloseButton && tb->titleBarFlags & Qt::WindowSystemMenuHint) {
3712 populateTitleBarButtonTheme(proxy(), widget, option, SC_TitleBarCloseButton, isActive, WP_CLOSEBUTTON, &theme);
3713 d->drawBackground(theme);
3714 }
3715 }
3716 break;
3717
3718#if QT_CONFIG(mdiarea)
3719 case CC_MdiControls: {
3720 QWindowsThemeData theme(widget, painter, QWindowsVistaStylePrivate::WindowTheme, WP_MDICLOSEBUTTON, CBS_NORMAL);
3721 if (Q_UNLIKELY(!theme.isValid()))
3722 return;
3723
3724 if (option->subControls.testFlag(SC_MdiCloseButton)) {
3725 populateMdiButtonTheme(proxy(), widget, option, SC_MdiCloseButton, WP_MDICLOSEBUTTON, &theme);
3726 d->drawBackground(theme, mdiButtonCorrectionFactor(theme, widget));
3727 }
3728 if (option->subControls.testFlag(SC_MdiNormalButton)) {
3729 populateMdiButtonTheme(proxy(), widget, option, SC_MdiNormalButton, WP_MDIRESTOREBUTTON, &theme);
3730 d->drawBackground(theme, mdiButtonCorrectionFactor(theme, widget));
3731 }
3732 if (option->subControls.testFlag(QStyle::SC_MdiMinButton)) {
3733 populateMdiButtonTheme(proxy(), widget, option, SC_MdiMinButton, WP_MDIMINBUTTON, &theme);
3734 d->drawBackground(theme, mdiButtonCorrectionFactor(theme, widget));
3735 }
3736 break;
3737 }
3738#endif // QT_CONFIG(mdiarea)
3739
3740#if QT_CONFIG(dial)
3741 case CC_Dial:
3742 if (const auto *dial = qstyleoption_cast<const QStyleOptionSlider *>(option))
3743 QStyleHelper::drawDial(dial, painter);
3744 break;
3745#endif // QT_CONFIG(dial)
3746
3747 case CC_ComboBox:
3748 if (const QStyleOptionComboBox *cmb = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
3749 if (cmb->editable) {
3750 if (sub & SC_ComboBoxEditField) {
3751 partId = EP_EDITBORDER_NOSCROLL;
3752 if (!(flags & State_Enabled))
3753 stateId = ETS_DISABLED;
3754 else if (flags & State_MouseOver)
3755 stateId = ETS_HOT;
3756 else if (flags & State_HasFocus)
3757 stateId = ETS_FOCUSED;
3758 else
3759 stateId = ETS_NORMAL;
3760
3763 partId, stateId, r);
3764
3765 d->drawBackground(theme);
3766 }
3767 if (sub & SC_ComboBoxArrow) {
3768 QRect subRect = proxy()->subControlRect(CC_ComboBox, option, SC_ComboBoxArrow, widget);
3770 theme.rect = subRect;
3771 partId = option->direction == Qt::RightToLeft ? CP_DROPDOWNBUTTONLEFT : CP_DROPDOWNBUTTONRIGHT;
3772
3773 if (!(cmb->state & State_Enabled))
3774 stateId = CBXS_DISABLED;
3775 else if (cmb->state & State_Sunken || cmb->state & State_On)
3776 stateId = CBXS_PRESSED;
3777 else if (cmb->state & State_MouseOver && option->activeSubControls & SC_ComboBoxArrow)
3778 stateId = CBXS_HOT;
3779 else
3780 stateId = CBXS_NORMAL;
3781
3782 theme.partId = partId;
3783 theme.stateId = stateId;
3784 d->drawBackground(theme);
3785 }
3786
3787 } else {
3788 if (sub & SC_ComboBoxFrame) {
3790 theme.rect = option->rect;
3791 theme.partId = CP_READONLY;
3792 if (!(cmb->state & State_Enabled))
3793 theme.stateId = CBXS_DISABLED;
3794 else if (cmb->state & State_Sunken || cmb->state & State_On)
3795 theme.stateId = CBXS_PRESSED;
3796 else if (cmb->state & State_MouseOver)
3797 theme.stateId = CBXS_HOT;
3798 else
3799 theme.stateId = CBXS_NORMAL;
3800 d->drawBackground(theme);
3801 }
3802 if (sub & SC_ComboBoxArrow) {
3804 theme.rect = proxy()->subControlRect(CC_ComboBox, option, SC_ComboBoxArrow, widget);
3805 theme.partId = option->direction == Qt::RightToLeft ? CP_DROPDOWNBUTTONLEFT : CP_DROPDOWNBUTTONRIGHT;
3806 if (!(cmb->state & State_Enabled))
3807 theme.stateId = CBXS_DISABLED;
3808 else
3809 theme.stateId = CBXS_NORMAL;
3810 d->drawBackground(theme);
3811 }
3812 if ((sub & SC_ComboBoxEditField) && (flags & State_HasFocus)) {
3814 fropt.QStyleOption::operator=(*cmb);
3815 fropt.rect = proxy()->subControlRect(CC_ComboBox, option, SC_ComboBoxEditField, widget);
3816 proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget);
3817 }
3818 }
3819 }
3820 break;
3821
3822 case CC_ScrollBar:
3823 if (const QStyleOptionSlider *scrollbar = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
3825 bool maxedOut = (scrollbar->maximum == scrollbar->minimum);
3826 if (maxedOut)
3827 flags &= ~State_Enabled;
3828
3829 bool isHorz = flags & State_Horizontal;
3830 bool isRTL = option->direction == Qt::RightToLeft;
3831 if (sub & SC_ScrollBarAddLine) {
3832 theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarAddLine, widget);
3833 partId = SBP_ARROWBTN;
3834 if (!(flags & State_Enabled))
3835 stateId = (isHorz ? (isRTL ? ABS_LEFTDISABLED : ABS_RIGHTDISABLED) : ABS_DOWNDISABLED);
3836 else if (scrollbar->activeSubControls & SC_ScrollBarAddLine && (scrollbar->state & State_Sunken))
3837 stateId = (isHorz ? (isRTL ? ABS_LEFTPRESSED : ABS_RIGHTPRESSED) : ABS_DOWNPRESSED);
3838 else if (scrollbar->activeSubControls & SC_ScrollBarAddLine && (scrollbar->state & State_MouseOver))
3839 stateId = (isHorz ? (isRTL ? ABS_LEFTHOT : ABS_RIGHTHOT) : ABS_DOWNHOT);
3840 else if (scrollbar->state & State_MouseOver)
3841 stateId = (isHorz ? (isRTL ? ABS_LEFTHOVER : ABS_RIGHTHOVER) : ABS_DOWNHOVER);
3842 else
3843 stateId = (isHorz ? (isRTL ? ABS_LEFTNORMAL : ABS_RIGHTNORMAL) : ABS_DOWNNORMAL);
3844 theme.partId = partId;
3845 theme.stateId = stateId;
3846 d->drawBackground(theme);
3847 }
3848 if (sub & SC_ScrollBarSubLine) {
3849 theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSubLine, widget);
3850 partId = SBP_ARROWBTN;
3851 if (!(flags & State_Enabled))
3852 stateId = (isHorz ? (isRTL ? ABS_RIGHTDISABLED : ABS_LEFTDISABLED) : ABS_UPDISABLED);
3853 else if (scrollbar->activeSubControls & SC_ScrollBarSubLine && (scrollbar->state & State_Sunken))
3854 stateId = (isHorz ? (isRTL ? ABS_RIGHTPRESSED : ABS_LEFTPRESSED) : ABS_UPPRESSED);
3855 else if (scrollbar->activeSubControls & SC_ScrollBarSubLine && (scrollbar->state & State_MouseOver))
3856 stateId = (isHorz ? (isRTL ? ABS_RIGHTHOT : ABS_LEFTHOT) : ABS_UPHOT);
3857 else if (scrollbar->state & State_MouseOver)
3858 stateId = (isHorz ? (isRTL ? ABS_RIGHTHOVER : ABS_LEFTHOVER) : ABS_UPHOVER);
3859 else
3860 stateId = (isHorz ? (isRTL ? ABS_RIGHTNORMAL : ABS_LEFTNORMAL) : ABS_UPNORMAL);
3861 theme.partId = partId;
3862 theme.stateId = stateId;
3863 d->drawBackground(theme);
3864 }
3865 if (maxedOut) {
3866 theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget);
3867 theme.rect = theme.rect.united(proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSubPage, widget));
3868 theme.rect = theme.rect.united(proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarAddPage, widget));
3869 partId = flags & State_Horizontal ? SBP_LOWERTRACKHORZ : SBP_LOWERTRACKVERT;
3870 stateId = SCRBS_DISABLED;
3871 theme.partId = partId;
3872 theme.stateId = stateId;
3873 d->drawBackground(theme);
3874 } else {
3875 if (sub & SC_ScrollBarSubPage) {
3876 theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSubPage, widget);
3877 partId = flags & State_Horizontal ? SBP_UPPERTRACKHORZ : SBP_UPPERTRACKVERT;
3878 if (!(flags & State_Enabled))
3879 stateId = SCRBS_DISABLED;
3880 else if (scrollbar->activeSubControls & SC_ScrollBarSubPage && (scrollbar->state & State_Sunken))
3881 stateId = SCRBS_PRESSED;
3882 else if (scrollbar->activeSubControls & SC_ScrollBarSubPage && (scrollbar->state & State_MouseOver))
3883 stateId = SCRBS_HOT;
3884 else
3885 stateId = SCRBS_NORMAL;
3886 theme.partId = partId;
3887 theme.stateId = stateId;
3888 d->drawBackground(theme);
3889 }
3890 if (sub & SC_ScrollBarAddPage) {
3891 theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarAddPage, widget);
3892 partId = flags & State_Horizontal ? SBP_LOWERTRACKHORZ : SBP_LOWERTRACKVERT;
3893 if (!(flags & State_Enabled))
3894 stateId = SCRBS_DISABLED;
3895 else if (scrollbar->activeSubControls & SC_ScrollBarAddPage && (scrollbar->state & State_Sunken))
3896 stateId = SCRBS_PRESSED;
3897 else if (scrollbar->activeSubControls & SC_ScrollBarAddPage && (scrollbar->state & State_MouseOver))
3898 stateId = SCRBS_HOT;
3899 else
3900 stateId = SCRBS_NORMAL;
3901 theme.partId = partId;
3902 theme.stateId = stateId;
3903 d->drawBackground(theme);
3904 }
3905 if (sub & SC_ScrollBarSlider) {
3906 theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget);
3907 if (!(flags & State_Enabled))
3908 stateId = SCRBS_DISABLED;
3909 else if (scrollbar->activeSubControls & SC_ScrollBarSlider && (scrollbar->state & State_Sunken))
3910 stateId = SCRBS_PRESSED;
3911 else if (scrollbar->activeSubControls & SC_ScrollBarSlider && (scrollbar->state & State_MouseOver))
3912 stateId = SCRBS_HOT;
3913 else if (option->state & State_MouseOver)
3914 stateId = SCRBS_HOVER;
3915 else
3916 stateId = SCRBS_NORMAL;
3917
3918 // Draw handle
3919 theme.partId = flags & State_Horizontal ? SBP_THUMBBTNHORZ : SBP_THUMBBTNVERT;
3920 theme.stateId = stateId;
3921 d->drawBackground(theme);
3922 }
3923 }
3924 }
3925 break;
3926
3927#if QT_CONFIG(spinbox)
3928 case CC_SpinBox:
3929 if (const QStyleOptionSpinBox *sb = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) {
3931 if (sb->frame && (sub & SC_SpinBoxFrame)) {
3932 partId = EP_EDITBORDER_NOSCROLL;
3933 if (!(flags & State_Enabled))
3934 stateId = ETS_DISABLED;
3935 else if (flags & State_MouseOver)
3936 stateId = ETS_HOT;
3937 else if (flags & State_HasFocus)
3938 stateId = ETS_SELECTED;
3939 else
3940 stateId = ETS_NORMAL;
3941
3944 partId, stateId, r);
3945 // The spinbox in Windows QStyle is drawn with frameless QLineEdit inside it
3946 // That however breaks with QtQuickControls where this results in transparent
3947 // spinbox background, so if there's no "widget" passed (QtQuickControls case),
3948 // let ftheme.noContent be false, which fixes the spinbox rendering in QQC
3949 ftheme.noContent = (widget != nullptr);
3950 d->drawBackground(ftheme);
3951 }
3952 if (sub & SC_SpinBoxUp) {
3953 theme.rect = proxy()->subControlRect(CC_SpinBox, option, SC_SpinBoxUp, widget).adjusted(0, 0, 0, 1);
3954 partId = SPNP_UP;
3955 if (!(sb->stepEnabled & QAbstractSpinBox::StepUpEnabled) || !(flags & State_Enabled))
3956 stateId = UPS_DISABLED;
3957 else if (sb->activeSubControls == SC_SpinBoxUp && (sb->state & State_Sunken))
3958 stateId = UPS_PRESSED;
3959 else if (sb->activeSubControls == SC_SpinBoxUp && (sb->state & State_MouseOver))
3960 stateId = UPS_HOT;
3961 else
3962 stateId = UPS_NORMAL;
3963 theme.partId = partId;
3964 theme.stateId = stateId;
3965 d->drawBackground(theme);
3966 }
3967 if (sub & SC_SpinBoxDown) {
3968 theme.rect = proxy()->subControlRect(CC_SpinBox, option, SC_SpinBoxDown, widget);
3969 partId = SPNP_DOWN;
3970 if (!(sb->stepEnabled & QAbstractSpinBox::StepDownEnabled) || !(flags & State_Enabled))
3971 stateId = DNS_DISABLED;
3972 else if (sb->activeSubControls == SC_SpinBoxDown && (sb->state & State_Sunken))
3973 stateId = DNS_PRESSED;
3974 else if (sb->activeSubControls == SC_SpinBoxDown && (sb->state & State_MouseOver))
3975 stateId = DNS_HOT;
3976 else
3977 stateId = DNS_NORMAL;
3978 theme.partId = partId;
3979 theme.stateId = stateId;
3980 d->drawBackground(theme);
3981 }
3982 }
3983 break;
3984#endif // QT_CONFIG(spinbox)
3985
3986 default:
3987 QWindowsStyle::drawComplexControl(control, option, painter, widget);
3988 break;
3989 }
3990}
3991
3996 const QSize &size, const QWidget *widget) const
3997{
3999 return QWindowsStyle::sizeFromContents(type, option, size, widget);
4000
4001 QSize contentSize(size);
4002
4003 switch (type) {
4004 case CT_LineEdit:
4005 case CT_ComboBox: {
4006 QWindowsThemeData buttontheme(widget, nullptr, QWindowsVistaStylePrivate::ButtonTheme, BP_PUSHBUTTON, PBS_NORMAL);
4007 if (buttontheme.isValid()) {
4008 const qreal factor = QWindowsStylePrivate::nativeMetricScaleFactor(widget);
4009 const QMarginsF borderSize = buttontheme.margins() * factor;
4010 if (!borderSize.isNull()) {
4011 const qreal margin = qreal(2) * factor;
4012 contentSize.rwidth() += qRound(borderSize.left() + borderSize.right() - margin);
4013 contentSize.rheight() += int(borderSize.bottom() + borderSize.top() - margin
4014 + qreal(1) / factor - 1);
4015 }
4016 const int textMargins = 2*(proxy()->pixelMetric(PM_FocusFrameHMargin, option) + 1);
4018 + textMargins, 23), 0); //arrow button
4019 }
4020 break;
4021 }
4022
4023 case CT_TabWidget:
4024 contentSize += QSize(6, 6);
4025 break;
4026
4027 case CT_Menu:
4028 contentSize += QSize(1, 0);
4029 break;
4030
4031#if QT_CONFIG(menubar)
4032 case CT_MenuBarItem:
4033 if (!contentSize.isEmpty())
4034 contentSize += QSize(windowsItemHMargin * 5 + 1, 5);
4035 break;
4036#endif
4037
4038 case CT_MenuItem: {
4039 contentSize = QWindowsStyle::sizeFromContents(type, option, size, widget);
4040 QWindowsThemeData theme(widget, nullptr,
4042 MENU_POPUPCHECKBACKGROUND, MBI_HOT);
4043 QWindowsThemeData themeSize = theme;
4044 themeSize.partId = MENU_POPUPCHECK;
4045 themeSize.stateId = 0;
4046 const QSizeF size = themeSize.size() * QWindowsStylePrivate::nativeMetricScaleFactor(widget);
4047 const QMarginsF margins = themeSize.margins() * QWindowsStylePrivate::nativeMetricScaleFactor(widget);
4048 int minimumHeight = qMax(qRound(size.height() + margins.bottom() + margins.top()), contentSize.height());
4049 contentSize.rwidth() += qRound(size.width() + margins.left() + margins.right());
4050 if (const QStyleOptionMenuItem *menuitem = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) {
4051 if (menuitem->menuItemType != QStyleOptionMenuItem::Separator)
4052 contentSize.setHeight(minimumHeight);
4053 }
4054 break;
4055 }
4056
4057 case CT_MdiControls: {
4058 contentSize.setHeight(int(QStyleHelper::dpiScaled(19, option)));
4059 int width = 54;
4060 if (const auto *styleOpt = qstyleoption_cast<const QStyleOptionComplex *>(option)) {
4061 width = 0;
4062 if (styleOpt->subControls & SC_MdiMinButton)
4063 width += 17 + 1;
4064 if (styleOpt->subControls & SC_MdiNormalButton)
4065 width += 17 + 1;
4066 if (styleOpt->subControls & SC_MdiCloseButton)
4067 width += 17 + 1;
4068 }
4069 contentSize.setWidth(int(QStyleHelper::dpiScaled(width, option)));
4070 break;
4071 }
4072
4073 case CT_ItemViewItem:
4074 contentSize = QWindowsStyle::sizeFromContents(type, option, size, widget);
4075 contentSize.rheight() += 2;
4076 break;
4077
4078 case CT_SpinBox: {
4079 //Spinbox adds frame twice
4080 contentSize = QWindowsStyle::sizeFromContents(type, option, size, widget);
4081 int border = proxy()->pixelMetric(PM_SpinBoxFrameWidth, option, widget);
4082 contentSize -= QSize(2*border, 2*border);
4083 break;
4084 }
4085
4086 case CT_HeaderSection:
4087 // When there is a sort indicator it adds to the width but it is shown
4088 // above the text natively and not on the side
4089 if (QStyleOptionHeader *hdr = qstyleoption_cast<QStyleOptionHeader *>(const_cast<QStyleOption *>(option))) {
4090 QStyleOptionHeader::SortIndicator sortInd = hdr->sortIndicator;
4091 hdr->sortIndicator = QStyleOptionHeader::None;
4092 contentSize = QWindowsStyle::sizeFromContents(type, hdr, size, widget);
4093 hdr->sortIndicator = sortInd;
4094 }
4095 break;
4096
4097 default:
4098 contentSize = QWindowsStyle::sizeFromContents(type, option, size, widget);
4099 break;
4100 }
4101
4102 return contentSize;
4103}
4104
4109{
4111 return QWindowsStyle::subElementRect(element, option, widget);
4112
4113 QRect rect(option->rect);
4114
4115 switch (element) {
4116 case SE_PushButtonContents:
4117 if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) {
4118 MARGINS borderSize;
4119 const HTHEME theme = OpenThemeData(widget ? QWindowsVistaStylePrivate::winId(widget) : nullptr, L"Button");
4120 if (theme) {
4121 int stateId = PBS_NORMAL;
4122 if (!(option->state & State_Enabled))
4123 stateId = PBS_DISABLED;
4124 else if (option->state & State_Sunken)
4125 stateId = PBS_PRESSED;
4126 else if (option->state & State_MouseOver)
4127 stateId = PBS_HOT;
4129 stateId = PBS_DEFAULTED;
4130
4131 int border = proxy()->pixelMetric(PM_DefaultFrameWidth, btn, widget);
4132 rect = option->rect.adjusted(border, border, -border, -border);
4133
4134 if (SUCCEEDED(GetThemeMargins(theme, nullptr, BP_PUSHBUTTON, stateId, TMT_CONTENTMARGINS, nullptr, &borderSize))) {
4135 rect.adjust(borderSize.cxLeftWidth, borderSize.cyTopHeight,
4136 -borderSize.cxRightWidth, -borderSize.cyBottomHeight);
4137 rect = visualRect(option->direction, option->rect, rect);
4138 }
4139 }
4140 }
4141 break;
4142
4143 case SE_DockWidgetCloseButton:
4144 case SE_DockWidgetFloatButton:
4145 rect = QWindowsStyle::subElementRect(element, option, widget);
4146 return rect.translated(0, 1);
4147
4148 case SE_TabWidgetTabContents:
4149 rect = QWindowsStyle::subElementRect(element, option, widget);
4150 if (qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(option)) {
4151 rect = QWindowsStyle::subElementRect(element, option, widget);
4152 if (const QTabWidget *tabWidget = qobject_cast<const QTabWidget *>(widget)) {
4153 if (tabWidget->documentMode())
4154 break;
4155 rect.adjust(0, 0, -2, -2);
4156 }
4157 }
4158 break;
4159
4160 case SE_TabWidgetTabBar: {
4161 rect = QWindowsStyle::subElementRect(element, option, widget);
4162 const auto *twfOption = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(option);
4163 if (twfOption && twfOption->direction == Qt::RightToLeft
4164 && (twfOption->shape == QTabBar::RoundedNorth
4165 || twfOption->shape == QTabBar::RoundedSouth))
4166 {
4167 QStyleOptionTab otherOption;
4168 otherOption.shape = (twfOption->shape == QTabBar::RoundedNorth
4170 int overlap = proxy()->pixelMetric(PM_TabBarBaseOverlap, &otherOption, widget);
4171 int borderThickness = proxy()->pixelMetric(PM_DefaultFrameWidth, option, widget);
4172 rect.adjust(-overlap + borderThickness, 0, -overlap + borderThickness, 0);
4173 }
4174 break;
4175 }
4176
4177 case SE_HeaderArrow: {
4178 rect = QWindowsStyle::subElementRect(element, option, widget);
4179 QRect r = rect;
4180 int h = option->rect.height();
4181 int w = option->rect.width();
4182 int x = option->rect.x();
4183 int y = option->rect.y();
4184 int margin = proxy()->pixelMetric(QStyle::PM_HeaderMargin, option, widget);
4185
4186 QWindowsThemeData theme(widget, nullptr,
4188 HP_HEADERSORTARROW, HSAS_SORTEDDOWN, option->rect);
4189
4190 int arrowWidth = 13;
4191 int arrowHeight = 5;
4192 if (theme.isValid()) {
4193 const QSizeF size = theme.size() * QWindowsStylePrivate::nativeMetricScaleFactor(widget);
4194 if (!size.isEmpty()) {
4195 arrowWidth = qRound(size.width());
4196 arrowHeight = qRound(size.height());
4197 }
4198 }
4199 if (option->state & State_Horizontal) {
4200 r.setRect(x + w/2 - arrowWidth/2, y , arrowWidth, arrowHeight);
4201 } else {
4202 int vert_size = w / 2;
4203 r.setRect(x + 5, y + h - margin * 2 - vert_size,
4204 w - margin * 2 - 5, vert_size);
4205 }
4206 rect = visualRect(option->direction, option->rect, r);
4207 break;
4208 }
4209
4210 case SE_HeaderLabel: {
4211 rect = QWindowsStyle::subElementRect(element, option, widget);
4212 int margin = proxy()->pixelMetric(QStyle::PM_HeaderMargin, option, widget);
4213 QRect r = option->rect;
4214 r.setRect(option->rect.x() + margin, option->rect.y() + margin,
4215 option->rect.width() - margin * 2, option->rect.height() - margin * 2);
4216 if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) {
4217 // Subtract width needed for arrow, if there is one
4218 if (header->sortIndicator != QStyleOptionHeader::None) {
4219 if (!(option->state & State_Horizontal)) //horizontal arrows are positioned on top
4220 r.setHeight(r.height() - (option->rect.width() / 2) - (margin * 2));
4221 }
4222 }
4223 rect = visualRect(option->direction, option->rect, r);
4224 break;
4225 }
4226
4227 case SE_ProgressBarContents:
4228 rect = QCommonStyle::subElementRect(SE_ProgressBarGroove, option, widget);
4229 break;
4230
4231 case SE_ItemViewItemDecoration:
4232 rect = QWindowsStyle::subElementRect(element, option, widget);
4233 if (qstyleoption_cast<const QStyleOptionViewItem *>(option))
4234 rect.adjust(-2, 0, 2, 0);
4235 break;
4236
4237 case SE_ItemViewItemFocusRect:
4238 rect = QWindowsStyle::subElementRect(element, option, widget);
4239 if (const QStyleOptionViewItem *vopt = qstyleoption_cast<const QStyleOptionViewItem *>(option)) {
4242 if (!vopt->icon.isNull())
4243 rect = textRect.united(displayRect);
4244 else
4245 rect = textRect;
4246 rect = rect.adjusted(1, 0, -1, 0);
4247 }
4248 break;
4249
4250 default:
4251 rect = QWindowsStyle::subElementRect(element, option, widget);
4252 break;
4253 }
4254
4255 return rect;
4256}
4257
4262 SubControl subControl, const QWidget *widget) const
4263{
4265 return QWindowsStyle::subControlRect(control, option, subControl, widget);
4266
4267 QRect rect;
4268
4269 switch (control) {
4270#if QT_CONFIG(combobox)
4271 case CC_ComboBox:
4272 if (const auto *cb = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
4273 const int x = cb->rect.x(), y = cb->rect.y(), wi = cb->rect.width(), he = cb->rect.height();
4274 const int margin = cb->frame ? 3 : 0;
4275 const int bmarg = cb->frame ? 2 : 0;
4276 const int arrowWidth = qRound(QStyleHelper::dpiScaled(16, option));
4277 const int arrowButtonWidth = bmarg + arrowWidth;
4278 const int xpos = x + wi - arrowButtonWidth;
4279
4280 switch (subControl) {
4281 case SC_ComboBoxFrame:
4282 case SC_ComboBoxListBoxPopup:
4283 rect = cb->rect;
4284 break;
4285
4286 case SC_ComboBoxArrow: {
4287 rect.setRect(xpos, y , arrowButtonWidth, he);
4288 }
4289 break;
4290
4291 case SC_ComboBoxEditField: {
4292 rect.setRect(x + margin, y + margin, wi - 2 * margin - arrowWidth, he - 2 * margin);
4293 }
4294 break;
4295
4296 default:
4297 break;
4298 }
4299 }
4300 break;
4301#endif // QT_CONFIG(combobox)
4302
4303 case CC_TitleBar:
4304 if (const QStyleOptionTitleBar *tb = qstyleoption_cast<const QStyleOptionTitleBar *>(option)) {
4305 if (!buttonVisible(subControl, tb))
4306 return rect;
4307 const qreal factor = QWindowsStylePrivate::nativeMetricScaleFactor(widget);
4308 const bool isToolTitle = false;
4309 const int height = tb->rect.height();
4310 const int width = tb->rect.width();
4311
4312 const int buttonMargin = int(QStyleHelper::dpiScaled(4, option));
4313 int buttonHeight = qRound(qreal(GetSystemMetrics(SM_CYSIZE)) * factor)
4314 - buttonMargin;
4315 const int buttonWidth =
4316 qRound(qreal(GetSystemMetrics(SM_CXSIZE)) * factor - QStyleHelper::dpiScaled(4, option));
4317
4318 const int frameWidth = proxy()->pixelMetric(PM_MdiSubWindowFrameWidth, option, widget);
4319 const bool sysmenuHint = (tb->titleBarFlags & Qt::WindowSystemMenuHint) != 0;
4320 const bool minimizeHint = (tb->titleBarFlags & Qt::WindowMinimizeButtonHint) != 0;
4321 const bool maximizeHint = (tb->titleBarFlags & Qt::WindowMaximizeButtonHint) != 0;
4322 const bool contextHint = (tb->titleBarFlags & Qt::WindowContextHelpButtonHint) != 0;
4323 const bool shadeHint = (tb->titleBarFlags & Qt::WindowShadeButtonHint) != 0;
4324
4325 bool isMinimized = tb->titleBarState & Qt::WindowMinimized;
4326 bool isMaximized = tb->titleBarState & Qt::WindowMaximized;
4327 int offset = 0;
4328 const int delta = buttonWidth + 2;
4329 int controlTop = option->rect.bottom() - buttonHeight - 2;
4330
4331 switch (subControl) {
4332 case SC_TitleBarLabel: {
4333 rect = QRect(frameWidth, 0, width - (buttonWidth + frameWidth + 10), height);
4334 if (isToolTitle) {
4335 if (sysmenuHint) {
4336 rect.adjust(0, 0, int(-buttonWidth - 3 * factor), 0);
4337 }
4338 if (minimizeHint || maximizeHint)
4339 rect.adjust(0, 0, int(-buttonWidth - 2 * factor), 0);
4340 } else {
4341 if (sysmenuHint) {
4342 const int leftOffset = int(height - 8 * factor);
4343 rect.adjust(leftOffset, 0, 0, int(4 * factor));
4344 }
4345 if (minimizeHint)
4346 rect.adjust(0, 0, int(-buttonWidth - 2 * factor), 0);
4347 if (maximizeHint)
4348 rect.adjust(0, 0, int(-buttonWidth - 2 * factor), 0);
4349 if (contextHint)
4350 rect.adjust(0, 0, int(-buttonWidth - 2 * factor), 0);
4351 if (shadeHint)
4352 rect.adjust(0, 0, int(-buttonWidth - 2 * factor), 0);
4353 }
4354 rect.translate(0, int(2 * factor));
4355 }
4356 break;
4357
4358 case SC_TitleBarContextHelpButton:
4359 if (tb->titleBarFlags & Qt::WindowContextHelpButtonHint)
4360 offset += delta;
4361 Q_FALLTHROUGH();
4362 case SC_TitleBarMinButton:
4363 if (!isMinimized && (tb->titleBarFlags & Qt::WindowMinimizeButtonHint))
4364 offset += delta;
4365 else if (subControl == SC_TitleBarMinButton)
4366 break;
4367 Q_FALLTHROUGH();
4368 case SC_TitleBarNormalButton:
4369 if (isMinimized && (tb->titleBarFlags & Qt::WindowMinimizeButtonHint))
4370 offset += delta;
4371 else if (isMaximized && (tb->titleBarFlags & Qt::WindowMaximizeButtonHint))
4372 offset += delta;
4373 else if (subControl == SC_TitleBarNormalButton)
4374 break;
4375 Q_FALLTHROUGH();
4376 case SC_TitleBarMaxButton:
4377 if (!isMaximized && (tb->titleBarFlags & Qt::WindowMaximizeButtonHint))
4378 offset += delta;
4379 else if (subControl == SC_TitleBarMaxButton)
4380 break;
4381 Q_FALLTHROUGH();
4382 case SC_TitleBarShadeButton:
4383 if (!isMinimized && (tb->titleBarFlags & Qt::WindowShadeButtonHint))
4384 offset += delta;
4385 else if (subControl == SC_TitleBarShadeButton)
4386 break;
4387 Q_FALLTHROUGH();
4388 case SC_TitleBarUnshadeButton:
4389 if (isMinimized && (tb->titleBarFlags & Qt::WindowShadeButtonHint))
4390 offset += delta;
4391 else if (subControl == SC_TitleBarUnshadeButton)
4392 break;
4393 Q_FALLTHROUGH();
4394 case SC_TitleBarCloseButton:
4395 if (tb->titleBarFlags & Qt::WindowSystemMenuHint)
4396 offset += delta;
4397 else if (subControl == SC_TitleBarCloseButton)
4398 break;
4399
4400 rect.setRect(width - offset - controlTop + 1, controlTop,
4401 buttonWidth, buttonHeight);
4402 break;
4403
4404 case SC_TitleBarSysMenu: {
4405 const int controlTop = int(6 * factor);
4406 const int controlHeight = int(height - controlTop - 3 * factor);
4407 int iconExtent = proxy()->pixelMetric(PM_SmallIconSize, option);
4408 QSize iconSize = tb->icon.actualSize(QSize(iconExtent, iconExtent));
4409 if (tb->icon.isNull())
4410 iconSize = QSize(controlHeight, controlHeight);
4411 int hPad = (controlHeight - iconSize.height())/2;
4412 int vPad = (controlHeight - iconSize.width())/2;
4413 rect = QRect(frameWidth + hPad, controlTop + vPad, iconSize.width(), iconSize.height());
4414 rect.translate(0, int(3 * factor));
4415 }
4416 break;
4417
4418 default:
4419 break;
4420 }
4421 }
4422 break;
4423
4424#if QT_CONFIG(mdiarea)
4425 case CC_MdiControls: {
4426 int numSubControls = 0;
4427 if (option->subControls & SC_MdiCloseButton)
4428 ++numSubControls;
4429 if (option->subControls & SC_MdiMinButton)
4430 ++numSubControls;
4431 if (option->subControls & SC_MdiNormalButton)
4432 ++numSubControls;
4433 if (numSubControls == 0)
4434 break;
4435
4436 int buttonWidth = option->rect.width() / numSubControls;
4437 int offset = 0;
4438
4439 switch (subControl) {
4440 case SC_MdiCloseButton:
4441 // Only one sub control, no offset needed.
4442 if (numSubControls == 1)
4443 break;
4444 offset += buttonWidth;
4445 Q_FALLTHROUGH();
4446 case SC_MdiNormalButton:
4447 // No offset needed if
4448 // 1) There's only one sub control
4449 // 2) We have a close button and a normal button (offset already added in SC_MdiClose)
4450 if (numSubControls == 1 || (numSubControls == 2 && !(option->subControls & SC_MdiMinButton)))
4451 break;
4452 if (option->subControls & SC_MdiNormalButton)
4453 offset += buttonWidth;
4454 break;
4455 default:
4456 break;
4457 }
4458
4459 rect = QRect(offset, 0, buttonWidth, option->rect.height());
4460 break;
4461 }
4462#endif // QT_CONFIG(mdiarea)
4463
4464 default:
4465 return QWindowsStyle::subControlRect(control, option, subControl, widget);
4466 }
4467
4468 return visualRect(option->direction, option->rect, rect);
4469}
4470
4475 const QPoint &pos, const QWidget *widget) const
4476{
4477 return QWindowsStyle::hitTestComplexControl(control, option, pos, widget);
4478}
4479
4483int QWindowsVistaStyle::pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const
4484{
4486 return QWindowsStyle::pixelMetric(metric, option, widget);
4487
4489 if (ret != QWindowsStylePrivate::InvalidMetric)
4490 return int(QStyleHelper::dpiScaled(ret, option));
4491
4493 if (res != QWindowsStylePrivate::InvalidMetric)
4494 return qRound(qreal(res) * QWindowsStylePrivate::nativeMetricScaleFactor(widget));
4495
4496 res = 0;
4497
4498 switch (metric) {
4499 case PM_MenuBarPanelWidth:
4500 case PM_ButtonDefaultIndicator:
4501 res = 0;
4502 break;
4503
4504 case PM_DefaultFrameWidth:
4505 res = qobject_cast<const QListView*>(widget) ? 2 : 1;
4506 break;
4507 case PM_MenuPanelWidth:
4508 case PM_SpinBoxFrameWidth:
4509 res = 1;
4510 break;
4511
4512 case PM_TabBarTabOverlap:
4513 case PM_MenuHMargin:
4514 case PM_MenuVMargin:
4515 res = 2;
4516 break;
4517
4518 case PM_TabBarBaseOverlap:
4519 if (const auto *tab = qstyleoption_cast<const QStyleOptionTab *>(option)) {
4520 switch (tab->shape) {
4525 res = 1;
4526 break;
4529 res = 2;
4530 break;
4533 res = 3;
4534 break;
4535 }
4536 }
4537 break;
4538
4539 case PM_SplitterWidth:
4541 break;
4542
4543 case PM_MdiSubWindowMinimizedWidth:
4544 res = 160;
4545 break;
4546
4547#if QT_CONFIG(toolbar)
4548 case PM_ToolBarHandleExtent:
4550 break;
4551
4552#endif // QT_CONFIG(toolbar)
4553 case PM_DockWidgetSeparatorExtent:
4554 case PM_DockWidgetTitleMargin:
4556 break;
4557
4558 case PM_ButtonShiftHorizontal:
4559 case PM_ButtonShiftVertical:
4560 res = qstyleoption_cast<const QStyleOptionToolButton *>(option) ? 1 : 0;
4561 break;
4562
4563 default:
4564 res = QWindowsStyle::pixelMetric(metric, option, widget);
4565 }
4566
4567 return res;
4568}
4569
4574{
4575 QWindowsStyle::polish(widget);
4577 return;
4578
4579 if (false
4580#if QT_CONFIG(abstractbutton)
4581 || qobject_cast<QAbstractButton*>(widget)
4582#endif // QT_CONFIG(abstractbutton)
4583 || qobject_cast<QToolButton*>(widget)
4584 || qobject_cast<QTabBar*>(widget)
4585#if QT_CONFIG(combobox)
4586 || qobject_cast<QComboBox*>(widget)
4587#endif // QT_CONFIG(combobox)
4588 || qobject_cast<QScrollBar*>(widget)
4589 || qobject_cast<QSlider*>(widget)
4590 || qobject_cast<QHeaderView*>(widget)
4591#if QT_CONFIG(spinbox)
4592 || qobject_cast<QAbstractSpinBox*>(widget)
4593 || qobject_cast<QSpinBox*>(widget)
4594#endif // QT_CONFIG(spinbox)
4595 ) {
4597 }
4598
4599#if QT_CONFIG(rubberband)
4600 if (qobject_cast<QRubberBand*>(widget))
4602#endif
4603
4604#if QT_CONFIG(lineedit)
4605 if (qobject_cast<QLineEdit*>(widget))
4607 else
4608#endif // QT_CONFIG(lineedit)
4609 if (qobject_cast<QGroupBox*>(widget))
4611#if QT_CONFIG(commandlinkbutton)
4612 else if (qobject_cast<QCommandLinkButton*>(widget)) {
4613 widget->setProperty("_qt_usingVistaStyle", true);
4614 QFont buttonFont = widget->font();
4615 buttonFont.setFamilies(QStringList{QLatin1String("Segoe UI")});
4616 widget->setFont(buttonFont);
4617 QPalette pal = widget->palette();
4620 widget->setPalette(pal);
4621 }
4622#endif // QT_CONFIG(commandlinkbutton)
4623 else if (widget->inherits("QTipLabel")) {
4624 //note that since tooltips are not reused
4625 //we do not have to care about unpolishing
4626 widget->setContentsMargins(3, 0, 4, 0);
4627 COLORREF bgRef;
4628 HTHEME theme = OpenThemeData(widget ? QWindowsVistaStylePrivate::winId(widget) : nullptr, L"TOOLTIP");
4629 if (theme && SUCCEEDED(GetThemeColor(theme, TTP_STANDARD, TTSS_NORMAL, TMT_TEXTCOLOR, &bgRef))) {
4630 QColor textColor = QColor::fromRgb(bgRef);
4631 QPalette pal;
4633 pal.setResolveMask(0);
4634 widget->setPalette(pal);
4635 }
4636 } else if (qobject_cast<QMessageBox *> (widget)) {
4638#if QT_CONFIG(dialogbuttonbox)
4639 QDialogButtonBox *buttonBox = widget->findChild<QDialogButtonBox *>(QLatin1String("qt_msgbox_buttonbox"));
4640 if (buttonBox)
4641 buttonBox->setContentsMargins(0, 9, 0, 0);
4642#endif
4643 }
4644#if QT_CONFIG(inputdialog)
4645 else if (qobject_cast<QInputDialog *> (widget)) {
4647#if QT_CONFIG(dialogbuttonbox)
4648 QDialogButtonBox *buttonBox = widget->findChild<QDialogButtonBox *>(QLatin1String("qt_inputdlg_buttonbox"));
4649 if (buttonBox)
4650 buttonBox->setContentsMargins(0, 9, 0, 0);
4651#endif
4652 }
4653#endif // QT_CONFIG(inputdialog)
4654 else if (QTreeView *tree = qobject_cast<QTreeView *> (widget)) {
4655 tree->viewport()->setAttribute(Qt::WA_Hover);
4656 }
4657 else if (QListView *list = qobject_cast<QListView *> (widget)) {
4658 list->viewport()->setAttribute(Qt::WA_Hover);
4659 }
4660}
4661
4666{
4667 Q_D(QWindowsVistaStyle);
4668
4669#if QT_CONFIG(rubberband)
4670 if (qobject_cast<QRubberBand*>(widget))
4672#endif
4673
4674 // Unpolish of widgets is the first thing that
4675 // happens when a theme changes, or the theme
4676 // engine is turned off. So we detect it here.
4677 bool oldState = QWindowsVistaStylePrivate::useVista();
4679 if ((oldState != newState) && newState) {
4680 d->cleanup(true);
4681 d->init(true);
4682 } else {
4683 // Cleanup handle map, if just changing style,
4684 // or turning it on. In both cases the values
4685 // already in the map might be old (other style).
4686 d->cleanupHandleMap();
4687 }
4688 if (false
4689 #if QT_CONFIG(abstractbutton)
4690 || qobject_cast<QAbstractButton*>(widget)
4691 #endif
4692 || qobject_cast<QToolButton*>(widget)
4693 || qobject_cast<QTabBar*>(widget)
4694 #if QT_CONFIG(combobox)
4695 || qobject_cast<QComboBox*>(widget)
4696 #endif // QT_CONFIG(combobox)
4697 || qobject_cast<QScrollBar*>(widget)
4698 || qobject_cast<QSlider*>(widget)
4699 || qobject_cast<QHeaderView*>(widget)
4700 #if QT_CONFIG(spinbox)
4701 || qobject_cast<QAbstractSpinBox*>(widget)
4702 || qobject_cast<QSpinBox*>(widget)
4703 #endif // QT_CONFIG(spinbox)
4704 ) {
4706 }
4707
4708 QWindowsStyle::unpolish(widget);
4709
4710 d->stopAnimation(widget);
4711
4712#if QT_CONFIG(lineedit)
4713 if (qobject_cast<QLineEdit*>(widget))
4715 else {
4716#endif // QT_CONFIG(lineedit)
4717 if (qobject_cast<QGroupBox*>(widget))
4719 else if (qobject_cast<QMessageBox *> (widget)) {
4721#if QT_CONFIG(dialogbuttonbox)
4722 QDialogButtonBox *buttonBox = widget->findChild<QDialogButtonBox *>(QLatin1String("qt_msgbox_buttonbox"));
4723 if (buttonBox)
4724 buttonBox->setContentsMargins(0, 0, 0, 0);
4725#endif
4726 }
4727#if QT_CONFIG(inputdialog)
4728 else if (qobject_cast<QInputDialog *> (widget)) {
4730#if QT_CONFIG(dialogbuttonbox)
4731 QDialogButtonBox *buttonBox = widget->findChild<QDialogButtonBox *>(QLatin1String("qt_inputdlg_buttonbox"));
4732 if (buttonBox)
4733 buttonBox->setContentsMargins(0, 0, 0, 0);
4734#endif
4735 }
4736#endif // QT_CONFIG(inputdialog)
4737 else if (QTreeView *tree = qobject_cast<QTreeView *> (widget)) {
4738 tree->viewport()->setAttribute(Qt::WA_Hover, false);
4739 }
4740#if QT_CONFIG(commandlinkbutton)
4741 else if (qobject_cast<QCommandLinkButton*>(widget)) {
4742 QFont font = QApplication::font("QCommandLinkButton");
4743 QFont widgetFont = widget->font();
4744 widgetFont.setFamilies(font.families()); //Only family set by polish
4745 widget->setFont(widgetFont);
4746 }
4747#endif // QT_CONFIG(commandlinkbutton)
4748 }
4749}
4750
4755{
4756 Q_D(QWindowsVistaStyle);
4757
4758 if (QGuiApplication::styleHints()->colorScheme() == Qt::ColorScheme::Dark) {
4759 // System runs in dark mode, but the Vista style cannot use a dark palette.
4760 // Overwrite with the light system palette.
4762 if (auto nativeWindowsApp = dynamic_cast<QWindowsApplication *>(QGuiApplicationPrivate::platformIntegration()))
4763 nativeWindowsApp->populateLightSystemPalette(pal);
4764 }
4765
4767 d->alphaCache.clear();
4768 d->hasInitColors = false;
4769
4770 if (!d->hasInitColors) {
4771 // Get text color for group box labels
4772 QWindowsThemeData theme(nullptr, nullptr, QWindowsVistaStylePrivate::ButtonTheme, 0, 0);
4773 COLORREF cref;
4774 GetThemeColor(theme.handle(), BP_GROUPBOX, GBS_NORMAL, TMT_TEXTCOLOR, &cref);
4775 d->groupBoxTextColor = qRgb(GetRValue(cref), GetGValue(cref), GetBValue(cref));
4776 GetThemeColor(theme.handle(), BP_GROUPBOX, GBS_DISABLED, TMT_TEXTCOLOR, &cref);
4777 d->groupBoxTextColorDisabled = qRgb(GetRValue(cref), GetGValue(cref), GetBValue(cref));
4778 // Where does this color come from?
4779 //GetThemeColor(theme.handle(), TKP_TICS, TSS_NORMAL, TMT_COLOR, &cref);
4780 d->sliderTickColor = qRgb(165, 162, 148);
4781 d->hasInitColors = true;
4782 }
4783
4784 QWindowsStyle::polish(pal);
4786}
4787
4792{
4793 // Override windows theme palettes to light
4794 if (qApp->styleHints()->colorScheme() == Qt::ColorScheme::Dark) {
4795 static const char* themedWidgets[] = {
4796 "QToolButton",
4797 "QAbstractButton",
4798 "QCheckBox",
4799 "QRadioButton",
4800 "QHeaderView",
4801 "QAbstractItemView",
4802 "QMessageBoxLabel",
4803 "QTabBar",
4804 "QLabel",
4805 "QGroupBox",
4806 "QMenu",
4807 "QMenuBar",
4808 "QTextEdit",
4809 "QTextControl",
4810 "QLineEdit"
4811 };
4812 for (const auto& themedWidget : std::as_const(themedWidgets)) {
4813 auto defaultResolveMask = QApplication::palette().resolveMask();
4814 auto widgetResolveMask = QApplication::palette(themedWidget).resolveMask();
4815 if (widgetResolveMask != defaultResolveMask)
4817 }
4818 }
4819
4820 QWindowsStyle::polish(app);
4821}
4822
4827 const QWidget *widget) const
4828{
4830 return QWindowsStyle::standardPixmap(standardPixmap, option, widget);
4831 }
4832
4833 switch (standardPixmap) {
4834 case SP_TitleBarMaxButton:
4835 case SP_TitleBarCloseButton:
4836 if (qstyleoption_cast<const QStyleOptionDockWidget *>(option)) {
4837 if (widget && widget->isWindow()) {
4838 QWindowsThemeData theme(widget, nullptr, QWindowsVistaStylePrivate::WindowTheme, WP_SMALLCLOSEBUTTON, CBS_NORMAL);
4839 if (theme.isValid()) {
4840 const QSize size = (theme.size() * QWindowsStylePrivate::nativeMetricScaleFactor(widget)).toSize();
4841 return QIcon(QWindowsStyle::standardPixmap(standardPixmap, option, widget)).pixmap(size);
4842 }
4843 }
4844 }
4845 break;
4846
4847 default:
4848 break;
4849 }
4850
4851 return QWindowsStyle::standardPixmap(standardPixmap, option, widget);
4852}
4853
4857QIcon QWindowsVistaStyle::standardIcon(StandardPixmap standardIcon,
4858 const QStyleOption *option,
4859 const QWidget *widget) const
4860{
4862 return QWindowsStyle::standardIcon(standardIcon, option, widget);
4863 }
4864
4865 auto *d = const_cast<QWindowsVistaStylePrivate*>(d_func());
4866
4867 switch (standardIcon) {
4868 case SP_TitleBarMaxButton:
4869 if (qstyleoption_cast<const QStyleOptionDockWidget *>(option)) {
4870 if (d->dockFloat.isNull()) {
4872 WP_SMALLCLOSEBUTTON, CBS_NORMAL);
4874 WP_MAXBUTTON, MAXBS_NORMAL);
4875 if (theme.isValid()) {
4876 const QSize size = (themeSize.size() * QWindowsStylePrivate::nativeMetricScaleFactor(widget)).toSize();
4877 QPixmap pm(size);
4879 QPainter p(&pm);
4880 theme.painter = &p;
4881 theme.rect = QRect(QPoint(0, 0), size);
4882 d->drawBackground(theme);
4883 d->dockFloat.addPixmap(pm, QIcon::Normal, QIcon::Off); // Normal
4885 theme.stateId = MAXBS_PUSHED;
4886 d->drawBackground(theme);
4887 d->dockFloat.addPixmap(pm, QIcon::Normal, QIcon::On); // Pressed
4889 theme.stateId = MAXBS_HOT;
4890 d->drawBackground(theme);
4891 d->dockFloat.addPixmap(pm, QIcon::Active, QIcon::Off); // Hover
4893 theme.stateId = MAXBS_INACTIVE;
4894 d->drawBackground(theme);
4895 d->dockFloat.addPixmap(pm, QIcon::Disabled, QIcon::Off); // Disabled
4896 }
4897 }
4898 if (widget && widget->isWindow())
4899 return d->dockFloat;
4900 }
4901 break;
4902
4903 case SP_TitleBarCloseButton:
4904 if (qstyleoption_cast<const QStyleOptionDockWidget *>(option)) {
4905 if (d->dockClose.isNull()) {
4907 WP_SMALLCLOSEBUTTON, CBS_NORMAL);
4908 if (theme.isValid()) {
4909 const QSize size = (theme.size() * QWindowsStylePrivate::nativeMetricScaleFactor(widget)).toSize();
4910 QPixmap pm(size);
4912 QPainter p(&pm);
4913 theme.painter = &p;
4914 theme.partId = WP_CLOSEBUTTON; // ####
4915 theme.rect = QRect(QPoint(0, 0), size);
4916 d->drawBackground(theme);
4917 d->dockClose.addPixmap(pm, QIcon::Normal, QIcon::Off); // Normal
4919 theme.stateId = CBS_PUSHED;
4920 d->drawBackground(theme);
4921 d->dockClose.addPixmap(pm, QIcon::Normal, QIcon::On); // Pressed
4923 theme.stateId = CBS_HOT;
4924 d->drawBackground(theme);
4925 d->dockClose.addPixmap(pm, QIcon::Active, QIcon::Off); // Hover
4927 theme.stateId = CBS_INACTIVE;
4928 d->drawBackground(theme);
4929 d->dockClose.addPixmap(pm, QIcon::Disabled, QIcon::Off); // Disabled
4930 }
4931 }
4932 if (widget && widget->isWindow())
4933 return d->dockClose;
4934 }
4935 break;
4936
4937 case SP_TitleBarNormalButton:
4938 if (qstyleoption_cast<const QStyleOptionDockWidget *>(option)) {
4939 if (d->dockFloat.isNull()) {
4941 WP_SMALLCLOSEBUTTON, CBS_NORMAL);
4943 WP_RESTOREBUTTON, RBS_NORMAL);
4944 if (theme.isValid()) {
4945 const QSize size = (themeSize.size() * QWindowsStylePrivate::nativeMetricScaleFactor(widget)).toSize();
4946 QPixmap pm(size);
4948 QPainter p(&pm);
4949 theme.painter = &p;
4950 theme.rect = QRect(QPoint(0, 0), size);
4951 d->drawBackground(theme);
4952 d->dockFloat.addPixmap(pm, QIcon::Normal, QIcon::Off); // Normal
4954 theme.stateId = RBS_PUSHED;
4955 d->drawBackground(theme);
4956 d->dockFloat.addPixmap(pm, QIcon::Normal, QIcon::On); // Pressed
4958 theme.stateId = RBS_HOT;
4959 d->drawBackground(theme);
4960 d->dockFloat.addPixmap(pm, QIcon::Active, QIcon::Off); // Hover
4962 theme.stateId = RBS_INACTIVE;
4963 d->drawBackground(theme);
4964 d->dockFloat.addPixmap(pm, QIcon::Disabled, QIcon::Off); // Disabled
4965 }
4966 }
4967 if (widget && widget->isWindow())
4968 return d->dockFloat;
4969 }
4970 break;
4971
4972 case SP_CommandLink: {
4975 if (theme.isValid()) {
4976 const QSize size = theme.size().toSize();
4977 QIcon linkGlyph;
4978 QPixmap pm(size);
4980 QPainter p(&pm);
4981 theme.painter = &p;
4982 theme.rect = QRect(QPoint(0, 0), size);
4983 d->drawBackground(theme);
4984 linkGlyph.addPixmap(pm, QIcon::Normal, QIcon::Off); // Normal
4986
4987 theme.stateId = CMDLGS_PRESSED;
4988 d->drawBackground(theme);
4989 linkGlyph.addPixmap(pm, QIcon::Normal, QIcon::On); // Pressed
4991
4992 theme.stateId = CMDLGS_HOT;
4993 d->drawBackground(theme);
4994 linkGlyph.addPixmap(pm, QIcon::Active, QIcon::Off); // Hover
4996
4997 theme.stateId = CMDLGS_DISABLED;
4998 d->drawBackground(theme);
4999 linkGlyph.addPixmap(pm, QIcon::Disabled, QIcon::Off); // Disabled
5000 return linkGlyph;
5001 }
5002 break;
5003 }
5004
5005 default:
5006 break;
5007 }
5008
5009 return QWindowsStyle::standardIcon(standardIcon, option, widget);
5010}
5011
bool isActive
The QAbstractItemView class provides the basic functionality for item view classes.
SelectionMode
This enum indicates how the view responds to user selections:
SelectionBehavior
\value SelectItems Selecting single items.
The QAbstractSpinBox class provides a spinbox and a line edit to display values.
\inmodule QtGui
The QApplication class manages the GUI application's control flow and main settings.
static void setPalette(const QPalette &, const char *className=nullptr)
Changes the application palette to palette.
static QPalette palette()
Returns the current application palette.
static QFont font()
Returns the default application font.
The QBackingStore class provides a drawing area for QWindow.
void setEndImage(const QImage &image)
void setStartImage(const QImage &image)
\inmodule QtGui
Definition qbrush.h:30
const QColor & color() const
Returns the brush color.
Definition qbrush.h:121
\inmodule QtCore
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition qcolor.h:31
QColor darker(int f=200) const noexcept
Definition qcolor.cpp:2857
static QColor fromRgb(QRgb rgb) noexcept
Static convenience function that returns a QColor constructed from the given QRgb value rgb.
Definition qcolor.cpp:2369
int red() const noexcept
Returns the red color component of this color.
Definition qcolor.cpp:1528
int blue() const noexcept
Returns the blue color component of this color.
Definition qcolor.cpp:1583
int green() const noexcept
Returns the green color component of this color.
Definition qcolor.cpp:1555
QRect subElementRect(SubElement r, const QStyleOption *opt, const QWidget *widget=nullptr) const override
\reimp
void drawControl(ControlElement element, const QStyleOption *opt, QPainter *p, const QWidget *w=nullptr) const override
\reimp
static QCoreApplication * instance() noexcept
Returns a pointer to the application's QCoreApplication (or QGuiApplication/QApplication) instance.
The QDialogButtonBox class is a widget that presents buttons in a layout that is appropriate to the c...
The QDockWidget class provides a widget that can be docked inside a QMainWindow or floated as a top-l...
Definition qdockwidget.h:20
QString elidedText(const QString &text, Qt::TextElideMode mode, int width, int flags=0) const
\reentrant
Definition qfont.h:22
void setFamilies(const QStringList &)
Definition qfont.cpp:2721
QStringList families() const
Definition qfont.cpp:2699
void setBold(bool)
If enable is true sets the font's weight to \l{Weight}{QFont::Bold}; otherwise sets the weight to \l{...
Definition qfont.h:373
void setColorAt(qreal pos, const QColor &color)
Creates a stop point at the given position with the given color.
Definition qbrush.cpp:1563
static QPlatformIntegration * platformIntegration()
static QPlatformNativeInterface * platformNativeInterface()
static QWindowList allWindows()
Returns a list of all the windows in the application.
static QStyleHints * styleHints()
Returns the application's style hints.
QIcon windowIcon
the default window icon
T value(const Key &key) const noexcept
Definition qhash.h:1054
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
Definition qhash.h:1303
The QIcon class provides scalable icons in different modes and states.
Definition qicon.h:20
Mode
This enum type describes the mode for which a pixmap is intended to be used.
Definition qicon.h:22
@ Disabled
Definition qicon.h:22
@ Normal
Definition qicon.h:22
@ Active
Definition qicon.h:22
qint64 cacheKey() const
Returns a number that identifies the contents of this QIcon object.
Definition qicon.cpp:819
@ Off
Definition qicon.h:23
@ On
Definition qicon.h:23
QPixmap pixmap(const QSize &size, Mode mode=Normal, State state=Off) const
Returns a pixmap with the requested size, mode, and state, generating one if necessary.
Definition qicon.cpp:834
\inmodule QtGui
Definition qimage.h:37
QImage copy(const QRect &rect=QRect()) const
Returns a sub-area of the image as a new image.
Format
The following image formats are available in Qt.
Definition qimage.h:41
@ Format_RGB32
Definition qimage.h:46
@ Format_ARGB32_Premultiplied
Definition qimage.h:48
@ Format_ARGB32
Definition qimage.h:47
\inmodule QtCore\compares equality \compareswith equality QLineF \endcompareswith
Definition qline.h:18
\inmodule QtGui
Definition qbrush.h:394
The QListView class provides a list or icon view onto a model.
Definition qlistview.h:17
\inmodule QtCore
Definition qmargins.h:270
constexpr qreal right() const noexcept
Returns the right margin.
Definition qmargins.h:383
constexpr qreal left() const noexcept
Returns the left margin.
Definition qmargins.h:377
constexpr qreal top() const noexcept
Returns the top margin.
Definition qmargins.h:380
constexpr qreal bottom() const noexcept
Returns the bottom margin.
Definition qmargins.h:386
Native interface to QGuiApplication, to be retrieved from QPlatformIntegration. \inmodule QtGui.
\inmodule QtCore
Definition qobject.h:103
T findChild(QAnyStringView aName, Qt::FindChildOptions options=Qt::FindChildrenRecursively) const
Returns the child of this object that can be cast into type T and that is called name,...
Definition qobject.h:155
QVariant property(const char *name) const
Returns the value of the object's name property.
Definition qobject.cpp:4323
bool setProperty(const char *name, const QVariant &value)
Sets the value of the object's name property to value.
bool inherits(const char *classname) const
Returns true if this object is an instance of a class that inherits className or a QObject subclass t...
Definition qobject.h:348
qreal devicePixelRatio() const
virtual int devType() const
qreal devicePixelRatioF() const
QRegion systemClip() const
QPaintDevice * paintDevice() const
Returns the device that this engine is painting on, if painting is active; otherwise returns \nullptr...
The QPainter class performs low-level painting on widgets and other paint devices.
Definition qpainter.h:46
const QPen & pen() const
Returns the painter's current pen.
void setClipping(bool enable)
Enables clipping if enable is true, or disables clipping if enable is false.
void drawRect(const QRectF &rect)
Draws the current rectangle with the current pen and brush.
Definition qpainter.h:519
QPaintDevice * device() const
Returns the paint device on which this painter is currently painting, or \nullptr if the painter is n...
qreal opacity() const
void setClipRect(const QRectF &, Qt::ClipOperation op=Qt::ReplaceClip)
Enables clipping, and sets the clip region to the given rectangle using the given clip operation.
void setPen(const QColor &color)
This is an overloaded member function, provided for convenience. It differs from the above function o...
void drawLine(const QLineF &line)
Draws a line defined by line.
Definition qpainter.h:442
QPaintEngine * paintEngine() const
Returns the paint engine that the painter is currently operating on if the painter is active; otherwi...
void setBrushOrigin(int x, int y)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qpainter.h:698
const QFont & font() const
Returns the currently set font used for drawing text.
void restore()
Restores the current painter state (pops a saved state off the stack).
void rotate(qreal a)
Rotates the coordinate system clockwise.
QFontMetrics fontMetrics() const
Returns the font metrics for the painter if the painter is active.
void drawLines(const QLineF *lines, int lineCount)
Draws the first lineCount lines in the array lines using the current pen.
void save()
Saves the current painter state (pushes the state onto a stack).
void drawImage(const QRectF &targetRect, const QImage &image, const QRectF &sourceRect, Qt::ImageConversionFlags flags=Qt::AutoColor)
Draws the rectangular portion source of the given image into the target rectangle in the paint device...
void setFont(const QFont &f)
Sets the painter's font to the given font.
QRegion clipRegion() const
Returns the currently set clip region.
void drawText(const QPointF &p, const QString &s)
Draws the given text with the currently defined text direction, beginning at the given position.
const QTransform & deviceTransform() const
Returns the matrix that transforms from logical coordinates to device coordinates of the platform dep...
void drawPixmap(const QRectF &targetRect, const QPixmap &pixmap, const QRectF &sourceRect)
Draws the rectangular portion source of the given pixmap into the given target in the paint device.
void eraseRect(const QRectF &)
Erases the area inside the given rectangle.
QPoint brushOrigin() const
Returns the currently set brush origin.
void setBrush(const QBrush &brush)
Sets the painter's brush to the given brush.
@ CompositionMode_SourceIn
Definition qpainter.h:103
bool isActive() const
Returns true if begin() has been called and end() has not yet been called; otherwise returns false.
void translate(const QPointF &offset)
Translates the coordinate system by the given offset; i.e.
void fillRect(const QRectF &, const QBrush &)
Fills the given rectangle with the brush specified.
bool hasClipping() const
Returns true if clipping has been set; otherwise returns false.
void setClipRegion(const QRegion &, Qt::ClipOperation op=Qt::ReplaceClip)
Sets the clip region to the given region using the specified clip operation.
The QPalette class contains color groups for each widget state.
Definition qpalette.h:19
const QBrush & brush(ColorGroup cg, ColorRole cr) const
Returns the brush in the specified color group, used for the given color role.
Definition qpalette.cpp:748
const QColor & color(ColorGroup cg, ColorRole cr) const
Returns the color in the specified color group, used for the given color role.
Definition qpalette.h:67
void setBrush(ColorRole cr, const QBrush &brush)
Sets the brush for the given color role to the specified brush for all groups in the palette.
Definition qpalette.h:151
void setResolveMask(ResolveMask mask)
ColorGroup
\value Disabled \value Active \value Inactive \value Normal synonym for Active
Definition qpalette.h:49
@ Inactive
Definition qpalette.h:49
@ Disabled
Definition qpalette.h:49
void setColor(ColorGroup cg, ColorRole cr, const QColor &color)
Sets the color in the specified color group, used for the given color role, to the specified solid co...
Definition qpalette.h:146
const QBrush & base() const
Returns the base brush of the current color group.
Definition qpalette.h:89
@ HighlightedText
Definition qpalette.h:53
@ BrightText
Definition qpalette.h:52
@ AlternateBase
Definition qpalette.h:55
@ ButtonText
Definition qpalette.h:52
@ WindowText
Definition qpalette.h:51
@ Highlight
Definition qpalette.h:53
@ ToolTipText
Definition qpalette.h:57
\inmodule QtGui
Definition qpen.h:28
static bool find(const QString &key, QPixmap *pixmap)
Looks for a cached pixmap associated with the given key in the cache.
static bool insert(const QString &key, const QPixmap &pixmap)
Inserts a copy of the pixmap pixmap associated with the key into the cache.
static void clear()
Removes all pixmaps from the cache.
Returns a copy of the pixmap that is transformed using the given transformation transform and transfo...
Definition qpixmap.h:27
bool isNull() const
Returns true if this is a null pixmap; otherwise returns false.
Definition qpixmap.cpp:456
void fill(const QColor &fillColor=Qt::white)
Fills the pixmap with the given color.
Definition qpixmap.cpp:850
static QPixmap fromImage(const QImage &image, Qt::ImageConversionFlags flags=Qt::AutoColor)
Converts the given image to a pixmap using the specified flags to control the conversion.
Definition qpixmap.cpp:1437
The QPlatformNativeInterface class provides an abstraction for retrieving native resource handles.
virtual void * nativeResourceForBackingStore(const QByteArray &resource, QBackingStore *backingStore)
\inmodule QtCore\reentrant
Definition qpoint.h:217
\inmodule QtCore\reentrant
Definition qpoint.h:25
\inmodule QtCore\reentrant
Definition qrect.h:484
constexpr void moveTo(qreal x, qreal y) noexcept
Moves the rectangle, leaving the top-left corner at the given position (x, y).
Definition qrect.h:750
constexpr qreal height() const noexcept
Returns the height of the rectangle.
Definition qrect.h:732
constexpr qreal width() const noexcept
Returns the width of the rectangle.
Definition qrect.h:729
constexpr QPointF topLeft() const noexcept
Returns the position of the rectangle's top-left corner.
Definition qrect.h:511
constexpr QSizeF size() const noexcept
Returns the size of the rectangle.
Definition qrect.h:735
constexpr QRect toRect() const noexcept
Returns a QRect based on the values of this rectangle.
Definition qrect.h:859
\inmodule QtCore\reentrant
Definition qrect.h:30
constexpr void adjust(int x1, int y1, int x2, int y2) noexcept
Adds dx1, dy1, dx2 and dy2 respectively to the existing coordinates of the rectangle.
Definition qrect.h:373
constexpr int height() const noexcept
Returns the height of the rectangle.
Definition qrect.h:239
constexpr int bottom() const noexcept
Returns the y-coordinate of the rectangle's bottom edge.
Definition qrect.h:182
constexpr QPoint topLeft() const noexcept
Returns the position of the rectangle's top-left corner.
Definition qrect.h:221
constexpr QRect adjusted(int x1, int y1, int x2, int y2) const noexcept
Returns a new rectangle with dx1, dy1, dx2 and dy2 added respectively to the existing coordinates of ...
Definition qrect.h:370
constexpr int top() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:176
constexpr QPoint topRight() const noexcept
Returns the position of the rectangle's top-right corner.
Definition qrect.h:227
constexpr void setBottom(int pos) noexcept
Sets the bottom edge of the rectangle to the given y coordinate.
Definition qrect.h:200
constexpr int left() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:173
constexpr void setRect(int x, int y, int w, int h) noexcept
Sets the coordinates of the rectangle's top-left corner to ({x}, {y}), and its size to the given widt...
Definition qrect.h:346
constexpr int x() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:185
constexpr void setWidth(int w) noexcept
Sets the width of the rectangle to the given width.
Definition qrect.h:381
constexpr QSize size() const noexcept
Returns the size of the rectangle.
Definition qrect.h:242
constexpr void setCoords(int x1, int y1, int x2, int y2) noexcept
Sets the coordinates of the rectangle's top-left corner to (x1, y1), and the coordinates of its botto...
Definition qrect.h:362
constexpr int width() const noexcept
Returns the width of the rectangle.
Definition qrect.h:236
QRect united(const QRect &other) const noexcept
Definition qrect.h:420
constexpr int y() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:188
constexpr void setHeight(int h) noexcept
Sets the height of the rectangle to the given height.
Definition qrect.h:384
constexpr void moveTop(int pos) noexcept
Moves the rectangle vertically, leaving the rectangle's top edge at the given y coordinate.
Definition qrect.h:289
constexpr QPoint center() const noexcept
Returns the center point of the rectangle.
Definition qrect.h:233
constexpr void setTop(int pos) noexcept
Sets the top edge of the rectangle to the given y coordinate.
Definition qrect.h:194
The QRegion class specifies a clip region for a painter.
Definition qregion.h:27
QRect boundingRect() const noexcept
Returns the bounding rectangle of this region.
int rectCount() const noexcept
bool isEmpty() const
Returns true if the region is empty; otherwise returns false.
\inmodule QtCore
Definition qsize.h:208
constexpr QSize toSize() const noexcept
Returns an integer based copy of this size.
Definition qsize.h:401
constexpr qreal width() const noexcept
Returns the width.
Definition qsize.h:332
constexpr bool isEmpty() const noexcept
Returns true if either of the width and height is less than or equal to 0; otherwise returns false.
Definition qsize.h:326
constexpr qreal height() const noexcept
Returns the height.
Definition qsize.h:335
\inmodule QtCore
Definition qsize.h:25
constexpr int height() const noexcept
Returns the height.
Definition qsize.h:133
constexpr int width() const noexcept
Returns the width.
Definition qsize.h:130
constexpr int & rheight() noexcept
Returns a reference to the height.
Definition qsize.h:157
constexpr void setWidth(int w) noexcept
Sets the width to the given width.
Definition qsize.h:136
constexpr int & rwidth() noexcept
Returns a reference to the width.
Definition qsize.h:154
constexpr bool isEmpty() const noexcept
Returns true if either of the width and height is less than or equal to 0; otherwise returns false.
Definition qsize.h:124
constexpr void setHeight(int h) noexcept
Sets the height to the given height.
Definition qsize.h:139
@ TicksAbove
Definition qslider.h:27
@ TicksRight
Definition qslider.h:30
@ TicksBelow
Definition qslider.h:29
@ TicksLeft
Definition qslider.h:28
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5871
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:8084
void setDuration(int duration)
void setStartTime(QTime time)
The QStyleHintReturnMask class provides style hints that return a QRegion.
\variable QStyleOptionGraphicsItem::exposedRect
\variable QStyleOptionHeaderV2::textElideMode
ButtonFeatures features
\variable QStyleOptionToolButton::features
\variable QStyleOptionMenuItem::menuItemType
QStyle::SubControls activeSubControls
\variable QStyleOption::palette
\variable QStyleOptionFrame::features
The QStyleOptionHeader class is used to describe the parameters for drawing a header.
SortIndicator
Indicates which direction the sort indicator should be drawn.
\variable QStyleOptionProgressBar::minimum
\variable QStyleOptionToolBox::selectedPosition
\variable QStyleOptionDockWidget::title
The QStyleOption class stores the parameters used by QStyle functions.
QStyle::State state
QObject * styleObject
The QStyle class is an abstract base class that encapsulates the look and feel of a GUI.
Definition qstyle.h:29
@ State_MouseOver
Definition qstyle.h:80
@ State_Sunken
Definition qstyle.h:69
@ State_Active
Definition qstyle.h:83
@ State_Open
Definition qstyle.h:85
@ State_Enabled
Definition qstyle.h:67
@ State_Horizontal
Definition qstyle.h:74
@ State_On
Definition qstyle.h:72
@ State_Selected
Definition qstyle.h:82
@ SP_TitleBarCloseButton
Definition qstyle.h:720
@ SP_TitleBarMaxButton
Definition qstyle.h:719
static int sliderPositionFromValue(int min, int max, int val, int space, bool upsideDown=false)
Converts the given logicalValue to a pixel position.
Definition qstyle.cpp:2222
static QRect visualRect(Qt::LayoutDirection direction, const QRect &boundingRect, const QRect &logicalRect)
Returns the given logicalRectangle converted to screen coordinates based on the specified direction.
Definition qstyle.cpp:2143
PixelMetric
This enum describes the various available pixel metrics.
Definition qstyle.h:413
@ PM_MenuVMargin
Definition qstyle.h:452
@ PM_MenuPanelWidth
Definition qstyle.h:453
@ PM_ScrollBarExtent
Definition qstyle.h:426
@ PM_DockWidgetFrameWidth
Definition qstyle.h:437
@ PM_TitleBarHeight
Definition qstyle.h:448
@ PM_DockWidgetTitleMargin
Definition qstyle.h:505
@ PM_ExclusiveIndicatorHeight
Definition qstyle.h:465
@ PM_MdiSubWindowFrameWidth
Definition qstyle.h:473
@ PM_DockWidgetTitleBarButtonMargin
Definition qstyle.h:509
@ PM_IndicatorWidth
Definition qstyle.h:462
@ PM_IndicatorHeight
Definition qstyle.h:463
@ PM_MenuButtonIndicator
Definition qstyle.h:416
@ PM_HeaderMargin
Definition qstyle.h:476
@ PM_MenuHMargin
Definition qstyle.h:451
@ PM_ProgressBarChunkWidth
Definition qstyle.h:445
@ PM_SliderThickness
Definition qstyle.h:429
@ PM_ExclusiveIndicatorWidth
Definition qstyle.h:464
@ PM_ScrollBarSliderMin
Definition qstyle.h:427
@ CC_MdiControls
Definition qstyle.h:340
@ CC_TitleBar
Definition qstyle.h:337
PrimitiveElement
This enum describes the various primitive elements.
Definition qstyle.h:102
@ PE_FrameLineEdit
Definition qstyle.h:108
@ PE_IndicatorCheckBox
Definition qstyle.h:131
@ PE_IndicatorRadioButton
Definition qstyle.h:136
@ SE_ItemViewItemDecoration
Definition qstyle.h:304
@ SE_ItemViewItemFocusRect
Definition qstyle.h:306
@ SE_ItemViewItemText
Definition qstyle.h:305
SubControl
This enum describes the available sub controls.
Definition qstyle.h:347
@ SC_TitleBarMinButton
Definition qstyle.h:377
@ SC_TitleBarUnshadeButton
Definition qstyle.h:382
@ SC_MdiMinButton
Definition qstyle.h:395
@ SC_TitleBarNormalButton
Definition qstyle.h:380
@ SC_TitleBarShadeButton
Definition qstyle.h:381
@ SC_TitleBarSysMenu
Definition qstyle.h:376
@ SC_TitleBarMaxButton
Definition qstyle.h:378
@ SC_TitleBarCloseButton
Definition qstyle.h:379
@ SC_TitleBarContextHelpButton
Definition qstyle.h:383
static QPoint visualPos(Qt::LayoutDirection direction, const QRect &boundingRect, const QPoint &logicalPos)
Returns the given logicalPosition converted to screen coordinates based on the specified direction.
Definition qstyle.cpp:2162
@ RoundedSouth
Definition qtabbar.h:42
@ RoundedNorth
Definition qtabbar.h:42
@ TriangularEast
Definition qtabbar.h:43
@ RoundedWest
Definition qtabbar.h:42
@ TriangularSouth
Definition qtabbar.h:43
@ RoundedEast
Definition qtabbar.h:42
@ TriangularWest
Definition qtabbar.h:43
@ TriangularNorth
Definition qtabbar.h:43
The QTabWidget class provides a stack of tabbed widgets.
Definition qtabwidget.h:20
\inmodule QtCore \reentrant
Definition qdatetime.h:215
static QTime currentTime()
Returns the current time as reported by the system clock.
int msecsTo(QTime t) const
Returns the number of milliseconds from this time to t.
The QTransform class specifies 2D transformations of a coordinate system.
Definition qtransform.h:20
QTransform & rotate(qreal a, Qt::Axis axis=Qt::ZAxis, qreal distanceToPlane=1024.0f)
The QTreeView class provides a default model/view implementation of a tree view.
Definition qtreeview.h:20
int toInt(bool *ok=nullptr) const
Returns the variant as an int if the variant has userType() \l QMetaType::Int, \l QMetaType::Bool,...
bool toBool() const
Returns the variant as a bool if the variant has userType() Bool.
QRect toRect() const
Returns the variant as a QRect if the variant has userType() \l QMetaType::QRect; otherwise returns a...
The QWidget class is the base class of all user interface objects.
Definition qwidget.h:99
void setAttribute(Qt::WidgetAttribute, bool on=true)
Sets the attribute attribute on this widget if on is true; otherwise clears the attribute.
QWidget * nativeParentWidget() const
Definition qwidget.cpp:4333
void setContentsMargins(int left, int top, int right, int bottom)
Sets the margins around the contents of the widget to have the sizes left, top, right,...
Definition qwidget.cpp:7590
void setWindowOpacity(qreal level)
QRect geometry
the geometry of the widget relative to its parent and excluding the window frame
Definition qwidget.h:106
void setPalette(const QPalette &)
Definition qwidget.cpp:4530
QPalette palette
the widget's palette
Definition qwidget.h:132
int height
the height of the widget excluding any window frame
Definition qwidget.h:115
QRect rect
the internal geometry of the widget excluding any window frame
Definition qwidget.h:116
bool isEnabled() const
Definition qwidget.h:814
QIcon windowIcon
the widget's icon
Definition qwidget.h:152
void setFont(const QFont &)
Definition qwidget.cpp:4667
QFont font
the font currently set for the widget
Definition qwidget.h:133
QWidget * parentWidget() const
Returns the parent of this widget, or \nullptr if it does not have any parent widget.
Definition qwidget.h:904
bool isWindow() const
Returns true if the widget is an independent window, otherwise returns false.
Definition qwidget.h:811
QBackingStore * backingStore() const
bool isActiveWindow
whether this widget's window is the active window
Definition qwidget.h:139
bool testAttribute(Qt::WidgetAttribute) const
Returns true if attribute attribute is set on this widget; otherwise returns false.
Definition qwidget.h:910
\inmodule QtGui
Definition qwindow.h:63
QMarginsF margins(const QRect &rect, int propId=TMT_CONTENTMARGINS)
static QSizeF themeSize(const QWidget *w=nullptr, QPainter *p=nullptr, int themeIn=-1, int part=0, int state=0)
void paint(QPainter *painter, const QStyleOption *option)
HBITMAP buffer(int w=0, int h=0)
static int fixedPixelMetric(QStyle::PixelMetric pm)
static HDC hdcForWidgetBackingStore(const QWidget *widget)
static QBackingStore * backingStoreForWidget(const QWidget *widget)
bool swapAlphaChannel(const QRect &rect, bool allPixels=false)
bool drawBackgroundThruNativeBuffer(QWindowsThemeData &QWindowsThemeData, qreal aditionalDevicePixelRatio, qreal correctionFactor)
static HWND winId(const QWidget *widget)
void init(bool force=false)
static bool isLineEditBaseColorSet(const QStyleOption *option, const QWidget *widget)
bool drawBackgroundDirectly(HDC dc, QWindowsThemeData &QWindowsThemeData, qreal aditionalDevicePixelRatio)
static bool isItemViewDelegateLineEdit(const QWidget *widget)
static bool useVista(bool update=false)
static HTHEME createTheme(int theme, HWND hwnd)
bool fixAlphaChannel(const QRect &rect)
void cleanup(bool force=false)
bool isTransparent(QWindowsThemeData &QWindowsThemeData)
bool hasAlphaChannel(const QRect &rect)
QRegion region(QWindowsThemeData &QWindowsThemeData)
bool drawBackground(QWindowsThemeData &QWindowsThemeData, qreal correctionFactor=1)
static int pixelMetricFromSystemDp(QStyle::PixelMetric pm, const QStyleOption *option=nullptr, const QWidget *widget=nullptr)
static QString themeName(int theme)
The QWindowsVistaStyle class provides a look and feel suitable for applications on Microsoft Windows ...
QRect subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const override
QRect subControlRect(ComplexControl cc, const QStyleOptionComplex *opt, SubControl sc, const QWidget *widget) const override
int styleHint(StyleHint hint, const QStyleOption *opt=nullptr, const QWidget *widget=nullptr, QStyleHintReturn *returnData=nullptr) const override
SubControl hitTestComplexControl(ComplexControl control, const QStyleOptionComplex *option, const QPoint &pos, const QWidget *widget=nullptr) const override
void drawControl(ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const override
void polish(QWidget *widget) override
int pixelMetric(PixelMetric metric, const QStyleOption *option=nullptr, const QWidget *widget=nullptr) const override
QPixmap standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt, const QWidget *widget=nullptr) const override
QWindowsVistaStyle()
Constructs a QWindowsVistaStyle object.
QIcon standardIcon(StandardPixmap standardIcon, const QStyleOption *option=nullptr, const QWidget *widget=nullptr) const override
\reimp
~QWindowsVistaStyle() override
Destructor.
void drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget=nullptr) const override
QSize sizeFromContents(ContentsType type, const QStyleOption *option, const QSize &size, const QWidget *widget) const override
void drawComplexControl(ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget) const override
void unpolish(QWidget *widget) override
QOpenGLWidget * widget
[1]
QPixmap p2
QPixmap p1
[0]
QPushButton * button
[2]
opt iconSize
rect
[4]
QPixmap pix
uint alignment
else opt state
[0]
QRect textRect
const QStyleOptionButton * btn
[3]
void newState(QList< State > &states, const char *token, const char *lexem, bool pre)
void qErrnoWarning(const char *msg,...)
QVector3D Q_QUICK3DUTILS_EXPORT rotate(const QMatrix4x4 &m, const QVector3D &v)
Definition qssgutils.cpp:75
Q_WIDGETS_EXPORT qreal dpiScaled(qreal value, qreal dpi)
Combined button and popup list for selecting options.
Q_GUI_EXPORT void clearAllThemeCaches()
Q_GUI_EXPORT HTHEME createTheme(int theme, HWND hwnd)
Q_GUI_EXPORT QString themeName(int theme)
@ WindowMinimized
Definition qnamespace.h:253
@ WindowMaximized
Definition qnamespace.h:254
@ BottomLeftCorner
@ TopRightCorner
@ TopLeftCorner
@ BottomRightCorner
@ AlignBottom
Definition qnamespace.h:154
@ AlignVCenter
Definition qnamespace.h:155
@ AlignTop
Definition qnamespace.h:153
@ AlignHCenter
Definition qnamespace.h:148
@ AlignCenter
Definition qnamespace.h:163
@ AlignLeft
Definition qnamespace.h:144
@ SmoothTransformation
@ WA_UnderMouse
Definition qnamespace.h:284
@ WA_Hover
Definition qnamespace.h:340
@ WA_TranslucentBackground
Definition qnamespace.h:402
@ WA_StyledBackground
Definition qnamespace.h:366
@ IntersectClip
@ LeftToRight
@ RightToLeft
@ KeepAspectRatio
Orientation
Definition qnamespace.h:98
@ Horizontal
Definition qnamespace.h:99
@ Vertical
Definition qnamespace.h:100
@ TextSingleLine
Definition qnamespace.h:170
@ TextDontClip
Definition qnamespace.h:171
@ TextHideMnemonic
Definition qnamespace.h:178
@ TextShowMnemonic
Definition qnamespace.h:173
@ transparent
Definition qnamespace.h:47
@ Dense4Pattern
@ NoBrush
@ Desktop
Definition qnamespace.h:215
@ WindowContextHelpButtonHint
Definition qnamespace.h:231
@ WindowMaximizeButtonHint
Definition qnamespace.h:229
@ WindowMinimizeButtonHint
Definition qnamespace.h:228
@ WindowShadeButtonHint
Definition qnamespace.h:232
@ WindowSystemMenuHint
Definition qnamespace.h:227
@ ElideRight
Definition qnamespace.h:190
Definition image.cpp:4
#define Q_BASIC_ATOMIC_INITIALIZER(a)
#define QByteArrayLiteral(str)
Definition qbytearray.h:52
#define Q_FALLTHROUGH()
#define Q_UNLIKELY(x)
#define qApp
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter * sub
static QString header(const QString &name)
void qDrawWinButton(QPainter *p, int x, int y, int w, int h, const QPalette &pal, bool sunken, const QBrush *fill)
bool qFuzzyCompare(qfloat16 p1, qfloat16 p2) noexcept
Definition qfloat16.h:333
int qRound(qfloat16 d) noexcept
Definition qfloat16.h:327
static void visualRect(QRectF *geom, Qt::LayoutDirection dir, const QRectF &contentsRect)
static int area(const QSize &s)
Definition qicon.cpp:153
static const double leftOffset
#define qDebug
[1]
Definition qlogging.h:164
#define qWarning
Definition qlogging.h:166
return ret
static const QStyle::SubControl SubControls[]
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
static QString themeName()
GLsizei const GLfloat * v
[13]
GLint GLint GLint GLint GLint x
[0]
GLenum mode
GLuint64 key
GLfloat GLfloat GLfloat w
[0]
GLint GLsizei GLsizei height
GLboolean GLboolean GLboolean GLboolean a
[7]
GLuint GLfloat GLfloat GLfloat GLfloat y1
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLboolean r
[2]
GLuint GLuint end
GLuint GLfloat GLfloat GLfloat x1
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLint GLenum GLsizei GLsizei GLsizei GLint border
GLenum GLuint buffer
GLint GLsizei width
GLenum type
GLuint GLsizei const GLchar * label
[43]
GLenum GLuint GLenum GLsizei const GLchar * buf
GLbitfield flags
GLenum GLuint GLintptr offset
GLint ref
GLuint name
GLuint GLenum transformType
GLint GLint GLint GLint GLint GLint GLint GLbitfield mask
GLint GLsizei GLsizei GLenum format
GLint y
GLfloat GLfloat GLfloat GLfloat h
GLuint GLenum GLenum transform
GLdouble s
[6]
Definition qopenglext.h:235
GLuint res
GLint void * img
Definition qopenglext.h:233
GLdouble GLdouble t
Definition qopenglext.h:243
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLuint64EXT * result
[6]
GLfloat GLfloat p
[1]
GLuint GLenum option
GLenum GLsizei len
GLfloat GLfloat GLfloat alpha
Definition qopenglext.h:418
static const QRectF scaleRect(const QRectF &r, qreal sx, qreal sy)
static bool hasAlpha(const QImage &image)
#define ERROR(description)
static QT_BEGIN_NAMESPACE qreal dpr(const QWindow *w)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define Q_ASSERT_X(cond, x, msg)
Definition qrandom.cpp:48
QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIterator begin(const QRegularExpressionMatchIterator &iterator)
constexpr QRgb qRgb(int r, int g, int b)
Definition qrgb.h:30
constexpr int qRed(QRgb rgb)
Definition qrgb.h:18
constexpr int qGreen(QRgb rgb)
Definition qrgb.h:21
constexpr int qBlue(QRgb rgb)
Definition qrgb.h:24
constexpr int qAlpha(QRgb rgb)
Definition qrgb.h:27
SSL_CTX int(* cb)(SSL *ssl, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg)
#define qPrintable(string)
Definition qstring.h:1531
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
#define QStringLiteral(str)
static QT_BEGIN_NAMESPACE QVariant hint(QPlatformIntegration::StyleHint h)
#define QT_CONFIG(feature)
unsigned int uint
Definition qtypes.h:34
long long qint64
Definition qtypes.h:60
double qreal
Definition qtypes.h:187
long HRESULT
#define disabled
#define RBS_INACTIVE
#define TMT_TEXTSHADOWCOLOR
@ UnknownAlpha
#define MAXBS_INACTIVE
#define CBS_INACTIVE
#define TST_NONE
static bool isFullyOpaque(const QWindowsThemeData &themeData)
#define BP_COMMANDLINK
#define CMDLGS_NORMAL
static QRectF scaleRect(const QRectF &r, qreal factor)
#define LISS_HOTSELECTED
static const int windowsItemFrame
#define TMT_CONTENTMARGINS
static bool buttonVisible(const QStyle::SubControl sc, const QStyleOptionTitleBar *tb)
#define LISS_SELECTEDNOTFOCUS
static const int windowsItemHMargin
bool canAnimate(const QStyleOption *option)
#define LISS_HOT
QStyleOption * clonedAnimationStyleOption(const QStyleOption *option)
static void qt_add_rect(HRGN &winRegion, QRect r)
#define CMDLGS_PRESSED
static int buttonStateId(int flags, int partId)
#define LISS_SELECTED
static const int windowsArrowHMargin
static QRegion scaleRegion(const QRegion &region, qreal factor)
static const int windowsItemVMargin
static void populateTitleBarButtonTheme(const QStyle *proxy, const QWidget *widget, const QStyleOptionComplex *option, QStyle::SubControl subControl, bool isTitleBarActive, int part, QWindowsThemeData *theme)
QObject * styleObject(const QStyleOption *option)
#define BP_COMMANDLINKGLYPH
static Qt::Orientation progressBarOrientation(const QStyleOption *option=nullptr)
static HRGN qt_hrgn_from_qregion(const QRegion &region)
void deleteClonedAnimationStyleOption(const QStyleOption *option)
@ SimpleTransform
@ HighDpiScalingTransform
@ ComplexTransform
static QImage createAnimationBuffer(const QStyleOption *option, const QWidget *widget)
static HWND createTreeViewHelperWindow()
#define CMDLGS_DISABLED
#define CMDLGS_HOT
static bool supportsStateTransition(QStyle::PrimitiveElement element, const QStyleOption *option, const QWidget *widget)
static const int windowsRightBorder
QWidget * panel
Definition settings.cpp:7
QList< int > list
[14]
if(qFloatDistance(a, b)<(1<< 7))
[0]
QRandomGenerator64 rd
[10]
ba fill(true)
QLinearGradient alphaGradient(rect.topLeft(), rect.bottomLeft())
[1]
rect deviceTransform(view->viewportTransform()).map(QPointF(0
QApplication app(argc, argv)
[0]
widget render & pixmap
QPainter painter(this)
[7]
aWidget window() -> setWindowTitle("New Window Title")
[2]
QFrame frame
[0]
QNetworkProxy proxy
[0]
QQuickView * view
[0]
\inmodule QtCore \reentrant
Definition qchar.h:18