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
qquickwindowsxpstyle.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
6
7#include <private/qobject_p.h>
8#include <private/qpaintengine_raster_p.h>
9#include <qpa/qplatformnativeinterface.h>
10#include <qpainter.h>
11#include <qpaintengine.h>
12#include <qbackingstore.h>
13#include <qpixmapcache.h>
14#include <qpa/qplatformnativeinterface.h>
15#include <qvarlengtharray.h>
16#include <qdebug.h>
17
18#include <algorithm>
19
21
22namespace QQC2 {
23
24// General const values
25static const int windowsItemFrame = 2; // menu item frame width
26static const int windowsItemHMargin = 3; // menu item hor text margin
27static const int windowsItemVMargin = 0; // menu item ver text margin
28static const int windowsArrowHMargin = 6; // arrow horizontal margin
29static const int windowsRightBorder = 12; // right border on windows
30
31// Theme names matching the QWindowsXPStylePrivate::Theme enumeration.
33{
34 L"BUTTON", L"COMBOBOX", L"EDIT", L"HEADER", L"LISTVIEW",
35 L"MENU", L"PROGRESS", L"REBAR", L"SCROLLBAR", L"SPIN",
36 L"TAB", L"TASKDIALOG", L"TOOLBAR", L"TOOLTIP", L"TRACKBAR",
37 L"TREEVIEW", L"WINDOW", L"STATUS", L"TREEVIEW"
38};
39
40// Theme data helper ------------------------------------------------------------------------------
41/* \internal
42 Returns \c true if the themedata is valid for use.
43*/
45{
46 return QWindowsXPStylePrivate::useXP() && theme >= 0 && handle();
47}
48
49
50/* \internal
51 Returns the theme engine handle to the specific class.
52 If the handle hasn't been opened before, it opens the data, and
53 adds it to a static map, for caching.
54*/
64
65/* \internal
66 Converts a QRect to the native RECT structure.
67*/
69{
70 RECT r;
71 r.left = qr.x();
72 r.right = qr.x() + qr.width();
73 r.top = qr.y();
74 r.bottom = qr.y() + qr.height();
75 return r;
76}
77
78/* \internal
79 Returns the native region of a part, if the part is considered
80 transparent. The region is scaled to the parts size (rect).
81*/
82
83// QWindowsXPStylePrivate -------------------------------------------------------------------------
84// Static initializations
85HWND QWindowsXPStylePrivate::m_vistaTreeViewHelper = nullptr;
86HTHEME QWindowsXPStylePrivate::m_themes[NThemes];
87bool QWindowsXPStylePrivate::use_xp = false;
88QBasicAtomicInt QWindowsXPStylePrivate::ref = Q_BASIC_ATOMIC_INITIALIZER(-1); // -1 based refcounting
89
90static void qt_add_rect(HRGN &winRegion, QRect r)
91{
92 HRGN rgn = CreateRectRgn(r.left(), r.top(), r.x() + r.width(), r.y() + r.height());
93 if (rgn) {
94 HRGN dest = CreateRectRgn(0,0,0,0);
95 int result = CombineRgn(dest, winRegion, rgn, RGN_OR);
96 if (result) {
97 DeleteObject(winRegion);
98 winRegion = dest;
99 }
100 DeleteObject(rgn);
101 }
102}
103
104static HRGN qt_hrgn_from_qregion(const QRegion &region)
105{
106 HRGN hRegion = CreateRectRgn(0,0,0,0);
107 if (region.rectCount() == 1) {
108 qt_add_rect(hRegion, region.boundingRect());
109 return hRegion;
110 }
111 for (const QRect &rect : region)
112 qt_add_rect(hRegion, rect);
113 return hRegion;
114}
115
116/* \internal
117 Checks if the theme engine can/should be used, or if we should
118 fall back to Windows style.
119*/
121{
122 if (update) {
123 use_xp = IsThemeActive() && (IsAppThemed() || !QCoreApplication::instance())
125 }
126 return use_xp;
127}
128
129/* \internal
130 Handles refcounting, and queries the theme engine for usage.
131*/
133{
134 if (ref.ref() && !force)
135 return;
136 if (!force) // -1 based atomic refcounting
137 ref.ref();
138
139 useXP(true);
140 std::fill(m_themes, m_themes + NThemes, nullptr);
141}
142
143/* \internal
144 Cleans up all static data.
145*/
147{
148 if (bufferBitmap) {
149 if (bufferDC && nullBitmap)
150 SelectObject(bufferDC, nullBitmap);
151 DeleteObject(bufferBitmap);
152 bufferBitmap = nullptr;
153 }
154
155 if (bufferDC)
156 DeleteDC(bufferDC);
157 bufferDC = nullptr;
158
159 if (ref.deref() && !force)
160 return;
161 if (!force) // -1 based atomic refcounting
162 ref.deref();
163
164 use_xp = false;
166}
167
168/* In order to obtain the correct VistaTreeViewTheme (arrows for PE_IndicatorBranch),
169 * we need to set the windows "explorer" theme explicitly on a native
170 * window and open the "TREEVIEW" theme handle passing its window handle
171 * in order to get Vista-style item view themes (particulary drawBackground()
172 * for selected items needs this).
173 * We invoke a service of the native Windows interface to create
174 * a non-visible window handle, open the theme on it and insert it into
175 * the cache so that it is found by XPThemeData::handle() first.
176 */
177
178static inline HWND createTreeViewHelperWindow()
179{
181 void *hwnd = nullptr;
182 void *wndProc = reinterpret_cast<void *>(DefWindowProc);
183 if (QMetaObject::invokeMethod(ni, "createMessageWindow", Qt::DirectConnection,
184 Q_RETURN_ARG(void*, hwnd),
185 Q_ARG(QString, QStringLiteral("QTreeViewThemeHelperWindowClass")),
186 Q_ARG(QString, QStringLiteral("QTreeViewThemeHelperWindow")),
187 Q_ARG(void*, wndProc)) && hwnd) {
188 return reinterpret_cast<HWND>(hwnd);
189 }
190 }
191 return nullptr;
192}
193
194bool QWindowsXPStylePrivate::initVistaTreeViewTheming()
195{
196 if (m_vistaTreeViewHelper)
197 return true;
198
199 m_vistaTreeViewHelper = createTreeViewHelperWindow();
200 if (!m_vistaTreeViewHelper) {
201 qWarning("Unable to create the treeview helper window.");
202 return false;
203 }
204 if (FAILED(SetWindowTheme(m_vistaTreeViewHelper, L"explorer", nullptr))) {
205 qErrnoWarning("SetWindowTheme() failed.");
206 cleanupVistaTreeViewTheming();
207 return false;
208 }
209 return true;
210}
211
212void QWindowsXPStylePrivate::cleanupVistaTreeViewTheming()
213{
214 if (m_vistaTreeViewHelper) {
215 DestroyWindow(m_vistaTreeViewHelper);
216 m_vistaTreeViewHelper = nullptr;
217 }
218}
219
220/* \internal
221 Closes all open theme data handles to ensure that we don't leak
222 resources, and that we don't refere to old handles when for
223 example the user changes the theme style.
224*/
226{
227 for (auto &theme : m_themes) {
228 if (theme) {
229 CloseThemeData(theme);
230 theme = nullptr;
231 }
232 }
233 QWindowsXPStylePrivate::cleanupVistaTreeViewTheming();
234}
235
236HTHEME QWindowsXPStylePrivate::createTheme(int theme, HWND hwnd)
237{
238 if (Q_UNLIKELY(theme < 0 || theme >= NThemes || !hwnd)) {
239 qWarning("Invalid parameters #%d, %p", theme, hwnd);
240 return nullptr;
241 }
242 if (!m_themes[theme]) {
243 const wchar_t *name = themeNames[theme];
244 if (theme == VistaTreeViewTheme && QWindowsXPStylePrivate::initVistaTreeViewTheming())
245 hwnd = QWindowsXPStylePrivate::m_vistaTreeViewHelper;
246 m_themes[theme] = OpenThemeData(hwnd, name);
247 if (Q_UNLIKELY(!m_themes[theme]))
248 qErrnoWarning("OpenThemeData() failed for theme %d (%s).",
249 theme, qPrintable(themeName(theme)));
250 }
251 return m_themes[theme];
252}
253
255{
256 return theme >= 0 && theme < NThemes ?
258 QString();
259}
260
261/*
262bool QWindowsXPStylePrivate::isItemViewDelegateLineEdit(const QWidget *widget)
263{
264 if (!widget)
265 return false;
266 const QWidget *parent1 = widget->parentWidget();
267 // Exlude dialogs or other toplevels parented on item views.
268 if (!parent1 || parent1->isWindow())
269 return false;
270 const QWidget *parent2 = parent1->parentWidget();
271 return parent2 && widget->inherits("QLineEdit")
272 && parent2->inherits("QAbstractItemView");
273}
274*/
275
276/*
277// Returns whether base color is set for this widget
278bool QWindowsXPStylePrivate::isLineEditBaseColorSet(const QStyleOption *option, const QWidget *widget)
279{
280 uint resolveMask = option->palette.resolve();
281 if (widget) {
282 // Since spin box includes a line edit we need to resolve the palette mask also from
283 // the parent, as while the color is always correct on the palette supplied by panel,
284 // the mask can still be empty. If either mask specifies custom base color, use that.
285#if QT_CONFIG(spinbox)
286 if (const QAbstractSpinBox *spinbox = qobject_cast<QAbstractSpinBox*>(widget->parentWidget()))
287 resolveMask |= spinbox->palette().resolve();
288#endif // QT_CONFIG(spinbox)
289 }
290 return (resolveMask & (1 << QPalette::Base)) != 0;
291}
292*/
293
301{
302 if (window)
303 if (const HWND hwnd = reinterpret_cast<HWND>(window->winId()))
304 return hwnd;
305
306 // Find top level with native window (there might be dialogs that do not have one).
307 const auto allWindows = QGuiApplication::allWindows();
308 for (const QWindow *window : allWindows) {
309 if (window->isTopLevel() && window->type() != Qt::Desktop && window->handle() != nullptr)
310 return reinterpret_cast<HWND>(window->winId());
311 }
312
313 return GetDesktopWindow();
314}
315
322{
323 // If we already have a HBITMAP which is of adequate size, just return that
324 if (bufferBitmap) {
325 if (bufferW >= w && bufferH >= h)
326 return bufferBitmap;
327 // Not big enough, discard the old one
328 if (bufferDC && nullBitmap)
329 SelectObject(bufferDC, nullBitmap);
330 DeleteObject(bufferBitmap);
331 bufferBitmap = nullptr;
332 }
333
334 w = qMax(bufferW, w);
335 h = qMax(bufferH, h);
336
337 if (!bufferDC) {
338 HDC displayDC = GetDC(nullptr);
339 bufferDC = CreateCompatibleDC(displayDC);
340 ReleaseDC(nullptr, displayDC);
341 }
342
343 // Define the header
344 BITMAPINFO bmi;
345 memset(&bmi, 0, sizeof(bmi));
346 bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
347 bmi.bmiHeader.biWidth = w;
348 bmi.bmiHeader.biHeight = -h;
349 bmi.bmiHeader.biPlanes = 1;
350 bmi.bmiHeader.biBitCount = 32;
351 bmi.bmiHeader.biCompression = BI_RGB;
352
353 // Create the pixmap
354 bufferPixels = nullptr;
355 bufferBitmap = CreateDIBSection(bufferDC, &bmi, DIB_RGB_COLORS, reinterpret_cast<void **>(&bufferPixels), nullptr, 0);
356 GdiFlush();
357 nullBitmap = static_cast<HBITMAP>(SelectObject(bufferDC, bufferBitmap));
358
359 if (Q_UNLIKELY(!bufferBitmap)) {
360 qErrnoWarning("QWindowsXPStylePrivate::buffer(%dx%d), CreateDIBSection() failed.", w, h);
361 bufferW = 0;
362 bufferH = 0;
363 return nullptr;
364 }
365 if (Q_UNLIKELY(!bufferPixels)) {
366 qErrnoWarning("QWindowsXPStylePrivate::buffer(%dx%d), CreateDIBSection() did not allocate pixel data.", w, h);
367 bufferW = 0;
368 bufferH = 0;
369 return nullptr;
370 }
371 bufferW = w;
372 bufferH = h;
373#ifdef DEBUG_XP_STYLE
374 qDebug("Creating new dib section (%d, %d)", w, h);
375#endif
376 return bufferBitmap;
377}
378
386{
387 return IsThemeBackgroundPartiallyTransparent(themeData.handle(), themeData.partId,
388 themeData.stateId);
389}
390
391
396{
397 HRGN hRgn = nullptr;
398 const qreal factor = QWindowsStylePrivate::nativeMetricScaleFactor(themeData.window);
399 RECT rect = themeData.toRECT(QRect(themeData.rect.topLeft() / factor, themeData.rect.size() / factor));
400 if (!SUCCEEDED(GetThemeBackgroundRegion(themeData.handle(), bufferHDC(), themeData.partId,
401 themeData.stateId, &rect, &hRgn))) {
402 return QRegion();
403 }
404
405 HRGN dest = CreateRectRgn(0, 0, 0, 0);
406 const bool success = CombineRgn(dest, hRgn, nullptr, RGN_COPY) != ERROR;
407
409
410 if (success) {
411 const auto numBytes = GetRegionData(dest, 0, nullptr);
412 if (numBytes == 0)
413 return QRegion();
414
415 char *buf = new (std::nothrow) char[numBytes];
416 if (!buf)
417 return QRegion();
418
419 RGNDATA *rd = reinterpret_cast<RGNDATA*>(buf);
420 if (GetRegionData(dest, numBytes, rd) == 0) {
421 delete [] buf;
422 return QRegion();
423 }
424
425 RECT *r = reinterpret_cast<RECT*>(rd->Buffer);
426 for (uint i = 0; i < rd->rdh.nCount; ++i) {
427 QRect rect;
428 rect.setCoords(int(r->left * factor), int(r->top * factor), int((r->right - 1) * factor), int((r->bottom - 1) * factor));
429 ++r;
430 region |= rect;
431 }
432
433 delete [] buf;
434 }
435
436 DeleteObject(hRgn);
437 DeleteObject(dest);
438
439 return region;
440}
441
447{
448 const int startX = rect.left();
449 const int startY = rect.top();
450 const int w = rect.width();
451 const int h = rect.height();
452
453 int firstAlpha = -1;
454 for (int y = startY; y < h/2; ++y) {
455 auto buffer = reinterpret_cast<const DWORD *>(bufferPixels) + (y * bufferW);
456 for (int x = startX; x < w; ++x, ++buffer) {
457 int alpha = (*buffer) >> 24;
458 if (firstAlpha == -1)
459 firstAlpha = alpha;
460 else if (alpha != firstAlpha)
461 return true;
462 }
463 }
464 return false;
465}
466
476{
477 const int startX = rect.left();
478 const int startY = rect.top();
479 const int w = rect.width();
480 const int h = rect.height();
481 bool hasFixedAlphaValue = false;
482
483 for (int y = startY; y < h; ++y) {
484 auto buffer = reinterpret_cast<DWORD *>(bufferPixels) + (y * bufferW);
485 for (int x = startX; x < w; ++x, ++buffer) {
486 uint pixel = *buffer;
487 int alpha = qAlpha(pixel);
488 if (qRed(pixel) > alpha || qGreen(pixel) > alpha || qBlue(pixel) > alpha) {
489 *buffer |= 0xff000000;
490 hasFixedAlphaValue = true;
491 }
492 }
493 }
494 return hasFixedAlphaValue;
495}
496
507{
508 const int startX = rect.left();
509 const int startY = rect.top();
510 const int w = rect.width();
511 const int h = rect.height();
512 bool valueChange = false;
513
514 // Flip the alphas, so that 255-alpha pixels are 0, and 0-alpha are 255.
515 for (int y = startY; y < h; ++y) {
516 auto buffer = reinterpret_cast<DWORD *>(bufferPixels) + (y * bufferW);
517 for (int x = startX; x < w; ++x, ++buffer) {
518 if (allPixels) {
519 *buffer |= 0xFF000000;
520 continue;
521 }
522 unsigned int alphaValue = (*buffer) & 0xFF000000;
523 if (alphaValue == 0xFF000000) {
524 *buffer = 0;
525 valueChange = true;
526 } else if (alphaValue == 0) {
527 *buffer |= 0xFF000000;
528 valueChange = true;
529 }
530 }
531 }
532 return valueChange;
533}
534
535#if 0
537
538static inline TransformType transformType(const QTransform &transform, qreal devicePixelRatio)
539{
541 return SimpleTransform;
542 if (transform.type() > QTransform::TxScale)
543 return ComplexTransform;
544 return qFuzzyCompare(transform.m11(), devicePixelRatio)
545 && qFuzzyCompare(transform.m22(), devicePixelRatio)
547}
548
549// QTBUG-60571: Exclude known fully opaque theme parts which produce values
550// invalid in ARGB32_Premultiplied (for example, 0x00ffffff).
551static inline bool isFullyOpaque(const XPThemeData &themeData)
552{
553 return themeData.theme == QWindowsXPStylePrivate::TaskDialogTheme && themeData.partId == TDLG_PRIMARYPANEL;
554}
555#endif
556
569{
570 if (themeData.rect.isEmpty())
571 return true;
572
573 QPainter *painter = themeData.painter;
574 Q_ASSERT_X(painter != nullptr, "QWindowsXPStylePrivate::drawBackground()", "Trying to draw a theme part without a painter");
575 if (!painter || !painter->isActive())
576 return false;
577
578 painter->save();
579
580 // Access paintDevice via engine since the painter may
581 // return the clip device which can still be a widget device in case of grabWidget().
582
583 //bool translucentToplevel = false;
584 //const QPaintDevice *paintDevice = painter->device();
585 const qreal additionalDevicePixelRatio = themeData.window ? themeData.window->devicePixelRatio() : qreal(1);
587/*
588 if (paintDevice->devType() == QInternal::Widget) {
589 const QWidget *window = static_cast<const QWidget *>(paintDevice)->window();
590 translucentToplevel = window->testAttribute(Qt::WA_TranslucentBackground);
591 }
592
593 const TransformType tt = transformType(painter->deviceTransform(), aditionalDevicePixelRatio);
594
595 bool canDrawDirectly = false;
596 if (themeData.widget && painter->opacity() == 1.0 && !themeData.rotate
597 && !isFullyOpaque(themeData)
598 && tt != ComplexTransform && !themeData.mirrorVertically
599 && !translucentToplevel) {
600 // Draw on backing store DC only for real widgets or backing store images.
601 const QPaintDevice *enginePaintDevice = painter->paintEngine()->paintDevice();
602 switch (enginePaintDevice->devType()) {
603 case QInternal::Widget:
604 canDrawDirectly = true;
605 break;
606 case QInternal::Image:
607 // Ensure the backing store has received as resize and is initialized.
608 if (QBackingStore *bs = backingStoreForWidget(themeData.widget))
609 if (bs->size().isValid() && bs->paintDevice() == enginePaintDevice)
610 canDrawDirectly = true;
611 }
612 }
613
614 const HDC dc = canDrawDirectly ? hdcForWidgetBackingStore(themeData.widget) : nullptr;
615 const bool result = dc && qFuzzyCompare(correctionFactor, qreal(1))
616 ? drawBackgroundDirectly(dc, themeData, aditionalDevicePixelRatio)
617 : drawBackgroundThruNativeBuffer(themeData, aditionalDevicePixelRatio, correctionFactor);
618 */
619 const bool result = drawBackgroundThruNativeBuffer(themeData, additionalDevicePixelRatio, correctionFactor);
620 painter->restore();
621 return result;
622}
623
624static inline QRectF scaleRect(const QRectF &r, qreal factor)
625{
626 return r.isValid() && factor > 1
627 ? QRectF(r.topLeft() * factor, r.size() * factor)
628 : r;
629}
630
631static QRegion scaleRegion(const QRegion &region, qreal factor)
632{
633 if (region.isEmpty() || qFuzzyCompare(factor, qreal(1)))
634 return region;
636 for (const QRect &rect : region)
637 result += QRectF(QPointF(rect.topLeft()) * factor, QSizeF(rect.size() * factor)).toRect();
638 return result;
639}
640
646bool QWindowsXPStylePrivate::drawBackgroundDirectly(HDC dc, XPThemeData &themeData, qreal additionalDevicePixelRatio)
647{
648 QPainter *painter = themeData.painter;
649
650 const auto &deviceTransform = painter->deviceTransform();
651 const QPointF redirectionDelta(deviceTransform.dx(), deviceTransform.dy());
652 const QRect area = scaleRect(QRectF(themeData.rect), additionalDevicePixelRatio).translated(redirectionDelta).toRect();
653
654 QRegion sysRgn = painter->paintEngine()->systemClip();
655 if (sysRgn.isEmpty())
656 sysRgn = area;
657 else
658 sysRgn &= area;
659 if (painter->hasClipping())
660 sysRgn &= scaleRegion(painter->clipRegion(), additionalDevicePixelRatio).translated(redirectionDelta.toPoint());
661 HRGN hrgn = qt_hrgn_from_qregion(sysRgn);
662 SelectClipRgn(dc, hrgn);
663
664#ifdef DEBUG_XP_STYLE
665 printf("---[ DIRECT PAINTING ]------------------> Name(%-10s) Part(%d) State(%d)\n",
666 qPrintable(themeData.name), themeData.partId, themeData.stateId);
667 showProperties(themeData);
668#endif
669
670 RECT drawRECT = themeData.toRECT(area);
671 DTBGOPTS drawOptions;
672 memset(&drawOptions, 0, sizeof(drawOptions));
673 drawOptions.dwSize = sizeof(drawOptions);
674 drawOptions.rcClip = themeData.toRECT(sysRgn.boundingRect());
675 drawOptions.dwFlags = DTBG_CLIPRECT
676 | (themeData.noBorder ? DTBG_OMITBORDER : 0)
677 | (themeData.noContent ? DTBG_OMITCONTENT : 0)
678 | (themeData.mirrorHorizontally ? DTBG_MIRRORDC : 0);
679
680 const HRESULT result = DrawThemeBackgroundEx(themeData.handle(), dc, themeData.partId, themeData.stateId, &(drawRECT), &drawOptions);
681 SelectClipRgn(dc, nullptr);
682 DeleteObject(hrgn);
683 return SUCCEEDED(result);
684}
685
699 qreal additionalDevicePixelRatio,
700 qreal correctionFactor)
701{
702 QPainter *painter = themeData.painter;
703 QRectF rectF = scaleRect(QRectF(themeData.rect), additionalDevicePixelRatio);
704
705 if ((themeData.rotate + 90) % 180 == 0) { // Catch 90,270,etc.. degree flips.
706 rectF = QRectF(0, 0, rectF.height(), rectF.width());
707 }
708 rectF.moveTo(0, 0);
709
710 const bool hasCorrectionFactor = !qFuzzyCompare(correctionFactor, qreal(1));
711 QRect rect = rectF.toRect();
712 QRect drawRect = hasCorrectionFactor
713 ? QRectF(rectF.topLeft() / correctionFactor, rectF.size() / correctionFactor).toRect() : rect;
714 int partId = themeData.partId;
715 int stateId = themeData.stateId;
716 int w = rect.width();
717 int h = rect.height();
718
719 // Values initialized later, either from cached values, or from function calls
720 AlphaChannelType alphaType = UnknownAlpha;
721 bool stateHasData = true; // We assume so;
722 bool hasAlpha = false;
723 bool partIsTransparent;
724 bool potentialInvalidAlpha;
725
726 QString pixmapCacheKey = QStringLiteral("$qt_xp_");
727 pixmapCacheKey.append(themeName(themeData.theme));
728 pixmapCacheKey.append(QLatin1Char('p'));
729 pixmapCacheKey.append(QString::number(partId));
730 pixmapCacheKey.append(QLatin1Char('s'));
731 pixmapCacheKey.append(QString::number(stateId));
732 pixmapCacheKey.append(QLatin1Char('s'));
733 pixmapCacheKey.append(themeData.noBorder ? QLatin1Char('0') : QLatin1Char('1'));
734 pixmapCacheKey.append(QLatin1Char('b'));
735 pixmapCacheKey.append(themeData.noContent ? QLatin1Char('0') : QLatin1Char('1'));
736 pixmapCacheKey.append(QString::number(w));
737 pixmapCacheKey.append(QLatin1Char('w'));
738 pixmapCacheKey.append(QString::number(h));
739 pixmapCacheKey.append(QLatin1Char('h'));
740 pixmapCacheKey.append(QString::number(additionalDevicePixelRatio));
741 pixmapCacheKey.append(QLatin1Char('d'));
742 if (hasCorrectionFactor) {
743 pixmapCacheKey.append(QLatin1Char('c'));
744 pixmapCacheKey.append(QString::number(correctionFactor));
745 }
746
747 QPixmap cachedPixmap;
748 ThemeMapKey key(themeData);
749 ThemeMapData data = alphaCache.value(key);
750
751 bool haveCachedPixmap = false;
752 bool isCached = data.dataValid;
753 if (isCached) {
754 partIsTransparent = data.partIsTransparent;
755 hasAlpha = data.hasAlphaChannel;
756 alphaType = data.alphaType;
757 potentialInvalidAlpha = data.hadInvalidAlpha;
758
759 haveCachedPixmap = QPixmapCache::find(pixmapCacheKey, &cachedPixmap);
760
761#ifdef DEBUG_XP_STYLE
762 char buf[25];
763 ::snprintf(buf, sizeof(buf), "+ Pixmap(%3d, %3d) ]", w, h);
764 printf("---[ CACHED %s--------> Name(%-10s) Part(%d) State(%d)\n",
765 haveCachedPixmap ? buf : "]-------------------",
766 qPrintable(themeData.name), themeData.partId, themeData.stateId);
767#endif
768 } else {
769 // Not cached, so get values from Theme Engine
770 BOOL tmt_borderonly = false;
771 COLORREF tmt_transparentcolor = 0x0;
772 PROPERTYORIGIN proporigin = PO_NOTFOUND;
773 GetThemeBool(themeData.handle(), themeData.partId, themeData.stateId, TMT_BORDERONLY, &tmt_borderonly);
774 GetThemeColor(themeData.handle(), themeData.partId, themeData.stateId, TMT_TRANSPARENTCOLOR, &tmt_transparentcolor);
775 GetThemePropertyOrigin(themeData.handle(), themeData.partId, themeData.stateId, TMT_CAPTIONMARGINS, &proporigin);
776
777 partIsTransparent = isTransparent(themeData);
778
779 potentialInvalidAlpha = false;
780 GetThemePropertyOrigin(themeData.handle(), themeData.partId, themeData.stateId, TMT_GLYPHTYPE, &proporigin);
781 if (proporigin == PO_PART || proporigin == PO_STATE) {
782 int tmt_glyphtype = GT_NONE;
783 GetThemeEnumValue(themeData.handle(), themeData.partId, themeData.stateId, TMT_GLYPHTYPE, &tmt_glyphtype);
784 potentialInvalidAlpha = partIsTransparent && tmt_glyphtype == GT_IMAGEGLYPH;
785 }
786
787#ifdef DEBUG_XP_STYLE
788 printf("---[ NOT CACHED ]-----------------------> Name(%-10s) Part(%d) State(%d)\n",
789 qPrintable(themeData.name), themeData.partId, themeData.stateId);
790 printf("-->partIsTransparen = %d\n", partIsTransparent);
791 printf("-->potentialInvalidAlpha = %d\n", potentialInvalidAlpha);
792 showProperties(themeData);
793#endif
794 }
795 bool wasAlphaSwapped = false;
796 bool wasAlphaFixed = false;
797
798 // OLD PSDK Workaround ------------------------------------------------------------------------
799 // See if we need extra clipping for the older PSDK, which does
800 // not have a DrawThemeBackgroundEx function for DTGB_OMITBORDER
801 // and DTGB_OMITCONTENT
802 bool addBorderContentClipping = false;
803 QRegion extraClip;
804 QRect area = drawRect;
805 if (themeData.noBorder || themeData.noContent) {
806 extraClip = area;
807 // We are running on a system where the uxtheme.dll does not have
808 // the DrawThemeBackgroundEx function, so we need to clip away
809 // borders or contents manually.
810
811 int borderSize = 0;
812 PROPERTYORIGIN origin = PO_NOTFOUND;
813 GetThemePropertyOrigin(themeData.handle(), themeData.partId, themeData.stateId, TMT_BORDERSIZE, &origin);
814 GetThemeInt(themeData.handle(), themeData.partId, themeData.stateId, TMT_BORDERSIZE, &borderSize);
815 borderSize *= additionalDevicePixelRatio;
816
817 // Clip away border region
818 if ((origin == PO_CLASS || origin == PO_PART || origin == PO_STATE) && borderSize > 0) {
819 if (themeData.noBorder) {
820 extraClip &= area;
821 area = area.adjusted(-borderSize, -borderSize, borderSize, borderSize);
822 }
823
824 // Clip away content region
825 if (themeData.noContent) {
826 QRegion content = area.adjusted(borderSize, borderSize, -borderSize, -borderSize);
827 extraClip ^= content;
828 }
829 }
830 addBorderContentClipping = (themeData.noBorder | themeData.noContent);
831 }
832
833 QImage img;
834 if (!haveCachedPixmap) { // If the pixmap is not cached, generate it! -------------------------
835 if (!buffer(drawRect.width(), drawRect.height())) // Ensure a buffer of at least (w, h) in size
836 return false;
837 HDC dc = bufferHDC();
838
839 // Clear the buffer
840 if (alphaType != NoAlpha) {
841 // Consider have separate "memset" function for small chunks for more speedup
842 memset(bufferPixels, 0x00, bufferW * drawRect.height() * 4);
843 }
844
845 // Difference between area and rect
846 int dx = area.x() - drawRect.x();
847 int dy = area.y() - drawRect.y();
848
849 // Adjust so painting rect starts from Origo
850 rect.moveTo(0,0);
851 area.moveTo(dx,dy);
852 DTBGOPTS drawOptions;
853 drawOptions.dwSize = sizeof(drawOptions);
854 drawOptions.rcClip = themeData.toRECT(rect);
855 drawOptions.dwFlags = DTBG_CLIPRECT
856 | (themeData.noBorder ? DTBG_OMITBORDER : 0)
857 | (themeData.noContent ? DTBG_OMITCONTENT : 0);
858
859 // Drawing the part into the backing store
860 RECT wRect(themeData.toRECT(area));
861 DrawThemeBackgroundEx(themeData.handle(), dc, themeData.partId, themeData.stateId, &wRect, &drawOptions);
862
863 // If not cached, analyze the buffer data to figure
864 // out alpha type, and if it contains data
865 if (!isCached) {
866 // SHORTCUT: If the part's state has no data, cache it for NOOP later
867 if (!stateHasData) {
868 memset(static_cast<void *>(&data), 0, sizeof(data));
869 data.dataValid = true;
870 alphaCache.insert(key, data);
871 return true;
872 }
874 if (!hasAlpha && partIsTransparent)
875 potentialInvalidAlpha = true;
876#if defined(DEBUG_XP_STYLE) && 1
877 dumpNativeDIB(drawRect.width(), drawRect.height());
878#endif
879 }
880
881 // Fix alpha values, if needed
882 if (potentialInvalidAlpha)
883 wasAlphaFixed = fixAlphaChannel(drawRect);
884
886 if ((partIsTransparent && !wasAlphaSwapped) || (!partIsTransparent && hasAlpha)) {
888 alphaType = RealAlpha;
889 } else if (wasAlphaSwapped) {
891 alphaType = MaskAlpha;
892 } else {
894 // The image data we got from the theme engine does not have any transparency,
895 // thus the alpha channel is set to 0.
896 // However, Format_RGB32 requires the alpha part to be set to 0xff, thus
897 // we must flip it from 0x00 to 0xff
898 swapAlphaChannel(rect, true);
899 alphaType = NoAlpha;
900 }
901#if defined(DEBUG_XP_STYLE) && 1
902 printf("Image format is: %s\n", alphaType == RealAlpha ? "Real Alpha" : alphaType == MaskAlpha ? "Masked Alpha" : "No Alpha");
903#endif
904 img = QImage(bufferPixels, bufferW, bufferH, format);
905 if (hasCorrectionFactor)
907 img.setDevicePixelRatio(additionalDevicePixelRatio);
908 }
909
910 // Blitting backing store
911 bool useRegion = partIsTransparent && !hasAlpha && !wasAlphaSwapped;
912
913 QRegion newRegion;
914 QRegion oldRegion;
915 if (useRegion) {
916 newRegion = region(themeData);
917 oldRegion = painter->clipRegion();
918 painter->setClipRegion(newRegion);
919#if defined(DEBUG_XP_STYLE) && 0
920 printf("Using region:\n");
921 for (const QRect &r : newRegion)
922 printf(" (%d, %d, %d, %d)\n", r.x(), r.y(), r.right(), r.bottom());
923#endif
924 }
925
926 if (addBorderContentClipping)
927 painter->setClipRegion(scaleRegion(extraClip, 1.0 / additionalDevicePixelRatio), Qt::IntersectClip);
928
929 if (!themeData.mirrorHorizontally && !themeData.mirrorVertically && !themeData.rotate) {
930 if (!haveCachedPixmap)
931 painter->drawImage(themeData.rect, img, rect);
932 else
933 painter->drawPixmap(themeData.rect, cachedPixmap);
934 } else {
935 // This is _slow_!
936 // Make a copy containing only the necessary data, and mirror
937 // on all wanted axes. Then draw the copy.
938 // If cached, the normal pixmap is cached, instead of caching
939 // all possible orientations for each part and state.
940 QImage imgCopy;
941 if (!haveCachedPixmap)
942 imgCopy = img.copy(rect);
943 else
944 imgCopy = cachedPixmap.toImage();
945
946 if (themeData.rotate) {
947 QTransform rotMatrix;
948 rotMatrix.rotate(themeData.rotate);
949 imgCopy = imgCopy.transformed(rotMatrix);
950 }
951 if (themeData.mirrorHorizontally || themeData.mirrorVertically) {
952 imgCopy = imgCopy.mirrored(themeData.mirrorHorizontally, themeData.mirrorVertically);
953 }
954 painter->drawImage(themeData.rect,
955 imgCopy);
956 }
957
958 if (useRegion || addBorderContentClipping) {
959 if (oldRegion.isEmpty())
960 painter->setClipping(false);
961 else
962 painter->setClipRegion(oldRegion);
963 }
964
965 // Cache the pixmap to avoid expensive swapAlphaChannel() calls
966 if (!haveCachedPixmap && w && h) {
968 QPixmapCache::insert(pixmapCacheKey, pix);
969#ifdef DEBUG_XP_STYLE
970 printf("+++Adding pixmap to cache, size(%d, %d), wasAlphaSwapped(%d), wasAlphaFixed(%d), name(%s)\n",
971 w, h, wasAlphaSwapped, wasAlphaFixed, qPrintable(pixmapCacheKey));
972#endif
973 }
974
975 // Add to theme part cache
976 if (!isCached) {
977 memset(static_cast<void *>(&data), 0, sizeof(data));
978 data.dataValid = true;
979 data.partIsTransparent = partIsTransparent;
980 data.alphaType = alphaType;
981 data.hasAlphaChannel = hasAlpha;
982 data.wasAlphaSwapped = wasAlphaSwapped;
983 data.hadInvalidAlpha = wasAlphaFixed;
984 alphaCache.insert(key, data);
985 }
986 return true;
987}
988
989
990// ------------------------------------------------------------------------------------------------
991
1020
1025
1028{
1031 }
1032
1033 QRect rect(option->rect);
1034 switch (sr) {
1038 return rect.translated(0, 1);
1039 break;
1040#if 0
1042 if (qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(option))
1043 {
1045 if (sr == SE_TabWidgetTabContents) {
1046 if (const QTabWidget *tabWidget = qobject_cast<const QTabWidget *>(widget)) {
1047 if (tabWidget->documentMode())
1048 break;
1049 }
1050
1051 rect.adjust(0, 0, -2, -2);
1052 }
1053 }
1054 break;
1055 case SE_TabWidgetTabBar: {
1057 const QStyleOptionTabWidgetFrame *twfOption =
1058 qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(option);
1059 if (twfOption && twfOption->direction == Qt::RightToLeft
1060 && (twfOption->shape == QTabBar::RoundedNorth
1061 || twfOption->shape == QTabBar::RoundedSouth))
1062 {
1063 QStyleOptionTab otherOption;
1064 otherOption.shape = (twfOption->shape == QTabBar::RoundedNorth
1066 int overlap = proxy()->pixelMetric(PM_TabBarBaseOverlap, &otherOption);
1067 int borderThickness = proxy()->pixelMetric(PM_DefaultFrameWidth, option);
1068 rect.adjust(-overlap + borderThickness, 0, -overlap + borderThickness, 0);
1069 }
1070 break;}
1071#endif
1073 if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) {
1074 MARGINS borderSize;
1075 if (option->window) {
1076 XPThemeData buttontheme(option->window, nullptr, QWindowsXPStylePrivate::ButtonTheme);
1077 HTHEME theme = buttontheme.handle();
1078 if (theme) {
1079 int stateId;
1080 if (!(option->state & State_Enabled))
1081 stateId = PBS_DISABLED;
1082 else if (option->state & State_Sunken)
1083 stateId = PBS_PRESSED;
1084 else if (option->state & State_MouseOver)
1085 stateId = PBS_HOT;
1087 stateId = PBS_DEFAULTED;
1088 else
1089 stateId = PBS_NORMAL;
1090
1092 rect = option->rect.adjusted(border, border, -border, -border);
1093
1094 if (SUCCEEDED(GetThemeMargins(theme, nullptr, BP_PUSHBUTTON, stateId, TMT_CONTENTMARGINS, nullptr, &borderSize))) {
1095 rect.adjust(borderSize.cxLeftWidth, borderSize.cyTopHeight,
1096 -borderSize.cxRightWidth, -borderSize.cyBottomHeight);
1097 rect = visualRect(option->direction, option->rect, rect);
1098 }
1099 }
1100 }
1101 }
1102 break;
1105 if (option->state & QStyle::State_Horizontal)
1106 rect.adjust(4, 3, -4, -3);
1107 else
1108 rect.adjust(3, 2, -3, -2);
1109 break;
1110 default:
1112 }
1113 return rect;
1114}
1115
1120{
1121 QWindowsXPStylePrivate *d = const_cast<QWindowsXPStylePrivate*>(d_func());
1122
1125 return;
1126 }
1127
1128 int themeNumber = -1;
1129 int partId = 0;
1130 int stateId = 0;
1131 QRect rect = option->rect;
1132 State flags = option->state;
1133 bool hMirrored = false;
1134 bool vMirrored = false;
1135 bool noBorder = false;
1136 bool noContent = false;
1137 int rotate = 0;
1138
1139 switch (pe) {
1140#if 0
1141 case PE_FrameTabBarBase:
1142 if (const QStyleOptionTabBarBase *tbb
1143 = qstyleoption_cast<const QStyleOptionTabBarBase *>(option)) {
1144 p->save();
1145 switch (tbb->shape) {
1147 p->setPen(QPen(tbb->palette.dark(), 0));
1148 p->drawLine(tbb->rect.topLeft(), tbb->rect.topRight());
1149 break;
1151 p->setPen(QPen(tbb->palette.dark(), 0));
1152 p->drawLine(tbb->rect.left(), tbb->rect.top(), tbb->rect.left(), tbb->rect.bottom());
1153 break;
1155 p->setPen(QPen(tbb->palette.dark(), 0));
1156 p->drawLine(tbb->rect.left(), tbb->rect.top(),
1157 tbb->rect.right(), tbb->rect.top());
1158 break;
1160 p->setPen(QPen(tbb->palette.dark(), 0));
1161 p->drawLine(tbb->rect.topLeft(), tbb->rect.bottomLeft());
1162 break;
1167 p->restore();
1169 return;
1170 }
1171 p->restore();
1172 }
1173 return;
1174#endif
1177 partId = BP_PUSHBUTTON;
1178 if (!(flags & State_Enabled))
1179 stateId = PBS_DISABLED;
1180 else if ((flags & State_Sunken) || (flags & State_On))
1181 stateId = PBS_PRESSED;
1182 else if (flags & State_MouseOver)
1183 stateId = PBS_HOT;
1184 //else if (flags & State_ButtonDefault)
1185 // stateId = PBS_DEFAULTED;
1186 else
1187 stateId = PBS_NORMAL;
1188 break;
1189
1190 case PE_PanelButtonTool:
1191// if (widget && widget->inherits("QDockWidgetTitleButton")) {
1192// if (const QWidget *dw = widget->parentWidget())
1193// if (dw->isWindow())
1194// return;
1195// }
1197 partId = TP_BUTTON;
1198 if (!(flags & State_Enabled))
1199 stateId = TS_DISABLED;
1200 else if (flags & State_Sunken)
1201 stateId = TS_PRESSED;
1202 else if (flags & State_MouseOver)
1203 stateId = flags & State_On ? TS_HOTCHECKED : TS_HOT;
1204 else if (flags & State_On)
1205 stateId = TS_CHECKED;
1206 else if (!(flags & State_AutoRaise))
1207 stateId = TS_HOT;
1208 else
1209 stateId = TS_NORMAL;
1210 break;
1211
1214 partId = TP_SPLITBUTTONDROPDOWN;
1215 if (!(flags & State_Enabled))
1216 stateId = TS_DISABLED;
1217 else if (flags & State_Sunken)
1218 stateId = TS_PRESSED;
1219 else if (flags & State_MouseOver)
1220 stateId = flags & State_On ? TS_HOTCHECKED : TS_HOT;
1221 else if (flags & State_On)
1222 stateId = TS_CHECKED;
1223 else if (!(flags & State_AutoRaise))
1224 stateId = TS_HOT;
1225 else
1226 stateId = TS_NORMAL;
1227 if (option->direction == Qt::RightToLeft)
1228 hMirrored = true;
1229 break;
1230
1233 partId = BP_CHECKBOX;
1234 if (!(flags & State_Enabled))
1235 stateId = CBS_UNCHECKEDDISABLED;
1236 else if (flags & State_Sunken)
1237 stateId = CBS_UNCHECKEDPRESSED;
1238 else if (flags & State_MouseOver)
1239 stateId = CBS_UNCHECKEDHOT;
1240 else
1241 stateId = CBS_UNCHECKEDNORMAL;
1242
1243 if (flags & State_On)
1244 stateId += CBS_CHECKEDNORMAL-1;
1245 else if (flags & State_NoChange)
1246 stateId += CBS_MIXEDNORMAL-1;
1247
1248 break;
1249
1252 partId = BP_RADIOBUTTON;
1253 if (!(flags & State_Enabled))
1254 stateId = RBS_UNCHECKEDDISABLED;
1255 else if (flags & State_Sunken)
1256 stateId = RBS_UNCHECKEDPRESSED;
1257 else if (flags & State_MouseOver)
1258 stateId = RBS_UNCHECKEDHOT;
1259 else
1260 stateId = RBS_UNCHECKEDNORMAL;
1261
1262 if (flags & State_On)
1263 stateId += RBS_CHECKEDNORMAL-1;
1264 break;
1265
1267 return;
1268
1269case PE_Frame:
1270 {
1271 if (flags & State_Raised)
1272 return;
1274 partId = LVP_LISTGROUP;
1275 XPThemeData theme(option->window, nullptr, themeNumber, partId);
1276
1277 if (!(flags & State_Enabled))
1278 stateId = ETS_DISABLED;
1279 else
1280 stateId = ETS_NORMAL;
1281 int fillType;
1282 if (GetThemeEnumValue(theme.handle(), partId, stateId, TMT_BGTYPE, &fillType) == S_OK) {
1283 if (fillType == BT_BORDERFILL) {
1284 COLORREF bcRef;
1285 GetThemeColor(theme.handle(), partId, stateId, TMT_BORDERCOLOR, &bcRef);
1286 QColor bordercolor(qRgb(GetRValue(bcRef), GetGValue(bcRef), GetBValue(bcRef)));
1287 QPen oldPen = p->pen();
1288 // int borderSize = 1;
1289 // GetThemeInt(theme.handle(), partId, stateId, TMT_BORDERCOLOR, &borderSize);
1290
1291 // Inner white border
1292 p->setPen(QPen(option->palette.base().color(), 0));
1293 const qreal dpi = QStyleHelper::dpi(option);
1294 const auto topLevelAdjustment = QStyleHelper::dpiScaled(0.5, dpi);
1295 const auto bottomRightAdjustment = QStyleHelper::dpiScaled(-1, dpi);
1296 p->drawRect(QRectF(option->rect).adjusted(topLevelAdjustment, topLevelAdjustment,
1297 bottomRightAdjustment, bottomRightAdjustment));
1298 // Outer dark border
1299 p->setPen(QPen(bordercolor, 0));
1300 p->drawRect(QRectF(option->rect).adjusted(0, 0, -topLevelAdjustment, -topLevelAdjustment));
1301 p->setPen(oldPen);
1302 return;
1303 }
1304 if (fillType == BT_NONE)
1305 return;
1306 }
1307 break;
1308 }
1309 case PE_FrameLineEdit: {
1310 // we try to check if this lineedit is a delegate on a QAbstractItemView-derived class.
1311 /*
1312 if (QWindowsXPStylePrivate::isItemViewDelegateLineEdit(widget)) {
1313 QPen oldPen = p->pen();
1314 // Inner white border
1315 p->setPen(QPen(option->palette.base().color(), 1));
1316 p->drawRect(option->rect.adjusted(1, 1, -2, -2));
1317 // Outer dark border
1318 p->setPen(QPen(option->palette.shadow().color(), 1));
1319 p->drawRect(option->rect.adjusted(0, 0, -1, -1));
1320 p->setPen(oldPen);
1321 return;
1322 }
1323 */
1324 if (qstyleoption_cast<const QStyleOptionFrame *>(option)) {
1326 partId = EP_EDITTEXT;
1327 noContent = true;
1328 if (!(flags & State_Enabled))
1329 stateId = ETS_DISABLED;
1330 else
1331 stateId = ETS_NORMAL;
1332 }
1333 break;
1334 }
1335
1336 case PE_PanelLineEdit:
1337 if (const QStyleOptionFrame *panel = qstyleoption_cast<const QStyleOptionFrame *>(option)) {
1339 partId = EP_EDITTEXT;
1340 noBorder = true;
1341 bool isEnabled = flags & State_Enabled;
1342
1343 stateId = isEnabled ? ETS_NORMAL : ETS_DISABLED;
1344
1345 /*if (QWindowsXPStylePrivate::isLineEditBaseColorSet(option, widget)) {
1346 p->fillRect(panel->rect, panel->palette.brush(QPalette::Base));
1347 } else*/ {
1348 XPThemeData theme(nullptr, p, themeNumber, partId, stateId, rect);
1349 if (!theme.isValid()) {
1351 return;
1352 }
1353 int bgType;
1354 GetThemeEnumValue(theme.handle(), partId, stateId, TMT_BGTYPE, &bgType);
1355 if ( bgType == BT_IMAGEFILE ) {
1356 theme.mirrorHorizontally = hMirrored;
1357 theme.mirrorVertically = vMirrored;
1358 theme.noBorder = noBorder;
1359 theme.noContent = noContent;
1360 theme.rotate = rotate;
1361 d->drawBackground(theme);
1362 } else {
1363 QBrush fillColor = option->palette.brush(QPalette::Base);
1364
1365 if (!isEnabled) {
1366 PROPERTYORIGIN origin = PO_NOTFOUND;
1367 GetThemePropertyOrigin(theme.handle(), theme.partId, theme.stateId, TMT_FILLCOLOR, &origin);
1368 // Use only if the fill property comes from our part
1369 if ((origin == PO_PART || origin == PO_STATE)) {
1370 COLORREF bgRef;
1371 GetThemeColor(theme.handle(), partId, stateId, TMT_FILLCOLOR, &bgRef);
1372 fillColor = QBrush(qRgb(GetRValue(bgRef), GetGValue(bgRef), GetBValue(bgRef)));
1373 }
1374 }
1375 p->fillRect(option->rect, fillColor);
1376 }
1377 }
1378
1379 if (panel->lineWidth > 0)
1381 return;
1382 }
1383 break;
1384#if 0
1385 case PE_FrameTabWidget:
1386 if (const QStyleOptionTabWidgetFrame *tab = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(option))
1387 {
1389 partId = TABP_PANE;
1390
1391 if (option->window) {
1392 bool useGradient = true;
1393 const int maxlength = 256;
1394 wchar_t themeFileName[maxlength];
1395 wchar_t themeColor[maxlength];
1396 // Due to a a scaling issue with the XP Silver theme, tab gradients are not used with it
1397 if (GetCurrentThemeName(themeFileName, maxlength, themeColor, maxlength, nullptr, 0) == S_OK) {
1398 wchar_t *offset = nullptr;
1399 if ((offset = wcsrchr(themeFileName, QChar(QLatin1Char('\\')).unicode())) != nullptr) {
1400 offset++;
1401 if (!lstrcmp(offset, L"Luna.msstyles") && !lstrcmp(offset, L"Metallic")) {
1402 useGradient = false;
1403 }
1404 }
1405 }
1406 // This should work, but currently there's an error in the ::drawBackgroundDirectly()
1407 // code, when using the HDC directly..
1408 if (useGradient) {
1409 QStyleOptionTabWidgetFrame frameOpt = *tab;
1410 //frameOpt.rect = widget->rect();
1411
1412 QRect contentsRect = subElementRect(SE_TabWidgetTabContents, &frameOpt);
1413 QRegion reg = option->rect;
1414 reg -= contentsRect;
1415 p->setClipRegion(reg);
1416 XPThemeData theme(option->window, p, themeNumber, partId, stateId, rect);
1417 theme.mirrorHorizontally = hMirrored;
1418 theme.mirrorVertically = vMirrored;
1419 d->drawBackground(theme);
1420 p->setClipRect(contentsRect);
1421 partId = TABP_BODY;
1422 }
1423 }
1424 switch (tab->shape) {
1427 break;
1430 vMirrored = true;
1431 break;
1434 rotate = 90;
1435 break;
1438 rotate = 90;
1439 hMirrored = true;
1440 break;
1441 default:
1442 break;
1443 }
1444 }
1445 break;
1446#endif
1447 case PE_FrameMenu:
1448 p->save();
1449 p->setPen(option->palette.dark().color());
1450 p->drawRect(rect.adjusted(0, 0, -1, -1));
1451 p->restore();
1452 return;
1453
1454 case PE_PanelMenuBar:
1455 break;
1456
1457 case PE_FrameDockWidget:
1458 if (const QStyleOptionFrame *frm = qstyleoption_cast<const QStyleOptionFrame *>(option))
1459 {
1461 if (flags & State_Active)
1462 stateId = FS_ACTIVE;
1463 else
1464 stateId = FS_INACTIVE;
1465
1466 int fwidth = proxy()->pixelMetric(PM_DockWidgetFrameWidth, frm);
1467
1468 XPThemeData theme(option->window, p, themeNumber, 0, stateId);
1469 if (!theme.isValid())
1470 break;
1471 theme.rect = QRect(frm->rect.x(), frm->rect.y(), frm->rect.x()+fwidth, frm->rect.height()-fwidth); theme.partId = WP_SMALLFRAMELEFT;
1472 d->drawBackground(theme);
1473 theme.rect = QRect(frm->rect.width()-fwidth, frm->rect.y(), fwidth, frm->rect.height()-fwidth);
1474 theme.partId = WP_SMALLFRAMERIGHT;
1475 d->drawBackground(theme);
1476 theme.rect = QRect(frm->rect.x(), frm->rect.bottom()-fwidth+1, frm->rect.width(), fwidth);
1477 theme.partId = WP_SMALLFRAMEBOTTOM;
1478 d->drawBackground(theme);
1479 return;
1480 }
1481 break;
1482
1484 {
1485#if 0 // XP theme engine doesn't know about this :(
1487 partId = HP_HEADERSORTARROW;
1488 if (flags & State_Down)
1489 stateId = HSAS_SORTEDDOWN;
1490 else
1491 stateId = HSAS_SORTEDUP;
1492#else
1493 if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) {
1494 p->save();
1495 p->setPen(option->palette.dark().color());
1496 p->translate(0, option->rect.height()/2 - 4);
1497 if (header->sortIndicator & QStyleOptionHeader::SortUp) { // invert logic to follow Windows style guide
1498 p->drawLine(option->rect.x(), option->rect.y(), option->rect.x()+8, option->rect.y());
1499 p->drawLine(option->rect.x()+1, option->rect.y()+1, option->rect.x()+7, option->rect.y()+1);
1500 p->drawLine(option->rect.x()+2, option->rect.y()+2, option->rect.x()+6, option->rect.y()+2);
1501 p->drawLine(option->rect.x()+3, option->rect.y()+3, option->rect.x()+5, option->rect.y()+3);
1502 p->drawPoint(option->rect.x()+4, option->rect.y()+4);
1503 } else if (header->sortIndicator & QStyleOptionHeader::SortDown) {
1504 p->drawLine(option->rect.x(), option->rect.y()+4, option->rect.x()+8, option->rect.y()+4);
1505 p->drawLine(option->rect.x()+1, option->rect.y()+3, option->rect.x()+7, option->rect.y()+3);
1506 p->drawLine(option->rect.x()+2, option->rect.y()+2, option->rect.x()+6, option->rect.y()+2);
1507 p->drawLine(option->rect.x()+3, option->rect.y()+1, option->rect.x()+5, option->rect.y()+1);
1508 p->drawPoint(option->rect.x()+4, option->rect.y());
1509 }
1510 p->restore();
1511 return;
1512 }
1513#endif
1514 }
1515 break;
1516
1519 partId = SP_PANE;
1520 break;
1521
1522 case PE_FrameGroupBox:
1524 partId = BP_GROUPBOX;
1525 if (!(flags & State_Enabled))
1526 stateId = GBS_DISABLED;
1527 else
1528 stateId = GBS_NORMAL;
1529 if (const QStyleOptionFrame *frame = qstyleoption_cast<const QStyleOptionFrame *>(option)) {
1530 if (frame->features & QStyleOptionFrame::Flat) {
1531 // Windows XP does not have a theme part for a flat GroupBox, paint it with the windows style
1532 QRect fr = frame->rect;
1533 QPoint p1(fr.x(), fr.y() + 1);
1534 QPoint p2(fr.x() + fr.width(), p1.y() + 1);
1535 rect = QRect(p1, p2);
1536 themeNumber = -1;
1537 }
1538 }
1539 break;
1540
1542 {
1544 bool inverted = false;
1545 if (const QStyleOptionProgressBar *pb = qstyleoption_cast<const QStyleOptionProgressBar *>(option)) {
1546 orient = pb->state & QStyle::State_Horizontal ? Qt::Horizontal : Qt::Vertical;
1547 inverted = pb->invertedAppearance;
1548 }
1549 if (orient == Qt::Horizontal) {
1550 partId = PP_CHUNK;
1551 rect = QRect(option->rect.x(), option->rect.y(), option->rect.width(), option->rect.height() );
1552 if (inverted && option->direction == Qt::LeftToRight)
1553 hMirrored = true;
1554 } else {
1555 partId = PP_CHUNKVERT;
1556 rect = QRect(option->rect.x(), option->rect.y(), option->rect.width(), option->rect.height());
1557 }
1559 stateId = 1;
1560 }
1561 break;
1562
1563 case PE_FrameWindow:
1564 if (const QStyleOptionFrame *frm = qstyleoption_cast<const QStyleOptionFrame *>(option))
1565 {
1567 if (flags & State_Active)
1568 stateId = FS_ACTIVE;
1569 else
1570 stateId = FS_INACTIVE;
1571
1572 int fwidth = int((frm->lineWidth + frm->midLineWidth) / QWindowsStylePrivate::nativeMetricScaleFactor(option));
1573
1574 XPThemeData theme(option->window, p, themeNumber, 0, stateId);
1575 if (!theme.isValid())
1576 break;
1577
1578 // May fail due to too-large buffers for large widgets, fall back to Windows style.
1579 theme.rect = QRect(option->rect.x(), option->rect.y()+fwidth, option->rect.x()+fwidth, option->rect.height()-fwidth);
1580 theme.partId = WP_FRAMELEFT;
1581 if (!d->drawBackground(theme)) {
1583 return;
1584 }
1585 theme.rect = QRect(option->rect.width()-fwidth, option->rect.y()+fwidth, fwidth, option->rect.height()-fwidth);
1586 theme.partId = WP_FRAMERIGHT;
1587 if (!d->drawBackground(theme)) {
1589 return;
1590 }
1591 theme.rect = QRect(option->rect.x(), option->rect.height()-fwidth, option->rect.width(), fwidth);
1592 theme.partId = WP_FRAMEBOTTOM;
1593 if (!d->drawBackground(theme)) {
1595 return;
1596 }
1597 theme.rect = QRect(option->rect.x(), option->rect.y(), option->rect.width(), option->rect.y()+fwidth);
1598 theme.partId = WP_CAPTION;
1599 if (!d->drawBackground(theme))
1601 return;
1602 }
1603 break;
1604
1605 case PE_IndicatorBranch:
1606 {
1607 static const int decoration_size = 9;
1608 int mid_h = option->rect.x() + option->rect.width() / 2;
1609 int mid_v = option->rect.y() + option->rect.height() / 2;
1610 int bef_h = mid_h;
1611 int bef_v = mid_v;
1612 int aft_h = mid_h;
1613 int aft_v = mid_v;
1614 QBrush brush(option->palette.dark().color(), Qt::Dense4Pattern);
1615 if (option->state & State_Item) {
1616 if (option->direction == Qt::RightToLeft)
1617 p->fillRect(option->rect.left(), mid_v, bef_h - option->rect.left(), 1, brush);
1618 else
1619 p->fillRect(aft_h, mid_v, option->rect.right() - aft_h + 1, 1, brush);
1620 }
1621 if (option->state & State_Sibling)
1622 p->fillRect(mid_h, aft_v, 1, option->rect.bottom() - aft_v + 1, brush);
1624 p->fillRect(mid_h, option->rect.y(), 1, bef_v - option->rect.y(), brush);
1625 if (option->state & State_Children) {
1626 int delta = decoration_size / 2;
1627 bef_h -= delta;
1628 bef_v -= delta;
1629 aft_h += delta;
1630 aft_v += delta;
1632 theme.rect = QRect(bef_h, bef_v, decoration_size, decoration_size);
1633 theme.partId = TVP_GLYPH;
1634 theme.stateId = flags & QStyle::State_Open ? GLPS_OPENED : GLPS_CLOSED;
1635 d->drawBackground(theme);
1636 }
1637 }
1638 return;
1639
1641 if (option->rect.height() < 3) {
1642 // XP style requires a few pixels for the separator
1643 // to be visible.
1645 return;
1646 }
1648 partId = TP_SEPARATOR;
1649
1650 if (option->state & State_Horizontal)
1651 partId = TP_SEPARATOR;
1652 else
1653 partId = TP_SEPARATORVERT;
1654
1655 break;
1656
1658
1660 partId = RP_GRIPPER;
1661 if (option->state & State_Horizontal) {
1662 partId = RP_GRIPPER;
1663 rect.adjust(0, 0, -2, 0);
1664 }
1665 else {
1666 partId = RP_GRIPPERVERT;
1667 rect.adjust(0, 0, 0, -2);
1668 }
1669 break;
1670
1673 button.QStyleOption::operator=(*option);
1674 button.state &= ~State_MouseOver;
1676 return;
1677 }
1678
1679 default:
1680 break;
1681 }
1682
1683 XPThemeData theme(option->window, p, themeNumber, partId, stateId, rect);
1684 if (!theme.isValid()) {
1686 return;
1687 }
1688 theme.mirrorHorizontally = hMirrored;
1689 theme.mirrorVertically = vMirrored;
1690 theme.noBorder = noBorder;
1691 theme.noContent = noContent;
1692 theme.rotate = rotate;
1693 d->drawBackground(theme);
1694}
1695
1700{
1701 QWindowsXPStylePrivate *d = const_cast<QWindowsXPStylePrivate*>(d_func());
1704 return;
1705 }
1706
1707 QRect rect(option->rect);
1708 State flags = option->state;
1709
1710 int rotate = 0;
1711 bool hMirrored = false;
1712 bool vMirrored = false;
1713
1714 int themeNumber = -1;
1715 int partId = 0;
1716 int stateId = 0;
1717 switch (element) {
1718 case CE_SizeGrip:
1719 {
1721 partId = SP_GRIPPER;
1722 XPThemeData theme(nullptr, p, themeNumber, partId);
1724 size.rheight()--;
1725 if (const QStyleOptionSizeGrip *sg = qstyleoption_cast<const QStyleOptionSizeGrip *>(option)) {
1726 switch (sg->corner) {
1728 rect = QRect(QPoint(rect.right() - size.width(), rect.bottom() - size.height()), size);
1729 break;
1731 rect = QRect(QPoint(rect.left() + 1, rect.bottom() - size.height()), size);
1732 hMirrored = true;
1733 break;
1734 case Qt::TopRightCorner:
1735 rect = QRect(QPoint(rect.right() - size.width(), rect.top() + 1), size);
1736 vMirrored = true;
1737 break;
1738 case Qt::TopLeftCorner:
1739 rect = QRect(rect.topLeft() + QPoint(1, 1), size);
1740 hMirrored = vMirrored = true;
1741 }
1742 }
1743 }
1744 break;
1745
1746 case CE_HeaderSection:
1748 partId = HP_HEADERITEM;
1749 if (flags & State_Sunken)
1750 stateId = HIS_PRESSED;
1751 else if (flags & State_MouseOver)
1752 stateId = HIS_HOT;
1753 else
1754 stateId = HIS_NORMAL;
1755 break;
1756
1757 case CE_Splitter:
1758 p->eraseRect(option->rect);
1759 return;
1760
1761 case CE_PushButtonBevel:
1762 if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option))
1763 {
1765 partId = BP_PUSHBUTTON;
1766 bool justFlat = ((btn->features & QStyleOptionButton::Flat) && !(flags & (State_On|State_Sunken)))
1768 && !(flags & State_MouseOver)
1771 stateId = PBS_DISABLED;
1772 else if (justFlat)
1773 ;
1774 else if (flags & (State_Sunken | State_On))
1775 stateId = PBS_PRESSED;
1776 else if (flags & State_MouseOver)
1777 stateId = PBS_HOT;
1779 stateId = PBS_DEFAULTED;
1780 else
1781 stateId = PBS_NORMAL;
1782
1783 if (!justFlat) {
1784 XPThemeData theme(option->window, p, themeNumber, partId, stateId, rect);
1785 d->drawBackground(theme);
1786 }
1787
1789 int mbiw = 0, mbih = 0;
1790 XPThemeData theme(option->window, nullptr,
1792 TP_SPLITBUTTONDROPDOWN);
1793 if (theme.isValid()) {
1795 mbiw = size.width();
1796 mbih = size.height();
1797 }
1798
1799 QRect ir = btn->rect;
1800 QStyleOptionButton newBtn = *btn;
1801 newBtn.rect = QRect(ir.right() - mbiw - 1, 1 + (ir.height()/2) - (mbih/2), mbiw, mbih);
1803 }
1804 return;
1805 }
1806 break;
1807 case CE_TabBarTab:
1808 if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(option))
1809 {
1810 stateId = tab->state & State_Enabled ? TIS_NORMAL : TIS_DISABLED;
1811 }
1812 break;
1813#if 0
1814 case CE_TabBarTabShape:
1815 if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(option))
1816 {
1818 bool isDisabled = !(tab->state & State_Enabled);
1819 bool hasFocus = tab->state & State_HasFocus;
1820 bool isHot = tab->state & State_MouseOver;
1821 bool selected = tab->state & State_Selected;
1822 bool lastTab = tab->position == QStyleOptionTab::End;
1823 bool firstTab = tab->position == QStyleOptionTab::Beginning;
1824 bool onlyOne = tab->position == QStyleOptionTab::OnlyOneTab;
1825 bool leftAligned = proxy()->styleHint(SH_TabBar_Alignment, tab) == Qt::AlignLeft;
1826 bool centerAligned = proxy()->styleHint(SH_TabBar_Alignment, tab) == Qt::AlignCenter;
1827 int borderThickness = proxy()->pixelMetric(PM_DefaultFrameWidth, option);
1828 int tabOverlap = proxy()->pixelMetric(PM_TabBarTabOverlap, option);
1829
1830 if (isDisabled)
1831 stateId = TIS_DISABLED;
1832 else if (selected)
1833 stateId = TIS_SELECTED;
1834 else if (hasFocus)
1835 stateId = TIS_FOCUSED;
1836 else if (isHot)
1837 stateId = TIS_HOT;
1838 else
1839 stateId = TIS_NORMAL;
1840
1841 // Selecting proper part depending on position
1842 if (firstTab || onlyOne) {
1843 if (leftAligned) {
1844 partId = TABP_TABITEMLEFTEDGE;
1845 } else if (centerAligned) {
1846 partId = TABP_TABITEM;
1847 } else { // rightAligned
1848 partId = TABP_TABITEMRIGHTEDGE;
1849 }
1850 } else {
1851 partId = TABP_TABITEM;
1852 }
1853
1854 if (tab->direction == Qt::RightToLeft
1855 && (tab->shape == QTabBar::RoundedNorth
1856 || tab->shape == QTabBar::RoundedSouth)) {
1857 bool temp = firstTab;
1858 firstTab = lastTab;
1859 lastTab = temp;
1860 }
1861 bool begin = firstTab || onlyOne;
1862 bool end = lastTab || onlyOne;
1863 switch (tab->shape) {
1865 if (selected)
1866 rect.adjust(begin ? 0 : -tabOverlap, 0, end ? 0 : tabOverlap, borderThickness);
1867 else
1868 rect.adjust(begin? tabOverlap : 0, tabOverlap, end ? -tabOverlap : 0, 0);
1869 break;
1871 //vMirrored = true;
1872 rotate = 180; // Not 100% correct, but works
1873 if (selected)
1874 rect.adjust(begin ? 0 : -tabOverlap , -borderThickness, end ? 0 : tabOverlap, 0);
1875 else
1876 rect.adjust(begin ? tabOverlap : 0, 0, end ? -tabOverlap : 0 , -tabOverlap);
1877 break;
1879 rotate = 90;
1880 if (selected) {
1881 rect.adjust(-borderThickness, begin ? 0 : -tabOverlap, 0, end ? 0 : tabOverlap);
1882 }else{
1883 rect.adjust(0, begin ? tabOverlap : 0, -tabOverlap, end ? -tabOverlap : 0);
1884 }
1885 break;
1887 hMirrored = true;
1888 rotate = 90;
1889 if (selected) {
1890 rect.adjust(0, begin ? 0 : -tabOverlap, borderThickness, end ? 0 : tabOverlap);
1891 }else{
1892 rect.adjust(tabOverlap, begin ? tabOverlap : 0, 0, end ? -tabOverlap : 0);
1893 }
1894 break;
1895 default:
1896 themeNumber = -1; // Do our own painting for triangular
1897 break;
1898 }
1899
1900 if (!selected) {
1901 switch (tab->shape) {
1903 rect.adjust(0,0, 0,-1);
1904 break;
1906 rect.adjust(0,1, 0,0);
1907 break;
1909 rect.adjust( 1,0, 0,0);
1910 break;
1912 rect.adjust(0,0, -1,0);
1913 break;
1914 default:
1915 break;
1916 }
1917 }
1918 }
1919 break;
1920#endif
1922 {
1924 if (const QStyleOptionProgressBar *pb = qstyleoption_cast<const QStyleOptionProgressBar *>(option))
1925 orient = pb->state & QStyle::State_Horizontal ? Qt::Horizontal : Qt::Vertical;
1926 partId = (orient == Qt::Horizontal) ? PP_BAR : PP_BARVERT;
1928 stateId = 1;
1929 }
1930 break;
1931
1932 case CE_MenuEmptyArea:
1933 case CE_MenuItem:
1934 if (const QStyleOptionMenuItem *menuitem = qstyleoption_cast<const QStyleOptionMenuItem *>(option))
1935 {
1936 int tab = menuitem->tabWidth;
1937 bool dis = !(menuitem->state & State_Enabled);
1938 bool act = menuitem->state & State_Selected;
1939 bool checkable = menuitem->menuHasCheckableItems;
1940 bool checked = checkable ? menuitem->checked : false;
1941
1942 // windows always has a check column, regardless whether we have an icon or not
1943 int checkcol = qMax(menuitem->maxIconWidth, 12);
1944
1945 int x, y, w, h;
1946 rect.getRect(&x, &y, &w, &h);
1947
1948 QBrush fill = menuitem->palette.brush(act ? QPalette::Highlight : QPalette::Button);
1949 p->fillRect(rect, fill);
1950
1951 if (element == CE_MenuEmptyArea)
1952 break;
1953
1954 // draw separator -------------------------------------------------
1955 if (menuitem->menuItemType == QStyleOptionMenuItem::Separator) {
1956 int yoff = y-1 + h / 2;
1957 p->setPen(menuitem->palette.dark().color());
1958 p->drawLine(x, yoff, x+w, yoff);
1959 ++yoff;
1960 p->setPen(menuitem->palette.light().color());
1961 p->drawLine(x, yoff, x+w, yoff);
1962 return;
1963 }
1964
1965 int xpos = x;
1966
1967 // draw icon ------------------------------------------------------
1968 if (!menuitem->icon.isNull()) {
1970 if (act && !dis)
1972 QPixmap pixmap = checked ?
1973 menuitem->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize, option), mode, QIcon::On) :
1974 menuitem->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize, option), mode);
1975 const int pixw = pixmap.width() / pixmap.devicePixelRatio();
1976 const int pixh = pixmap.height() / pixmap.devicePixelRatio();
1977 QRect iconRect(0, 0, pixw, pixh);
1978 iconRect.moveCenter(QRect(xpos, y, checkcol, h).center());
1979 QRect vIconRect = visualRect(option->direction, option->rect, iconRect);
1980 p->setPen(menuitem->palette.text().color());
1981 p->setBrush(Qt::NoBrush);
1982 if (checked)
1983 p->drawRect(vIconRect.adjusted(-1, -1, 0, 0));
1984 p->drawPixmap(vIconRect.topLeft(), pixmap);
1985
1986 // draw checkmark -------------------------------------------------
1987 } else if (checked) {
1988 QStyleOptionMenuItem newMi = *menuitem;
1989 newMi.state = State_None;
1990 if (!dis)
1991 newMi.state |= State_Enabled;
1992 if (act)
1993 newMi.state |= State_On;
1994
1995 QRect checkMarkRect = QRect(menuitem->rect.x() + windowsItemFrame,
1996 menuitem->rect.y() + windowsItemFrame,
1997 checkcol - 2 * windowsItemFrame,
1998 menuitem->rect.height() - 2*windowsItemFrame);
1999 newMi.rect = visualRect(option->direction, option->rect, checkMarkRect);
2001 }
2002
2003 QColor textColor = dis ? menuitem->palette.text().color() :
2004 act ? menuitem->palette.highlightedText().color() : menuitem->palette.buttonText().color();
2005 p->setPen(textColor);
2006
2007 // draw text ------------------------------------------------------
2008 int xm = windowsItemFrame + checkcol + windowsItemHMargin;
2009 xpos = menuitem->rect.x() + xm;
2010 QRect textRect(xpos, y + windowsItemVMargin, w - xm - windowsRightBorder - tab + 1, h - 2 * windowsItemVMargin);
2011 QRect vTextRect = visualRect(option->direction, option->rect, textRect);
2012 QString s = menuitem->text;
2013 if (!s.isEmpty()) {
2014 p->save();
2015 int t = s.indexOf(QLatin1Char('\t'));
2017 if (!proxy()->styleHint(SH_UnderlineShortcut, menuitem))
2018 text_flags |= Qt::TextHideMnemonic;
2019 // draw tab text ----------------
2020 if (t >= 0) {
2021 QRect vShortcutRect = visualRect(option->direction, option->rect, QRect(textRect.topRight(), menuitem->rect.bottomRight()));
2022 if (dis && !act && proxy()->styleHint(SH_EtchDisabledText, option)) {
2023 p->setPen(menuitem->palette.light().color());
2024 p->drawText(vShortcutRect.adjusted(1,1,1,1), text_flags, s.mid(t + 1));
2025 p->setPen(textColor);
2026 }
2027 p->drawText(vShortcutRect, text_flags, s.mid(t + 1));
2028 s = s.left(t);
2029 }
2030 QFont font = menuitem->font;
2031 if (menuitem->menuItemType == QStyleOptionMenuItem::DefaultItem)
2032 font.setBold(true);
2033 p->setFont(font);
2034 if (dis && !act && proxy()->styleHint(SH_EtchDisabledText, option)) {
2035 p->setPen(menuitem->palette.light().color());
2036 p->drawText(vTextRect.adjusted(1,1,1,1), text_flags, s.left(t));
2037 p->setPen(textColor);
2038 }
2039 p->drawText(vTextRect, text_flags, s);
2040 p->restore();
2041 }
2042
2043 // draw sub menu arrow --------------------------------------------
2044 if (menuitem->menuItemType == QStyleOptionMenuItem::SubMenu) {
2045 int dim = (h - 2) / 2;
2046 PrimitiveElement arrow;
2048 xpos = x + w - windowsArrowHMargin - windowsItemFrame - dim;
2049 QRect vSubMenuRect = visualRect(option->direction, option->rect, QRect(xpos, y + h / 2 - dim / 2, dim, dim));
2050 QStyleOptionMenuItem newMI = *menuitem;
2051 newMI.rect = vSubMenuRect;
2052 newMI.state = dis ? State_None : State_Enabled;
2053 if (act)
2054 newMI.palette.setColor(QPalette::ButtonText, newMI.palette.highlightedText().color());
2055 proxy()->drawPrimitive(arrow, &newMI, p);
2056 }
2057 }
2058 return;
2059
2060 case CE_MenuBarItem:
2061 if (const QStyleOptionMenuItem *mbi = qstyleoption_cast<const QStyleOptionMenuItem *>(option))
2062 {
2063 if (mbi->menuItemType == QStyleOptionMenuItem::DefaultItem)
2064 break;
2065
2066 bool act = mbi->state & State_Selected;
2067 bool dis = !(mbi->state & State_Enabled);
2068
2069 QBrush fill = mbi->palette.brush(act ? QPalette::Highlight : QPalette::Button);
2070 QPalette::ColorRole textRole = dis ? QPalette::Text:
2073
2075 if (!proxy()->styleHint(SH_UnderlineShortcut, mbi))
2077
2078 p->fillRect(rect, fill);
2079 if (!pix.isNull())
2080 drawItemPixmap(p, mbi->rect, alignment, pix);
2081 else
2082 drawItemText(p, mbi->rect, alignment, mbi->palette, mbi->state & State_Enabled, mbi->text, textRole);
2083 }
2084 return;
2085#if 0 && QT_CONFIG(dockwidget)
2086 case CE_DockWidgetTitle:
2087 if (const QStyleOptionDockWidget *dwOpt = qstyleoption_cast<const QStyleOptionDockWidget *>(option))
2088 {
2089 int buttonMargin = 4;
2091 int fw = proxy()->pixelMetric(PM_DockWidgetFrameWidth, dwOpt);
2092 bool isFloating = false; // widget && widget->isWindow();
2093 bool isActive = dwOpt->state & State_Active;
2094
2095 const bool verticalTitleBar = dwOpt->verticalTitleBar;
2096
2097 if (verticalTitleBar) {
2098 rect = rect.transposed();
2099
2100 p->translate(rect.left() - 1, rect.top() + rect.width());
2101 p->rotate(-90);
2102 p->translate(-rect.left() + 1, -rect.top());
2103 }
2104 QRect r = rect.adjusted(0, 2, -1, -3);
2105 QRect titleRect = r;
2106
2107 if (dwOpt->closable) {
2108 QSize sz = proxy()->standardIcon(QStyle::SP_TitleBarCloseButton, dwOpt).actualSize(QSize(10, 10));
2109 titleRect.adjust(0, 0, -sz.width() - mw - buttonMargin, 0);
2110 }
2111
2112 if (dwOpt->floatable) {
2113 QSize sz = proxy()->standardIcon(QStyle::SP_TitleBarMaxButton, dwOpt).actualSize(QSize(10, 10));
2114 titleRect.adjust(0, 0, -sz.width() - mw - buttonMargin, 0);
2115 }
2116
2117 if (isFloating) {
2118 titleRect.adjust(0, -fw, 0, 0);
2119 if (option->window && option->window->icon().cacheKey() != QApplication::windowIcon().cacheKey())
2120 titleRect.adjust(titleRect.height() + mw, 0, 0, 0);
2121 } else {
2122 titleRect.adjust(mw, 0, 0, 0);
2123 if (!dwOpt->floatable && !dwOpt->closable)
2124 titleRect.adjust(0, 0, -mw, 0);
2125 }
2126
2127 if (!verticalTitleBar)
2128 titleRect = visualRect(dwOpt->direction, r, titleRect);
2129
2130 if (!isFloating) {
2131 QPen oldPen = p->pen();
2132 QString titleText = p->fontMetrics().elidedText(dwOpt->title, Qt::ElideRight, titleRect.width());
2133 p->setPen(dwOpt->palette.color(QPalette::Dark));
2134 p->drawRect(r);
2135
2136 if (!titleText.isEmpty()) {
2137 drawItemText(p, titleRect,
2139 dwOpt->state & State_Enabled, titleText,
2141 }
2142
2143 p->setPen(oldPen);
2144 } else {
2146 if (isActive)
2147 stateId = CS_ACTIVE;
2148 else
2149 stateId = CS_INACTIVE;
2150
2151 int titleHeight = rect.height() - 2;
2152 rect = rect.adjusted(-fw, -fw, fw, 0);
2153
2154 XPThemeData theme(option->window, p, themeNumber, 0, stateId);
2155 if (!theme.isValid())
2156 break;
2157
2158 // Draw small type title bar
2159 theme.rect = rect;
2160 theme.partId = WP_SMALLCAPTION;
2161 d->drawBackground(theme);
2162
2163 // Figure out maximal button space on title bar
2164
2165 QIcon ico = option->window->icon();
2166 bool hasIcon = (ico.cacheKey() != QApplication::windowIcon().cacheKey());
2167 if (hasIcon) {
2168 QPixmap pxIco = ico.pixmap(titleHeight);
2169 if (!verticalTitleBar && dwOpt->direction == Qt::RightToLeft)
2170 p->drawPixmap(rect.width() - titleHeight - pxIco.width(), rect.bottom() - titleHeight - 2, pxIco);
2171 else
2172 p->drawPixmap(fw, rect.bottom() - titleHeight - 2, pxIco);
2173 }
2174 if (!dwOpt->title.isEmpty()) {
2175 QPen oldPen = p->pen();
2176 QFont oldFont = p->font();
2177 QFont titleFont = oldFont;
2178 titleFont.setBold(true);
2179 p->setFont(titleFont);
2180 QString titleText
2181 = p->fontMetrics().elidedText(dwOpt->title, Qt::ElideRight, titleRect.width());
2182
2183 int result = TST_NONE;
2184 GetThemeEnumValue(theme.handle(), WP_SMALLCAPTION, isActive ? CS_ACTIVE : CS_INACTIVE, TMT_TEXTSHADOWTYPE, &result);
2185 if (result != TST_NONE) {
2186 COLORREF textShadowRef;
2187 GetThemeColor(theme.handle(), WP_SMALLCAPTION, isActive ? CS_ACTIVE : CS_INACTIVE, TMT_TEXTSHADOWCOLOR, &textShadowRef);
2188 QColor textShadow = qRgb(GetRValue(textShadowRef), GetGValue(textShadowRef), GetBValue(textShadowRef));
2189 p->setPen(textShadow);
2190 drawItemText(p, titleRect.adjusted(1, 1, 1, 1),
2191 Qt::AlignLeft | Qt::AlignBottom, dwOpt->palette,
2192 dwOpt->state & State_Enabled, titleText);
2193 }
2194
2195 COLORREF captionText = GetSysColor(isActive ? COLOR_CAPTIONTEXT : COLOR_INACTIVECAPTIONTEXT);
2196 QColor textColor = qRgb(GetRValue(captionText), GetGValue(captionText), GetBValue(captionText));
2197 p->setPen(textColor);
2198 drawItemText(p, titleRect,
2199 Qt::AlignLeft | Qt::AlignBottom, dwOpt->palette,
2200 dwOpt->state & State_Enabled, titleText);
2201 p->setFont(oldFont);
2202 p->setPen(oldPen);
2203 }
2204
2205 }
2206
2207 return;
2208 }
2209 break;
2210#endif // QT_CONFIG(dockwidget)
2211#if 0 && QT_CONFIG(rubberband)
2212 case CE_RubberBand:
2213 if (qstyleoption_cast<const QStyleOptionRubberBand *>(option)) {
2214 QColor highlight = option->palette.color(QPalette::Active, QPalette::Highlight).toRgb();
2215 p->save();
2216 p->setPen(highlight.darker(120));
2217 QColor dimHighlight(qMin(highlight.red()/2 + 110, 255),
2218 qMin(highlight.green()/2 + 110, 255),
2219 qMin(highlight.blue()/2 + 110, 255),
2220 127);
2221 //(widget && widget->isTopLevel())? 255 : 127);
2222 p->setBrush(dimHighlight);
2223 p->drawRect(option->rect.adjusted(0, 0, -1, -1));
2224 p->restore();
2225 return;
2226 }
2227 break;
2228#endif // QT_CONFIG(rubberband)
2229 case CE_HeaderEmptyArea:
2230 if (option->state & State_Horizontal)
2231 {
2233 stateId = HIS_NORMAL;
2234 }
2235 else {
2237 return;
2238 }
2239 break;
2240 default:
2241 break;
2242 }
2243
2244 XPThemeData theme(option->window, p, themeNumber, partId, stateId, rect);
2245 if (!theme.isValid()) {
2247 return;
2248 }
2249
2250 theme.rotate = rotate;
2251 theme.mirrorHorizontally = hMirrored;
2252 theme.mirrorVertically = vMirrored;
2253 d->drawBackground(theme);
2254}
2255
2257{
2258 const bool horizontal = flags & QStyle::State_Horizontal;
2260 const QMargins contentsMargin =
2261 (theme->margins(theme->rect, TMT_SIZINGMARGINS) * factor).toMargins();
2262 theme->partId = horizontal ? SBP_GRIPPERHORZ : SBP_GRIPPERVERT;
2263 const QSize size = (theme->size() * factor).toSize();
2264
2265 const int hSpace = theme->rect.width() - size.width();
2266 const int vSpace = theme->rect.height() - size.height();
2267 const bool sufficientSpace = (horizontal && hSpace > (contentsMargin.left() + contentsMargin.right()))
2268 || vSpace > contentsMargin.top() + contentsMargin.bottom();
2269 return sufficientSpace ? QRect(theme->rect.topLeft() + QPoint(hSpace, vSpace) / 2, size) : QRect();
2270}
2271
2272#if 0 && QT_CONFIG(mdiarea)
2273// Helper for drawing MDI buttons into the corner widget of QMenuBar in case a
2274// QMdiSubWindow is maximized.
2275static void populateMdiButtonTheme(const QStyle *proxy,
2277 QStyle::SubControl subControl, int part,
2278 XPThemeData *theme)
2279{
2280 theme->partId = part;
2281 theme->rect = proxy->subControlRect(QStyle::CC_MdiControls, option, subControl);
2282 if (!option->state.testFlag(QStyle::State_Enabled))
2283 theme->stateId = CBS_INACTIVE;
2284 else if (option->state.testFlag(QStyle::State_Sunken) && option->activeSubControls.testFlag(subControl))
2285 theme->stateId = CBS_PUSHED;
2286 else if (option->state.testFlag(QStyle::State_MouseOver) && option->activeSubControls.testFlag(subControl))
2287 theme->stateId = CBS_HOT;
2288 else
2289 theme->stateId = CBS_NORMAL;
2290}
2291
2292// Calculate an small (max 2), empirical correction factor for scaling up
2293// WP_MDICLOSEBUTTON, WP_MDIRESTOREBUTTON, WP_MDIMINBUTTON, which are too
2294// small on High DPI screens (QTBUG-75927).
2295qreal mdiButtonCorrectionFactor(XPThemeData &theme, const QPaintDevice *pd = nullptr)
2296{
2297 const auto dpr = pd ? pd->devicePixelRatioF() : qApp->devicePixelRatio();
2298 const QSizeF nativeSize = QSizeF(theme.size()) / dpr;
2299 const QSizeF requestedSize(theme.rect.size());
2300 const auto rawFactor = qMin(requestedSize.width() / nativeSize.width(),
2301 requestedSize.height() / nativeSize.height());
2302 const auto factor = rawFactor >= qreal(2) ? qreal(2) : qreal(1);
2303 return factor;
2304}
2305#endif // QT_CONFIG(mdiarea)
2306
2309 QStyle::SubControl subControl,
2310 bool isTitleBarActive, int part,
2311 XPThemeData *theme)
2312{
2313 theme->rect = proxy->subControlRect(QStyle::CC_TitleBar, option, subControl);
2314 theme->partId = part;
2315 if (!(option->state & QStyle::State_Enabled))
2316 theme->stateId = RBS_DISABLED;
2317 else if (option->activeSubControls == subControl && option->state.testFlag(QStyle::State_Sunken))
2318 theme->stateId = RBS_PUSHED;
2319 else if (option->activeSubControls == subControl && option->state.testFlag(QStyle::State_MouseOver))
2320 theme->stateId = RBS_HOT;
2321 else if (!isTitleBarActive)
2322 theme->stateId = RBS_INACTIVE;
2323 else
2324 theme->stateId = RBS_NORMAL;
2325}
2326
2331 QPainter *p) const
2332{
2333 QWindowsXPStylePrivate *d = const_cast<QWindowsXPStylePrivate*>(d_func());
2334
2337 return;
2338 }
2339
2340 State flags = option->state;
2341 SubControls sub = option->subControls;
2342 QRect r = option->rect;
2343
2344 int partId = 0;
2345 int stateId = 0;
2346 if (option->window && option->window->isActive())
2348
2349 switch (cc) {
2350//#if QT_CONFIG(spinbox)
2351 case CC_SpinBox:
2352 if (const QStyleOptionSpinBox *sb = qstyleoption_cast<const QStyleOptionSpinBox *>(option))
2353 {
2355
2356 if (sb->frame && (sub & SC_SpinBoxFrame)) {
2357 partId = EP_EDITTEXT;
2358 if (!(flags & State_Enabled))
2359 stateId = ETS_DISABLED;
2360 else if (flags & State_HasFocus)
2361 stateId = ETS_FOCUSED;
2362 else
2363 stateId = ETS_NORMAL;
2364
2366 partId, stateId, r);
2367 ftheme.noContent = true;
2368 d->drawBackground(ftheme);
2369 }
2370 if (sub & SC_SpinBoxUp) {
2372 partId = SPNP_UP;
2373 if (!(sb->stepEnabled & QStyleOptionSpinBox::StepUpEnabled) || !(flags & State_Enabled))
2374 stateId = UPS_DISABLED;
2375 else if (sb->activeSubControls == SC_SpinBoxUp && (sb->state & State_Sunken))
2376 stateId = UPS_PRESSED;
2377 else if (sb->activeSubControls == SC_SpinBoxUp && (sb->state & State_MouseOver))
2378 stateId = UPS_HOT;
2379 else
2380 stateId = UPS_NORMAL;
2381 theme.partId = partId;
2382 theme.stateId = stateId;
2383 d->drawBackground(theme);
2384 }
2385 if (sub & SC_SpinBoxDown) {
2387 partId = SPNP_DOWN;
2388 if (!(sb->stepEnabled & QStyleOptionSpinBox::StepDownEnabled) || !(flags & State_Enabled))
2389 stateId = DNS_DISABLED;
2390 else if (sb->activeSubControls == SC_SpinBoxDown && (sb->state & State_Sunken))
2391 stateId = DNS_PRESSED;
2392 else if (sb->activeSubControls == SC_SpinBoxDown && (sb->state & State_MouseOver))
2393 stateId = DNS_HOT;
2394 else
2395 stateId = DNS_NORMAL;
2396 theme.partId = partId;
2397 theme.stateId = stateId;
2398 d->drawBackground(theme);
2399 }
2400 }
2401 break;
2402//#endif // QT_CONFIG(spinbox)
2403//#if QT_CONFIG(combobox)
2404 case CC_ComboBox:
2405 if (const QStyleOptionComboBox *cmb = qstyleoption_cast<const QStyleOptionComboBox *>(option))
2406 {
2407 if (cmb->editable) {
2408 if (sub & SC_ComboBoxEditField) {
2409 partId = EP_EDITBORDER_NOSCROLL;
2410 if (!(flags & State_Enabled))
2411 stateId = ETS_DISABLED;
2412 else if (flags & State_MouseOver)
2413 stateId = ETS_HOT;
2414 else if (flags & State_HasFocus)
2415 stateId = ETS_FOCUSED;
2416 else
2417 stateId = ETS_NORMAL;
2418
2419 XPThemeData theme(option->window, p,
2421 partId, stateId, r);
2422
2423 d->drawBackground(theme);
2424 }
2425 if (sub & SC_ComboBoxArrow) {
2428 theme.rect = subRect;
2429 partId = option->direction == Qt::RightToLeft ? CP_DROPDOWNBUTTONLEFT : CP_DROPDOWNBUTTONRIGHT;
2430
2431 if (!(cmb->state & State_Enabled))
2432 stateId = CBXS_DISABLED;
2433 else if (cmb->state & State_Sunken || cmb->state & State_On)
2434 stateId = CBXS_PRESSED;
2435 else if (cmb->state & State_MouseOver && option->activeSubControls & SC_ComboBoxArrow)
2436 stateId = CBXS_HOT;
2437 else
2438 stateId = CBXS_NORMAL;
2439
2440 theme.partId = partId;
2441 theme.stateId = stateId;
2442 d->drawBackground(theme);
2443 }
2444
2445 } else {
2446 if (sub & SC_ComboBoxFrame) {
2448 theme.rect = option->rect;
2449 theme.partId = CP_READONLY;
2450 if (!(cmb->state & State_Enabled))
2451 theme.stateId = CBXS_DISABLED;
2452 else if (cmb->state & State_Sunken || cmb->state & State_On)
2453 theme.stateId = CBXS_PRESSED;
2454 else if (cmb->state & State_MouseOver)
2455 theme.stateId = CBXS_HOT;
2456 else
2457 theme.stateId = CBXS_NORMAL;
2458 d->drawBackground(theme);
2459 }
2460 if (sub & SC_ComboBoxArrow) {
2463 theme.partId = option->direction == Qt::RightToLeft ? CP_DROPDOWNBUTTONLEFT : CP_DROPDOWNBUTTONRIGHT;
2464 if (!(cmb->state & State_Enabled))
2465 theme.stateId = CBXS_DISABLED;
2466 else
2467 theme.stateId = CBXS_NORMAL;
2468 d->drawBackground(theme);
2469 }
2472 fropt.QStyleOption::operator=(*cmb);
2475 }
2476 }
2477 }
2478 break;
2479//#endif // QT_CONFIG(combobox)
2480 case CC_ScrollBar:
2481 if (const QStyleOptionSlider *scrollbar = qstyleoption_cast<const QStyleOptionSlider *>(option))
2482 {
2484 bool maxedOut = (scrollbar->maximum == scrollbar->minimum);
2485 if (maxedOut)
2486 flags &= ~State_Enabled;
2487
2488 bool isHorz = flags & State_Horizontal;
2489 bool isRTL = option->direction == Qt::RightToLeft;
2490 if (sub & SC_ScrollBarAddLine) {
2492 partId = SBP_ARROWBTN;
2493 if (!(flags & State_Enabled))
2494 stateId = (isHorz ? (isRTL ? ABS_LEFTDISABLED : ABS_RIGHTDISABLED) : ABS_DOWNDISABLED);
2495 else if (scrollbar->activeSubControls & SC_ScrollBarAddLine && (scrollbar->state & State_Sunken))
2496 stateId = (isHorz ? (isRTL ? ABS_LEFTPRESSED : ABS_RIGHTPRESSED) : ABS_DOWNPRESSED);
2497 else if (scrollbar->activeSubControls & SC_ScrollBarAddLine && (scrollbar->state & State_MouseOver))
2498 stateId = (isHorz ? (isRTL ? ABS_LEFTHOT : ABS_RIGHTHOT) : ABS_DOWNHOT);
2499 else
2500 stateId = (isHorz ? (isRTL ? ABS_LEFTNORMAL : ABS_RIGHTNORMAL) : ABS_DOWNNORMAL);
2501 theme.partId = partId;
2502 theme.stateId = stateId;
2503 d->drawBackground(theme);
2504 }
2505 if (sub & SC_ScrollBarSubLine) {
2507 partId = SBP_ARROWBTN;
2508 if (!(flags & State_Enabled))
2509 stateId = (isHorz ? (isRTL ? ABS_RIGHTDISABLED : ABS_LEFTDISABLED) : ABS_UPDISABLED);
2510 else if (scrollbar->activeSubControls & SC_ScrollBarSubLine && (scrollbar->state & State_Sunken))
2511 stateId = (isHorz ? (isRTL ? ABS_RIGHTPRESSED : ABS_LEFTPRESSED) : ABS_UPPRESSED);
2512 else if (scrollbar->activeSubControls & SC_ScrollBarSubLine && (scrollbar->state & State_MouseOver))
2513 stateId = (isHorz ? (isRTL ? ABS_RIGHTHOT : ABS_LEFTHOT) : ABS_UPHOT);
2514 else
2515 stateId = (isHorz ? (isRTL ? ABS_RIGHTNORMAL : ABS_LEFTNORMAL) : ABS_UPNORMAL);
2516 theme.partId = partId;
2517 theme.stateId = stateId;
2518 d->drawBackground(theme);
2519 }
2520 if (maxedOut) {
2521 if (sub & SC_ScrollBarSlider) {
2525 partId = scrollbar->orientation == Qt::Horizontal ? SBP_LOWERTRACKHORZ : SBP_LOWERTRACKVERT;
2526 stateId = SCRBS_DISABLED;
2527 theme.partId = partId;
2528 theme.stateId = stateId;
2529 d->drawBackground(theme);
2530 }
2531 } else {
2532 if (sub & SC_ScrollBarSubPage) {
2534 partId = flags & State_Horizontal ? SBP_UPPERTRACKHORZ : SBP_UPPERTRACKVERT;
2535 if (!(flags & State_Enabled))
2536 stateId = SCRBS_DISABLED;
2537 else if (scrollbar->activeSubControls & SC_ScrollBarSubPage && (scrollbar->state & State_Sunken))
2538 stateId = SCRBS_PRESSED;
2539 else if (scrollbar->activeSubControls & SC_ScrollBarSubPage && (scrollbar->state & State_MouseOver))
2540 stateId = SCRBS_HOT;
2541 else
2542 stateId = SCRBS_NORMAL;
2543 theme.partId = partId;
2544 theme.stateId = stateId;
2545 d->drawBackground(theme);
2546 }
2547 if (sub & SC_ScrollBarAddPage) {
2549 partId = flags & State_Horizontal ? SBP_LOWERTRACKHORZ : SBP_LOWERTRACKVERT;
2550 if (!(flags & State_Enabled))
2551 stateId = SCRBS_DISABLED;
2552 else if (scrollbar->activeSubControls & SC_ScrollBarAddPage && (scrollbar->state & State_Sunken))
2553 stateId = SCRBS_PRESSED;
2554 else if (scrollbar->activeSubControls & SC_ScrollBarAddPage && (scrollbar->state & State_MouseOver))
2555 stateId = SCRBS_HOT;
2556 else
2557 stateId = SCRBS_NORMAL;
2558 theme.partId = partId;
2559 theme.stateId = stateId;
2560 d->drawBackground(theme);
2561 }
2562 if (sub & SC_ScrollBarSlider) {
2563 // The style paint the slider handle so that it is surrounded by transparent areas
2564 // on each side. These areas have the same size as the Left/Right (or Top/Left) buttons.
2565 // This is probaly done in order for the handle to travel all along the geometry
2566 // of the slider, while the handle still not occluding the buttons.
2567 // We do not want those transparent areas, so we clip them off here.
2568 const int extentForButton = proxy()->pixelMetric(PM_ScrollBarExtent, scrollbar);
2569 QSize extend(extentForButton, 0);
2570 if (scrollbar->orientation == Qt::Vertical)
2571 extend.transpose();
2572
2573 QRect rect = r; // 'r' is the rect for the scrollbar handle
2574 rect.setSize(rect.size() + 2 * extend); // 'rect' is the rect for the whole scrollbar
2575 p->setClipRect(r); // clip off button areas
2576 p->translate(-extend.width(), -extend.height()); // translate left button area away
2577
2578 theme.rect = rect;
2579 if (!(flags & State_Enabled))
2580 stateId = SCRBS_DISABLED;
2581 else if (scrollbar->activeSubControls & SC_ScrollBarSlider && (scrollbar->state & State_Sunken))
2582 stateId = SCRBS_PRESSED;
2583 else if (scrollbar->activeSubControls & SC_ScrollBarSlider && (scrollbar->state & State_MouseOver))
2584 stateId = SCRBS_HOT;
2585 else
2586 stateId = SCRBS_NORMAL;
2587
2588 // Draw handle
2589 theme.partId = flags & State_Horizontal ? SBP_THUMBBTNHORZ : SBP_THUMBBTNVERT;
2590 theme.stateId = stateId;
2591 d->drawBackground(theme);
2592
2593 const QRect gripperBounds = QWindowsXPStylePrivate::scrollBarGripperBounds(flags, &theme);
2594 // Draw gripper if there is enough space
2595 if (!gripperBounds.isEmpty()) {
2596 p->save();
2597 theme.rect = gripperBounds;
2598 p->setClipRegion(d->region(theme));// Only change inside the region of the gripper
2599 d->drawBackground(theme); // Transparent gripper ontop of background
2600 p->restore();
2601 }
2602 }
2603 }
2604 }
2605 break;
2606
2607//#if QT_CONFIG(slider)
2608 case CC_Slider:
2609 if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(option))
2610 {
2612 QRect slrect = slider->rect;
2613 QRegion tickreg = slrect;
2614 if (sub & SC_SliderGroove) {
2616 if (slider->orientation == Qt::Horizontal) {
2617 partId = TKP_TRACK;
2618 stateId = TRS_NORMAL;
2619 theme.rect = QRect(slrect.left(), theme.rect.center().y() - 2, slrect.width(), 4);
2620 } else {
2621 partId = TKP_TRACKVERT;
2622 stateId = TRVS_NORMAL;
2623 theme.rect = QRect(theme.rect.center().x() - 2, slrect.top(), 4, slrect.height());
2624 }
2625 theme.partId = partId;
2626 theme.stateId = stateId;
2627 d->drawBackground(theme);
2628 tickreg -= theme.rect;
2629 }
2630 if (sub & SC_SliderTickmarks) {
2631 int tickOffset = proxy()->pixelMetric(PM_SliderTickmarkOffset, slider);
2632 int ticks = slider->tickPosition;
2633 int thickness = proxy()->pixelMetric(PM_SliderControlThickness, slider);
2634 int len = proxy()->pixelMetric(PM_SliderLength, slider);
2635 int available = proxy()->pixelMetric(PM_SliderSpaceAvailable, slider);
2636 int interval = slider->tickInterval;
2637 if (interval <= 0) {
2638 interval = slider->singleStep;
2639 if (QStyle::sliderPositionFromValue(slider->minimum, slider->maximum, interval,
2640 available)
2641 - QStyle::sliderPositionFromValue(slider->minimum, slider->maximum,
2642 0, available) < 3)
2643 interval = slider->pageStep;
2644 }
2645 if (!interval)
2646 interval = 1;
2647 int fudge = len / 2;
2648 int pos;
2649 int bothOffset = (ticks & QStyleOptionSlider::TicksAbove && ticks & QStyleOptionSlider::TicksBelow) ? 1 : 0;
2650 p->setPen(d->sliderTickColor);
2651 QVarLengthArray<QLine, 32> lines;
2652 int v = slider->minimum;
2653 while (v <= slider->maximum + 1) {
2654 if (v == slider->maximum + 1 && interval == 1)
2655 break;
2656 const int v_ = qMin(v, slider->maximum);
2657 int tickLength = (v_ == slider->minimum || v_ >= slider->maximum) ? 4 : 3;
2658 pos = QStyle::sliderPositionFromValue(slider->minimum, slider->maximum,
2659 v_, available) + fudge;
2660 if (slider->orientation == Qt::Horizontal) {
2662 lines.append(QLine(pos, tickOffset - 1 - bothOffset,
2663 pos, tickOffset - 1 - bothOffset - tickLength));
2664
2666 lines.append(QLine(pos, tickOffset + thickness + bothOffset,
2667 pos, tickOffset + thickness + bothOffset + tickLength));
2668 } else {
2670 lines.append(QLine(tickOffset - 1 - bothOffset, pos,
2671 tickOffset - 1 - bothOffset - tickLength, pos));
2672
2674 lines.append(QLine(tickOffset + thickness + bothOffset, pos,
2675 tickOffset + thickness + bothOffset + tickLength, pos));
2676 }
2677 // in the case where maximum is max int
2678 int nextInterval = v + interval;
2679 if (nextInterval < v)
2680 break;
2681 v = nextInterval;
2682 }
2683 if (!lines.isEmpty()) {
2684 p->save();
2685 p->translate(slrect.topLeft());
2686 p->drawLines(lines.constData(), lines.size());
2687 p->restore();
2688 }
2689 }
2690 if (sub & SC_SliderHandle) {
2692 if (slider->orientation == Qt::Horizontal) {
2693 if (slider->tickPosition == QStyleOptionSlider::TicksAbove)
2694 partId = TKP_THUMBTOP;
2695 else if (slider->tickPosition == QStyleOptionSlider::TicksBelow)
2696 partId = TKP_THUMBBOTTOM;
2697 else
2698 partId = TKP_THUMB;
2699
2700 if (!(slider->state & State_Enabled))
2701 stateId = TUS_DISABLED;
2702 else if (slider->activeSubControls & SC_SliderHandle && (slider->state & State_Sunken))
2703 stateId = TUS_PRESSED;
2704 else if (slider->activeSubControls & SC_SliderHandle && (slider->state & State_MouseOver))
2705 stateId = TUS_HOT;
2706 else if (flags & State_HasFocus)
2707 stateId = TUS_FOCUSED;
2708 else
2709 stateId = TUS_NORMAL;
2710 } else {
2711 if (slider->tickPosition == QStyleOptionSlider::TicksLeft)
2712 partId = TKP_THUMBLEFT;
2713 else if (slider->tickPosition == QStyleOptionSlider::TicksRight)
2714 partId = TKP_THUMBRIGHT;
2715 else
2716 partId = TKP_THUMBVERT;
2717
2718 if (!(slider->state & State_Enabled))
2719 stateId = TUVS_DISABLED;
2720 else if (slider->activeSubControls & SC_SliderHandle && (slider->state & State_Sunken))
2721 stateId = TUVS_PRESSED;
2722 else if (slider->activeSubControls & SC_SliderHandle && (slider->state & State_MouseOver))
2723 stateId = TUVS_HOT;
2724 else if (flags & State_HasFocus)
2725 stateId = TUVS_FOCUSED;
2726 else
2727 stateId = TUVS_NORMAL;
2728 }
2729 theme.partId = partId;
2730 theme.stateId = stateId;
2731 d->drawBackground(theme);
2732 }
2733 if (sub & SC_SliderGroove && slider->state & State_HasFocus) {
2735 fropt.QStyleOption::operator=(*slider);
2736 fropt.rect = subElementRect(SE_SliderFocusRect, slider);
2738 }
2739 }
2740 break;
2741//#endif
2742#if 0 && QT_CONFIG(toolbutton)
2743 case CC_ToolButton:
2744 if (const QStyleOptionToolButton *toolbutton
2745 = qstyleoption_cast<const QStyleOptionToolButton *>(option)) {
2746 QRect button, menuarea;
2747 button = proxy()->subControlRect(cc, toolbutton, SC_ToolButton);
2748 menuarea = proxy()->subControlRect(cc, toolbutton, SC_ToolButtonMenu);
2749
2750 State bflags = toolbutton->state & ~State_Sunken;
2751 State mflags = bflags;
2752 bool autoRaise = flags & State_AutoRaise;
2753 if (autoRaise) {
2754 if (!(bflags & State_MouseOver) || !(bflags & State_Enabled)) {
2755 bflags &= ~State_Raised;
2756 }
2757 }
2758
2759 if (toolbutton->state & State_Sunken) {
2760 if (toolbutton->activeSubControls & SC_ToolButton) {
2761 bflags |= State_Sunken;
2762 mflags |= State_MouseOver | State_Sunken;
2763 } else if (toolbutton->activeSubControls & SC_ToolButtonMenu) {
2764 mflags |= State_Sunken;
2765 bflags |= State_MouseOver;
2766 }
2767 }
2768
2769 QStyleOption tool = *toolbutton;
2770 if (toolbutton->subControls & SC_ToolButton) {
2771 if (flags & (State_Sunken | State_On | State_Raised) || !autoRaise) {
2772 if (toolbutton->features & QStyleOptionToolButton::MenuButtonPopup && autoRaise) {
2774 theme.partId = TP_SPLITBUTTON;
2775 theme.rect = button;
2776 if (!(bflags & State_Enabled))
2777 stateId = TS_DISABLED;
2778 else if (bflags & State_Sunken)
2779 stateId = TS_PRESSED;
2780 else if (bflags & State_MouseOver || !(flags & State_AutoRaise))
2781 stateId = flags & State_On ? TS_HOTCHECKED : TS_HOT;
2782 else if (bflags & State_On)
2783 stateId = TS_CHECKED;
2784 else
2785 stateId = TS_NORMAL;
2786 if (option->direction == Qt::RightToLeft)
2787 theme.mirrorHorizontally = true;
2788 theme.stateId = stateId;
2789 d->drawBackground(theme);
2790 } else {
2791 tool.rect = option->rect;
2792 tool.state = bflags;
2793 if (autoRaise) // for tool bars
2795 else
2797 }
2798 }
2799 }
2800
2801 if (toolbutton->state & State_HasFocus) {
2803 fr.QStyleOption::operator=(*toolbutton);
2804 fr.rect.adjust(3, 3, -3, -3);
2805 if (toolbutton->features & QStyleOptionToolButton::MenuButtonPopup)
2806 fr.rect.adjust(0, 0, -proxy()->pixelMetric(QStyle::PM_MenuButtonIndicator,
2807 toolbutton), 0);
2809 }
2810 QStyleOptionToolButton label = *toolbutton;
2811 label.state = bflags;
2812 int fw = 2;
2813 if (!autoRaise)
2814 label.state &= ~State_Sunken;
2815 label.rect = button.adjusted(fw, fw, -fw, -fw);
2817
2818 if (toolbutton->subControls & SC_ToolButtonMenu) {
2819 tool.rect = menuarea;
2820 tool.state = mflags;
2821 if (autoRaise) {
2823 } else {
2824 tool.state = mflags;
2825 menuarea.adjust(-2, 0, 0, 0);
2826 // Draw menu button
2827 if ((bflags & State_Sunken) != (mflags & State_Sunken)){
2828 p->save();
2829 p->setClipRect(menuarea);
2830 tool.rect = option->rect;
2832 p->restore();
2833 }
2834 // Draw arrow
2835 p->save();
2836 p->setPen(option->palette.dark().color());
2837 p->drawLine(menuarea.left(), menuarea.top() + 3,
2838 menuarea.left(), menuarea.bottom() - 3);
2839 p->setPen(option->palette.light().color());
2840 p->drawLine(menuarea.left() - 1, menuarea.top() + 3,
2841 menuarea.left() - 1, menuarea.bottom() - 3);
2842
2843 tool.rect = menuarea.adjusted(2, 3, -2, -1);
2845 p->restore();
2846 }
2847 } else if (toolbutton->features & QStyleOptionToolButton::HasMenu) {
2848 int mbi = proxy()->pixelMetric(PM_MenuButtonIndicator, toolbutton);
2849 QRect ir = toolbutton->rect;
2850 QStyleOptionToolButton newBtn = *toolbutton;
2851 newBtn.rect = QRect(ir.right() + 4 - mbi, ir.height() - mbi + 4, mbi - 5, mbi - 5);
2853 }
2854 }
2855 break;
2856#endif // QT_CONFIG(toolbutton)
2857
2858 case CC_TitleBar:
2859 {
2860 if (const QStyleOptionTitleBar *tb = qstyleoption_cast<const QStyleOptionTitleBar *>(option))
2861 {
2863 bool isActive = tb->titleBarState & QStyle::State_Active;
2865 if (sub & SC_TitleBarLabel) {
2866
2867 partId = (tb->titleBarState & Qt::WindowMinimized) ? WP_MINCAPTION : WP_CAPTION;
2868 theme.rect = option->rect;
2869 if (!(option->state & QStyle::State_Enabled))
2870 stateId = CS_DISABLED;
2871 else if (isActive)
2872 stateId = CS_ACTIVE;
2873 else
2874 stateId = CS_INACTIVE;
2875
2876 theme.partId = partId;
2877 theme.stateId = stateId;
2878 d->drawBackground(theme);
2879
2881
2882 int result = TST_NONE;
2883 GetThemeEnumValue(theme.handle(), WP_CAPTION, isActive ? CS_ACTIVE : CS_INACTIVE, TMT_TEXTSHADOWTYPE, &result);
2884 if (result != TST_NONE) {
2885 COLORREF textShadowRef;
2886 GetThemeColor(theme.handle(), WP_CAPTION, isActive ? CS_ACTIVE : CS_INACTIVE, TMT_TEXTSHADOWCOLOR, &textShadowRef);
2887 QColor textShadow = qRgb(GetRValue(textShadowRef), GetGValue(textShadowRef), GetBValue(textShadowRef));
2888 p->setPen(textShadow);
2889 p->drawText(int(ir.x() + 3 * factor), int(ir.y() + 2 * factor),
2890 int(ir.width() - 1 * factor), ir.height(),
2892 }
2893 COLORREF captionText = GetSysColor(isActive ? COLOR_CAPTIONTEXT : COLOR_INACTIVECAPTIONTEXT);
2894 QColor textColor = qRgb(GetRValue(captionText), GetGValue(captionText), GetBValue(captionText));
2895 p->setPen(textColor);
2896 p->drawText(int(ir.x() + 2 * factor), int(ir.y() + 1 * factor),
2897 int(ir.width() - 2 * factor), ir.height(),
2899 }
2900 if (sub & SC_TitleBarSysMenu && tb->titleBarFlags & Qt::WindowSystemMenuHint) {
2902 partId = WP_SYSBUTTON;
2903 if (!(option->state & QStyle::State_Enabled) || !isActive)
2904 stateId = SBS_DISABLED;
2905 else if (option->activeSubControls == SC_TitleBarSysMenu && (option->state & State_Sunken))
2906 stateId = SBS_PUSHED;
2907 else if (option->activeSubControls == SC_TitleBarSysMenu && (option->state & State_MouseOver))
2908 stateId = SBS_HOT;
2909 else
2910 stateId = SBS_NORMAL;
2911 if (!tb->icon.isNull()) {
2912 tb->icon.paint(p, theme.rect);
2913 } else {
2914 theme.partId = partId;
2915 theme.stateId = stateId;
2916 if (theme.size().isEmpty()) {
2919 p->save();
2920 drawItemPixmap(p, theme.rect, Qt::AlignCenter, pm);
2921 p->restore();
2922 } else {
2923 d->drawBackground(theme);
2924 }
2925 }
2926 }
2927
2928 if (sub & SC_TitleBarMinButton && tb->titleBarFlags & Qt::WindowMinimizeButtonHint
2929 && !(tb->titleBarState & Qt::WindowMinimized)) {
2931 d->drawBackground(theme);
2932 }
2933 if (sub & SC_TitleBarMaxButton && tb->titleBarFlags & Qt::WindowMaximizeButtonHint
2934 && !(tb->titleBarState & Qt::WindowMaximized)) {
2936 d->drawBackground(theme);
2937 }
2939 && tb->titleBarFlags & Qt::WindowContextHelpButtonHint) {
2941 d->drawBackground(theme);
2942 }
2943 bool drawNormalButton = (sub & SC_TitleBarNormalButton)
2944 && (((tb->titleBarFlags & Qt::WindowMinimizeButtonHint)
2945 && (tb->titleBarState & Qt::WindowMinimized))
2946 || ((tb->titleBarFlags & Qt::WindowMaximizeButtonHint)
2947 && (tb->titleBarState & Qt::WindowMaximized)));
2948 if (drawNormalButton) {
2950 d->drawBackground(theme);
2951 }
2952 if (sub & SC_TitleBarShadeButton && tb->titleBarFlags & Qt::WindowShadeButtonHint
2953 && !(tb->titleBarState & Qt::WindowMinimized)) {
2955 d->drawBackground(theme);
2956 }
2957 if (sub & SC_TitleBarUnshadeButton && tb->titleBarFlags & Qt::WindowShadeButtonHint
2958 && tb->titleBarState & Qt::WindowMinimized) {
2960 d->drawBackground(theme);
2961 }
2962 if (sub & SC_TitleBarCloseButton && tb->titleBarFlags & Qt::WindowSystemMenuHint) {
2964 d->drawBackground(theme);
2965 }
2966 }
2967 }
2968 break;
2969
2970#if 0 && QT_CONFIG(mdiarea)
2971 case CC_MdiControls:
2972 {
2973 XPThemeData theme(option->window, p, QWindowsXPStylePrivate::WindowTheme, WP_MDICLOSEBUTTON, CBS_NORMAL);
2974 if (Q_UNLIKELY(!theme.isValid()))
2975 return;
2976
2977 if (option->subControls.testFlag(SC_MdiCloseButton)) {
2978 populateMdiButtonTheme(proxy(), option, SC_MdiCloseButton, WP_MDICLOSEBUTTON, &theme);
2979 d->drawBackground(theme, mdiButtonCorrectionFactor(theme));
2980 }
2981 if (option->subControls.testFlag(SC_MdiNormalButton)) {
2982 populateMdiButtonTheme(proxy(), option, SC_MdiNormalButton, WP_MDIRESTOREBUTTON, &theme);
2983 d->drawBackground(theme, mdiButtonCorrectionFactor(theme));
2984 }
2985 if (option->subControls.testFlag(QStyle::SC_MdiMinButton)) {
2986 populateMdiButtonTheme(proxy(), option, SC_MdiMinButton, WP_MDIMINBUTTON, &theme);
2987 d->drawBackground(theme, mdiButtonCorrectionFactor(theme));
2988 }
2989 }
2990 break;
2991#endif // QT_CONFIG(mdiarea)
2992#if 0 && QT_CONFIG(dial)
2993 case CC_Dial:
2994 if (const QStyleOptionSlider *dial = qstyleoption_cast<const QStyleOptionSlider *>(option))
2996 break;
2997#endif // QT_CONFIG(dial)
2998 default:
3000 break;
3001 }
3002}
3003
3005{
3006 if (const QStyleOptionProgressBar *pb = qstyleoption_cast<const QStyleOptionProgressBar *>(option))
3008 return Qt::Horizontal;
3009}
3010
3012{
3013 switch (pm) {
3015 return XPThemeData::themeSize(option->window, nullptr, QWindowsXPStylePrivate::ButtonTheme, BP_CHECKBOX, CBS_UNCHECKEDNORMAL).width();
3017 return XPThemeData::themeSize(option->window, nullptr, QWindowsXPStylePrivate::ButtonTheme, BP_CHECKBOX, CBS_UNCHECKEDNORMAL).height();
3019 return XPThemeData::themeSize(option->window, nullptr, QWindowsXPStylePrivate::ButtonTheme, BP_RADIOBUTTON, RBS_UNCHECKEDNORMAL).width();
3021 return XPThemeData::themeSize(option->window, nullptr, QWindowsXPStylePrivate::ButtonTheme, BP_RADIOBUTTON, RBS_UNCHECKEDNORMAL).height();
3024 ? XPThemeData::themeSize(option->window, nullptr, QWindowsXPStylePrivate::ProgressTheme, PP_CHUNK).width()
3025 : XPThemeData::themeSize(option->window, nullptr, QWindowsXPStylePrivate::ProgressTheme, PP_CHUNKVERT).height();
3027 return XPThemeData::themeSize(option->window, nullptr, QWindowsXPStylePrivate::TrackBarTheme, TKP_THUMB).height();
3029 return option->window && (option->window->type() == Qt::Tool)
3030 ? GetSystemMetrics(SM_CYSMCAPTION) + GetSystemMetrics(SM_CXSIZEFRAME)
3031 : GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CXSIZEFRAME);
3033 return XPThemeData::themeSize(option->window, nullptr, QWindowsXPStylePrivate::WindowTheme, WP_FRAMELEFT, FS_ACTIVE).width();
3035 return XPThemeData::themeSize(option->window, nullptr, QWindowsXPStylePrivate::WindowTheme, WP_SMALLFRAMERIGHT, FS_ACTIVE).width();
3036 default:
3037 break;
3038 }
3040}
3041
3044{
3047
3051
3052 res = 0;
3053 switch (pm) {
3056 res = 0;
3057 break;
3058
3060 res = 1;
3061 //res = qobject_cast<const QListView*>(widget) ? 2 : 1;
3062 break;
3063 case PM_MenuPanelWidth:
3065 res = 1;
3066 break;
3067
3069 case PM_MenuHMargin:
3070 case PM_MenuVMargin:
3071 res = 2;
3072 break;
3073#if 0
3075 if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(option)) {
3076 switch (tab->shape) {
3081 res = 1;
3082 break;
3085 res = 2;
3086 break;
3089 res = 3;
3090 break;
3091 }
3092 }
3093 break;
3094#endif
3095 case PM_SplitterWidth:
3097 break;
3098
3100 res = 160;
3101 break;
3102
3103#if 0 && QT_CONFIG(toolbar)
3106 break;
3107
3108#endif // QT_CONFIG(toolbar)
3112 break;
3113
3116 res = qstyleoption_cast<const QStyleOptionToolButton *>(option) ? 1 : 0;
3117 break;
3118
3119 default:
3121 }
3122
3123 return res;
3124}
3125
3126/*
3127 This function is used by subControlRect to check if a button
3128 should be drawn for the given subControl given a set of window flags.
3129*/
3131
3132 bool isMinimized = tb->titleBarState & Qt::WindowMinimized;
3133 bool isMaximized = tb->titleBarState & Qt::WindowMaximized;
3134 const uint flags = tb->titleBarFlags;
3135 bool retVal = false;
3136 switch (sc) {
3139 retVal = true;
3140 break;
3142 if (!isMinimized && (flags & Qt::WindowMinimizeButtonHint))
3143 retVal = true;
3144 break;
3146 if (isMinimized && (flags & Qt::WindowMinimizeButtonHint))
3147 retVal = true;
3148 else if (isMaximized && (flags & Qt::WindowMaximizeButtonHint))
3149 retVal = true;
3150 break;
3152 if (!isMaximized && (flags & Qt::WindowMaximizeButtonHint))
3153 retVal = true;
3154 break;
3156 if (!isMinimized && flags & Qt::WindowShadeButtonHint)
3157 retVal = true;
3158 break;
3160 if (isMinimized && flags & Qt::WindowShadeButtonHint)
3161 retVal = true;
3162 break;
3165 retVal = true;
3166 break;
3169 retVal = true;
3170 break;
3171 default :
3172 retVal = true;
3173 }
3174 return retVal;
3175}
3176
3181 SubControl subControl) const
3182{
3184 return QWindowsStyle::subControlRect(cc, option, subControl);
3185
3186 QRect rect;
3187
3188 switch (cc) {
3189 case CC_GroupBox:
3190 rect = visualRect(option->direction, option->rect,
3191 QWindowsStyle::subControlRect(cc, option, subControl));
3192 if (subControl == QStyle::SC_GroupBoxContents) {
3193 // This will add the margins that was added by QLayouts in QtWidgets
3194 // (default to 9 for layouts inside a QGroupBox)
3195 rect.adjust(9, 9, -9, -9);
3196 }
3197 break;
3198 case CC_TitleBar:
3199 if (const QStyleOptionTitleBar *tb = qstyleoption_cast<const QStyleOptionTitleBar *>(option)) {
3200 if (!buttonVisible(subControl, tb))
3201 return rect;
3202 const bool isToolTitle = false;
3203 const int height = tb->rect.height();
3204 const int width = tb->rect.width();
3205 const int buttonMargin = int(QStyleHelper::dpiScaled(4, option));
3207 int buttonHeight = qRound(qreal(GetSystemMetrics(SM_CYSIZE)) * factor)
3208 - buttonMargin;
3209 int buttonWidth = qRound(qreal(GetSystemMetrics(SM_CXSIZE)) * factor)
3210 - buttonMargin;
3211 const int delta = buttonWidth + 2;
3212 int controlTop = option->rect.bottom() - buttonHeight - 2;
3213 const int frameWidth = proxy()->pixelMetric(PM_MdiSubWindowFrameWidth, option);
3214 const bool sysmenuHint = (tb->titleBarFlags & Qt::WindowSystemMenuHint) != 0;
3215 const bool minimizeHint = (tb->titleBarFlags & Qt::WindowMinimizeButtonHint) != 0;
3216 const bool maximizeHint = (tb->titleBarFlags & Qt::WindowMaximizeButtonHint) != 0;
3217 const bool contextHint = (tb->titleBarFlags & Qt::WindowContextHelpButtonHint) != 0;
3218 const bool shadeHint = (tb->titleBarFlags & Qt::WindowShadeButtonHint) != 0;
3219 bool isMinimized = tb->titleBarState & Qt::WindowMinimized;
3220 bool isMaximized = tb->titleBarState & Qt::WindowMaximized;
3221 int offset = 0;
3222
3223 switch (subControl) {
3224 case SC_TitleBarLabel:
3225 rect = QRect(frameWidth, 0, width - (buttonWidth + frameWidth + 10), height);
3226 if (isToolTitle) {
3227 if (sysmenuHint) {
3228 rect.adjust(0, 0, -buttonWidth - 3, 0);
3229 }
3230 if (minimizeHint || maximizeHint)
3231 rect.adjust(0, 0, -buttonWidth - 2, 0);
3232 } else {
3233 if (sysmenuHint) {
3234 const int leftOffset = height - 8;
3235 rect.adjust(leftOffset, 0, 0, 0);
3236 }
3237 if (minimizeHint)
3238 rect.adjust(0, 0, -buttonWidth - 2, 0);
3239 if (maximizeHint)
3240 rect.adjust(0, 0, -buttonWidth - 2, 0);
3241 if (contextHint)
3242 rect.adjust(0, 0, -buttonWidth - 2, 0);
3243 if (shadeHint)
3244 rect.adjust(0, 0, -buttonWidth - 2, 0);
3245 }
3246 break;
3247
3249 if (tb->titleBarFlags & Qt::WindowContextHelpButtonHint)
3250 offset += delta;
3251 Q_FALLTHROUGH();
3253 if (!isMinimized && (tb->titleBarFlags & Qt::WindowMinimizeButtonHint))
3254 offset += delta;
3255 else if (subControl == SC_TitleBarMinButton)
3256 break;
3257 Q_FALLTHROUGH();
3259 if (isMinimized && (tb->titleBarFlags & Qt::WindowMinimizeButtonHint))
3260 offset += delta;
3261 else if (isMaximized && (tb->titleBarFlags & Qt::WindowMaximizeButtonHint))
3262 offset += delta;
3263 else if (subControl == SC_TitleBarNormalButton)
3264 break;
3265 Q_FALLTHROUGH();
3267 if (!isMaximized && (tb->titleBarFlags & Qt::WindowMaximizeButtonHint))
3268 offset += delta;
3269 else if (subControl == SC_TitleBarMaxButton)
3270 break;
3271 Q_FALLTHROUGH();
3273 if (!isMinimized && (tb->titleBarFlags & Qt::WindowShadeButtonHint))
3274 offset += delta;
3275 else if (subControl == SC_TitleBarShadeButton)
3276 break;
3277 Q_FALLTHROUGH();
3279 if (isMinimized && (tb->titleBarFlags & Qt::WindowShadeButtonHint))
3280 offset += delta;
3281 else if (subControl == SC_TitleBarUnshadeButton)
3282 break;
3283 Q_FALLTHROUGH();
3285 if (tb->titleBarFlags & Qt::WindowSystemMenuHint)
3286 offset += delta;
3287 else if (subControl == SC_TitleBarCloseButton)
3288 break;
3289
3290 rect.setRect(width - offset - controlTop + 1, controlTop,
3291 buttonWidth, buttonHeight);
3292 break;
3293
3294 case SC_TitleBarSysMenu:
3295 {
3296 const int controlTop = 6;
3297 const int controlHeight = height - controlTop - 3;
3298 const int iconExtent = proxy()->pixelMetric(PM_SmallIconSize, option);
3299 QSize iconSize = tb->icon.actualSize(QSize(iconExtent, iconExtent));
3300 if (tb->icon.isNull())
3301 iconSize = QSize(controlHeight, controlHeight);
3302 int hPad = (controlHeight - iconSize.height())/2;
3303 int vPad = (controlHeight - iconSize.width())/2;
3304 rect = QRect(frameWidth + hPad, controlTop + vPad, iconSize.width(), iconSize.height());
3305 }
3306 break;
3307 default:
3308 break;
3309 }
3310 }
3311 break;
3312
3313 case CC_ComboBox:
3314 if (const QStyleOptionComboBox *cmb = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
3315 const int x = cmb->rect.x(), y = cmb->rect.y(), wi = cmb->rect.width(), he = cmb->rect.height();
3316 const int xpos = x + wi - qRound(QStyleHelper::dpiScaled(1 + 16, option));
3317
3318 switch (subControl) {
3319 case SC_ComboBoxFrame:
3320 rect = cmb->rect;
3321 break;
3322
3323 case SC_ComboBoxArrow: {
3324 const qreal dpi = QStyleHelper::dpi(option);
3325 rect = QRect(xpos, y + qRound(QStyleHelper::dpiScaled(1, dpi)),
3327 he - qRound(QStyleHelper::dpiScaled(2, dpi)));
3328 }
3329 break;
3330
3331 case SC_ComboBoxEditField: {
3332 const qreal dpi = QStyleHelper::dpi(option);
3333 const int frame = qRound(QStyleHelper::dpiScaled(2, dpi));
3334 rect = QRect(x + frame, y + frame,
3335 wi - qRound(QStyleHelper::dpiScaled(3 + 16, dpi)),
3336 he - qRound(QStyleHelper::dpiScaled(4, dpi)));
3337 }
3338 break;
3339
3341 rect = cmb->rect;
3342 break;
3343
3344 default:
3345 break;
3346 }
3347 }
3348 break;
3349#if 0 && QT_CONFIG(mdiarea)
3350 case CC_MdiControls:
3351 {
3352 int numSubControls = 0;
3353 if (option->subControls & SC_MdiCloseButton)
3354 ++numSubControls;
3355 if (option->subControls & SC_MdiMinButton)
3356 ++numSubControls;
3357 if (option->subControls & SC_MdiNormalButton)
3358 ++numSubControls;
3359 if (numSubControls == 0)
3360 break;
3361
3362 int buttonWidth = option->rect.width() / numSubControls;
3363 int offset = 0;
3364 switch (subControl) {
3365 case SC_MdiCloseButton:
3366 // Only one sub control, no offset needed.
3367 if (numSubControls == 1)
3368 break;
3369 offset += buttonWidth;
3370 Q_FALLTHROUGH();
3371 case SC_MdiNormalButton:
3372 // No offset needed if
3373 // 1) There's only one sub control
3374 // 2) We have a close button and a normal button (offset already added in SC_MdiClose)
3375 if (numSubControls == 1 || (numSubControls == 2 && !(option->subControls & SC_MdiMinButton)))
3376 break;
3377 if (option->subControls & SC_MdiNormalButton)
3378 offset += buttonWidth;
3379 break;
3380 default:
3381 break;
3382 }
3383 rect = QRect(offset, 0, buttonWidth, option->rect.height());
3384 break;
3385 }
3386#endif // QT_CONFIG(mdiarea)
3387
3388 default:
3389 rect = visualRect(option->direction, option->rect,
3390 QWindowsStyle::subControlRect(cc, option, subControl));
3391 break;
3392 }
3393 return visualRect(option->direction, option->rect, rect);
3394}
3395
3400 const QSize &contentsSize) const
3401{
3403 return QWindowsStyle::sizeFromContents(ct, option, contentsSize);
3404
3405 QSize sz(contentsSize);
3406 switch (ct) {
3407 case CT_LineEdit:
3408 case CT_ComboBox:
3409 {
3410 if (contentsSize.isEmpty()) {
3411 // Minimum size
3412 return QSize(20, 20);
3413 }
3414 XPThemeData buttontheme(option->window, nullptr, QWindowsXPStylePrivate::ButtonTheme, BP_PUSHBUTTON, PBS_NORMAL);
3415 if (buttontheme.isValid()) {
3416 const QMarginsF borderSize = buttontheme.margins();
3417 if (!borderSize.isNull()) {
3418 const qreal margin = qreal(2);
3419 sz.rwidth() += qRound(borderSize.left() + borderSize.right() - margin);
3420 sz.rheight() += int(borderSize.bottom() + borderSize.top() - margin);
3421 }
3422 const int textMargins = 2*(proxy()->pixelMetric(PM_FocusFrameHMargin, option) + 1);
3424 + textMargins, 23), 0); //arrow button
3425 }
3426 }
3427 break;
3428 case CT_TabWidget:
3429 sz += QSize(6, 6);
3430 break;
3431 case CT_Menu:
3432 sz += QSize(1, 0);
3433 break;
3434#if 0 && QT_CONFIG(menubar)
3435 case CT_MenuBarItem:
3436 if (!sz.isEmpty())
3437 sz += QSize(windowsItemHMargin * 5 + 1, 6);
3438 break;
3439#endif
3440 case CT_MenuItem:
3441 if (const QStyleOptionMenuItem *menuitem = qstyleoption_cast<const QStyleOptionMenuItem *>(option))
3442 {
3443 if (menuitem->menuItemType != QStyleOptionMenuItem::Separator) {
3445 sz.setHeight(sz.height() - 2);
3446 return sz;
3447 }
3448 }
3450 break;
3451
3452 case CT_MdiControls: {
3454 int width = 54;
3455 if (const QStyleOptionComplex *styleOpt = qstyleoption_cast<const QStyleOptionComplex *>(option)) {
3456 width = 0;
3457 if (styleOpt->subControls & SC_MdiMinButton)
3458 width += 17 + 1;
3459 if (styleOpt->subControls & SC_MdiNormalButton)
3460 width += 17 + 1;
3461 if (styleOpt->subControls & SC_MdiCloseButton)
3462 width += 17 + 1;
3463 }
3465 }
3466 break;
3467
3468 case CT_Slider:
3469 if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
3470 QStyle::SubControls sub = slider->subControls;
3471 const int TickSpace = 5;
3472 int thick = proxy()->pixelMetric(QStyle::PM_SliderThickness, slider);
3473
3474 if (slider->tickPosition & QStyleOptionSlider::TicksAbove)
3475 thick += TickSpace;
3476 if (slider->tickPosition & QStyleOptionSlider::TicksBelow)
3477 thick += TickSpace;
3478 sz.setWidth(thick);
3479
3480 if (sub & SC_SliderGroove) {
3481 const int SliderLength = 84;
3482 sz.setHeight(SliderLength);
3483 }
3484 if (slider->orientation == Qt::Horizontal)
3485 sz.transpose();
3486 if (sub & SC_SliderHandle) {
3487 const QSize s = proxy()->subControlRect(CC_Slider, slider, SC_SliderHandle).size();
3488 sz = sz.expandedTo(s);
3489 }
3490 }
3491 break;
3492 case CT_ScrollBar :
3493 // Make sure that the scroll bar is large enough to display the thumb indicator.
3494 if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
3495 const int scrollBarHeight = proxy()->pixelMetric(QStyle::PM_ScrollBarExtent, slider);
3496 const int scrollBarSliderMin = proxy()->pixelMetric(QStyle::PM_ScrollBarSliderMin, slider);
3497 int &szw = slider->orientation == Qt::Horizontal ? sz.rwidth() : sz.rheight();
3498 int &szh = slider->orientation == Qt::Horizontal ? sz.rheight() : sz.rwidth();
3499 if (slider->subControls & SC_ScrollBarSlider) {
3500 szw = qMax(szw, scrollBarSliderMin);
3501 szh = scrollBarHeight;
3502 } else if (slider->subControls & SC_ScrollBarGroove) {
3503 szw = qMax(szw, scrollBarSliderMin + 2 * scrollBarHeight);
3504 szh = scrollBarHeight;
3505 } else if (slider->subControls & (SC_ScrollBarAddLine| SC_ScrollBarSubLine)) {
3506 // Assume that the AddLine and SubLine buttons have the same size, and just query
3507 // for the size of AddLine
3508 const int sbextent = proxy()->pixelMetric(PM_ScrollBarExtent, slider);
3509 szw = qMax(szw, sbextent);
3510 szh = scrollBarHeight;
3511 }
3512 }
3513 break;
3514 default:
3516 break;
3517 }
3518
3519 return sz;
3520}
3521
3522
3525 QStyleHintReturn *returnData) const
3526{
3527 QWindowsXPStylePrivate *d = const_cast<QWindowsXPStylePrivate*>(d_func());
3529 return QWindowsStyle::styleHint(hint, option, returnData);
3530
3531 int res = 0;
3532 switch (hint) {
3533
3535 //res = (qobject_cast<const QLabel*>(widget) != 0);
3536 res = 0;
3537 break;
3538
3540 res = 0;
3541 break;
3542
3545 res = 1;
3546 break;
3547
3549 if (option->state & QStyle::State_Enabled)
3551 else
3552 res = d->groupBoxTextColorDisabled;
3553 break;
3554
3556 res = 0xC0C0C0;
3557 break;
3558
3560 {
3561 res = 1;
3562 QStyleHintReturnMask *mask = qstyleoption_cast<QStyleHintReturnMask *>(returnData);
3563 const QStyleOptionTitleBar *titlebar = qstyleoption_cast<const QStyleOptionTitleBar *>(option);
3564 if (mask && titlebar) {
3565 // Note certain themes will not return the whole window frame but only the titlebar part when
3566 // queried This function needs to return the entire window mask, hence we will only fetch the mask for the
3567 // titlebar itself and add the remaining part of the window rect at the bottom.
3568 int tbHeight = proxy()->pixelMetric(PM_TitleBarHeight, option);
3569 QRect titleBarRect = option->rect;
3570 titleBarRect.setHeight(tbHeight);
3571 XPThemeData themeData;
3572 if (titlebar->titleBarState & Qt::WindowMinimized) {
3573 themeData = XPThemeData(option->window, nullptr,
3575 WP_MINCAPTION, CS_ACTIVE, titleBarRect);
3576 } else {
3577 themeData = XPThemeData(option->window, nullptr,
3579 WP_CAPTION, CS_ACTIVE, titleBarRect);
3580 }
3581 mask->region = d->region(themeData) +
3582 QRect(0, tbHeight, option->rect.width(), option->rect.height() - tbHeight);
3583 }
3584 }
3585 break;
3586#if 0 && QT_CONFIG(rubberband)
3587 case SH_RubberBand_Mask:
3588 if (qstyleoption_cast<const QStyleOptionRubberBand *>(option))
3589 res = 0;
3590 break;
3591#endif // QT_CONFIG(rubberband)
3592
3594 res = 1;
3595 break;
3596
3597 default:
3598 res =QWindowsStyle::styleHint(hint, option, returnData);
3599 }
3600
3601 return res;
3602}
3603
3605{
3606 QMargins margins;
3607
3608 switch (cc) {
3609 case CC_ScrollBar: {
3611 if (const auto option = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
3612 if (option->orientation == Qt::Horizontal) {
3613 margins.setTop(-1);
3614 margins.setBottom(-1);
3615 } else {
3616 margins.setLeft(-1);
3617 margins.setRight(-1);
3618 }
3619 }
3620 break; }
3621 default:
3623 break;
3624 }
3625
3626 return margins;
3627}
3628
3629
3635
3640{
3643
3644#if 0
3645 switch (standardPixmap) {
3648 if (qstyleoption_cast<const QStyleOptionDockWidget *>(option))
3649 {
3650 if (widget && widget->isWindow()) {
3651 XPThemeData theme(widget, nullptr, QWindowsXPStylePrivate::WindowTheme, WP_SMALLCLOSEBUTTON, CBS_NORMAL);
3652 if (theme.isValid()) {
3655 }
3656 }
3657 }
3658 break;
3659 default:
3660 break;
3661 }
3662#endif
3664}
3665
3670 const QStyleOption *option) const
3671{
3674 }
3675#if 0
3676 QWindowsXPStylePrivate *d = const_cast<QWindowsXPStylePrivate*>(d_func());
3677 switch (standardIcon) {
3679 if (qstyleoption_cast<const QStyleOptionDockWidget *>(option))
3680 {
3681 if (d->dockFloat.isNull()) {
3682 XPThemeData themeSize(nullptr, nullptr, QWindowsXPStylePrivate::WindowTheme,
3683 WP_SMALLCLOSEBUTTON, CBS_NORMAL);
3684 XPThemeData theme(nullptr, nullptr, QWindowsXPStylePrivate::WindowTheme,
3685 WP_MAXBUTTON, MAXBS_NORMAL);
3686 if (theme.isValid()) {
3687 const QSize size = (themeSize.size() * QWindowsStylePrivate::nativeMetricScaleFactor(option)).toSize();
3688 QPixmap pm(size);
3690 QPainter p(&pm);
3691 theme.painter = &p;
3692 theme.rect = QRect(QPoint(0, 0), size);
3693 d->drawBackground(theme);
3694 d->dockFloat.addPixmap(pm, QIcon::Normal, QIcon::Off); // Normal
3696 theme.stateId = MAXBS_PUSHED;
3697 d->drawBackground(theme);
3698 d->dockFloat.addPixmap(pm, QIcon::Normal, QIcon::On); // Pressed
3700 theme.stateId = MAXBS_HOT;
3701 d->drawBackground(theme);
3702 d->dockFloat.addPixmap(pm, QIcon::Active, QIcon::Off); // Hover
3704 theme.stateId = MAXBS_INACTIVE;
3705 d->drawBackground(theme);
3706 d->dockFloat.addPixmap(pm, QIcon::Disabled, QIcon::Off); // Disabled
3707 }
3708 }
3709 if (widget && widget->isWindow())
3710 return d->dockFloat;
3711
3712 }
3713 break;
3715 if (qstyleoption_cast<const QStyleOptionDockWidget *>(option))
3716 {
3717 if (d->dockClose.isNull()) {
3718 XPThemeData theme(nullptr, nullptr, QWindowsXPStylePrivate::WindowTheme,
3719 WP_SMALLCLOSEBUTTON, CBS_NORMAL);
3720 if (theme.isValid()) {
3722 QPixmap pm(size);
3724 QPainter p(&pm);
3725 theme.painter = &p;
3726 theme.partId = WP_CLOSEBUTTON; // ####
3727 theme.rect = QRect(QPoint(0, 0), size);
3728 d->drawBackground(theme);
3729 d->dockClose.addPixmap(pm, QIcon::Normal, QIcon::Off); // Normal
3731 theme.stateId = CBS_PUSHED;
3732 d->drawBackground(theme);
3733 d->dockClose.addPixmap(pm, QIcon::Normal, QIcon::On); // Pressed
3735 theme.stateId = CBS_HOT;
3736 d->drawBackground(theme);
3737 d->dockClose.addPixmap(pm, QIcon::Active, QIcon::Off); // Hover
3739 theme.stateId = CBS_INACTIVE;
3740 d->drawBackground(theme);
3741 d->dockClose.addPixmap(pm, QIcon::Disabled, QIcon::Off); // Disabled
3742 }
3743 }
3744 if (widget && widget->isWindow())
3745 return d->dockClose;
3746 }
3747 break;
3749 if (qstyleoption_cast<const QStyleOptionDockWidget *>(option))
3750 {
3751 if (d->dockFloat.isNull()) {
3752 XPThemeData themeSize(nullptr, nullptr, QWindowsXPStylePrivate::WindowTheme,
3753 WP_SMALLCLOSEBUTTON, CBS_NORMAL);
3754 XPThemeData theme(nullptr, nullptr, QWindowsXPStylePrivate::WindowTheme,
3755 WP_RESTOREBUTTON, RBS_NORMAL);
3756 if (theme.isValid()) {
3757 const QSize size = (themeSize.size() * QWindowsStylePrivate::nativeMetricScaleFactor(option)).toSize();
3758 QPixmap pm(size);
3760 QPainter p(&pm);
3761 theme.painter = &p;
3762 theme.rect = QRect(QPoint(0, 0), size);
3763 d->drawBackground(theme);
3764 d->dockFloat.addPixmap(pm, QIcon::Normal, QIcon::Off); // Normal
3766 theme.stateId = RBS_PUSHED;
3767 d->drawBackground(theme);
3768 d->dockFloat.addPixmap(pm, QIcon::Normal, QIcon::On); // Pressed
3770 theme.stateId = RBS_HOT;
3771 d->drawBackground(theme);
3772 d->dockFloat.addPixmap(pm, QIcon::Active, QIcon::Off); // Hover
3774 theme.stateId = RBS_INACTIVE;
3775 d->drawBackground(theme);
3776 d->dockFloat.addPixmap(pm, QIcon::Disabled, QIcon::Off); // Disabled
3777 }
3778 }
3779 if (widget && widget->isWindow())
3780 return d->dockFloat;
3781
3782 }
3783 break;
3784 default:
3785 break;
3786 }
3787#endif
3789}
3790
3799
3800#ifndef QT_NO_DEBUG_STREAM
3802{
3803 QDebugStateSaver saver(d);
3804 d.nospace();
3805 d << "XPThemeData(" << t.window << ", theme=#" << t.theme << ", " << t.htheme
3806 << ", partId=" << t.partId << ", stateId=" << t.stateId << ", rect=" << t.rect
3807 << ", mirrorHorizontally=" << t.mirrorHorizontally << ", mirrorVertically="
3808 << t.mirrorVertically << ", noBorder=" << t.noBorder << ", noContent=" << t.noContent
3809 << ", rotate=" << t.rotate << ')';
3810 return d;
3811}
3812
3814{
3815 QDebugStateSaver saver(d);
3816 d.nospace();
3817 d << "ThemeMapKey(theme=#" << k.theme
3818 << ", partId=" << k.partId << ", stateId=" << k.stateId
3819 << ", noBorder=" << k.noBorder << ", noContent=" << k.noContent << ')';
3820 return d;
3821}
3822
3824{
3825 QDebugStateSaver saver(d);
3826 d.nospace();
3827 d << "ThemeMapData(alphaType=" << td.alphaType
3828 << ", dataValid=" << td.dataValid << ", partIsTransparent=" << td.partIsTransparent
3829 << ", hasAlphaChannel=" << td.hasAlphaChannel << ", wasAlphaSwapped=" << td.wasAlphaSwapped
3830 << ", hadInvalidAlpha=" << td.hadInvalidAlpha << ')';
3831 return d;
3832}
3833#endif // QT_NO_DEBUG_STREAM
3834
3835// Debugging code ---------------------------------------------------------------------[ START ]---
3836// The code for this point on is not compiled by default, but only used as assisting
3837// debugging code when you uncomment the DEBUG_XP_STYLE define at the top of the file.
3838
3839#ifdef DEBUG_XP_STYLE
3840// The schema file expects these to be defined by the user.
3841#define TMT_ENUMDEF 8
3842#define TMT_ENUMVAL TEXT('A')
3843#define TMT_ENUM TEXT('B')
3844#define SCHEMA_STRINGS // For 2nd pass on schema file
3846#include <tmschema.h>
3848
3849// A property's value, type and name combo
3850struct PropPair {
3851 int propValue;
3852 int propType;
3853 LPCWSTR propName;
3854};
3855
3856// Operator for sorting of PropPairs
3857bool operator<(PropPair a, PropPair b) {
3858 return wcscmp(a.propName, b.propName) < 0;
3859}
3860
3861// Our list of all possible properties
3862static QList<PropPair> all_props;
3863
3864
3876void QWindowsXPStylePrivate::dumpNativeDIB(int w, int h)
3877{
3878 if (w && h) {
3879 static int pCount = 0;
3880 DWORD *bufPix = (DWORD*)bufferPixels;
3881
3882 const unsigned int bufferSize = bufferH * bufferW * 16;
3883 char *bufferDump = new char[bufferSize];
3884 char *bufferEndAdress = bufferDump + bufferSize;
3885 char *bufferPos = bufferDump;
3886
3887 memset(bufferDump, 0, sizeof(bufferDump));
3888 bufferPos += snprintf(bufferPos, bufferEndAdress - bufferPos, "const int pixelBufferW%d = %d;\n", pCount, w);
3889 bufferPos += snprintf(bufferPos, bufferEndAdress - bufferPos, "const int pixelBufferH%d = %d;\n", pCount, h);
3890 bufferPos += snprintf(bufferPos, bufferEndAdress - bufferPos, "const unsigned DWORD pixelBuffer%d[] = {", pCount);
3891 for (int iy = 0; iy < h; ++iy) {
3892 bufferPos += snprintf(bufferPos, bufferEndAdress - bufferPos, "\n ");
3893 bufPix = (DWORD*)(bufferPixels + (iy * bufferW * 4));
3894 for (int ix = 0; ix < w; ++ix) {
3895 bufferPos += snprintf(bufferPos, bufferEndAdress - bufferPos, "0x%08x, ", *bufPix);
3896 ++bufPix;
3897 }
3898 }
3899 bufferPos += snprintf(bufferPos, bufferEndAdress - bufferPos, "\n};\n\n");
3900 printf(bufferDump);
3901
3902 delete[] bufferDump;
3903 ++pCount;
3904 }
3905}
3906
3910static void showProperty(XPThemeData &themeData, const PropPair &prop)
3911{
3912 PROPERTYORIGIN origin = PO_NOTFOUND;
3913 GetThemePropertyOrigin(themeData.handle(), themeData.partId, themeData.stateId, prop.propValue, &origin);
3914 const char *originStr;
3915 switch (origin) {
3916 case PO_STATE:
3917 originStr = "State ";
3918 break;
3919 case PO_PART:
3920 originStr = "Part ";
3921 break;
3922 case PO_CLASS:
3923 originStr = "Class ";
3924 break;
3925 case PO_GLOBAL:
3926 originStr = "Globl ";
3927 break;
3928 case PO_NOTFOUND:
3929 default:
3930 originStr = "Unkwn ";
3931 break;
3932 }
3933
3934 switch (prop.propType) {
3935 case TMT_STRING:
3936 {
3937 wchar_t buffer[512];
3938 GetThemeString(themeData.handle(), themeData.partId, themeData.stateId, prop.propValue, buffer, 512);
3939 printf(" (%sString) %-20S: %S\n", originStr, prop.propName, buffer);
3940 }
3941 break;
3942 case TMT_ENUM:
3943 {
3944 int result = -1;
3945 GetThemeEnumValue(themeData.handle(), themeData.partId, themeData.stateId, prop.propValue, &result);
3946 printf(" (%sEnum) %-20S: %d\n", originStr, prop.propName, result);
3947 }
3948 break;
3949 case TMT_INT:
3950 {
3951 int result = -1;
3952 GetThemeInt(themeData.handle(), themeData.partId, themeData.stateId, prop.propValue, &result);
3953 printf(" (%sint) %-20S: %d\n", originStr, prop.propName, result);
3954 }
3955 break;
3956 case TMT_BOOL:
3957 {
3958 BOOL result = false;
3959 GetThemeBool(themeData.handle(), themeData.partId, themeData.stateId, prop.propValue, &result);
3960 printf(" (%sbool) %-20S: %d\n", originStr, prop.propName, result);
3961 }
3962 break;
3963 case TMT_COLOR:
3964 {
3965 COLORREF result = 0;
3966 GetThemeColor(themeData.handle(), themeData.partId, themeData.stateId, prop.propValue, &result);
3967 printf(" (%scolor) %-20S: 0x%08X\n", originStr, prop.propName, result);
3968 }
3969 break;
3970 case TMT_MARGINS:
3971 {
3972 MARGINS result;
3973 memset(&result, 0, sizeof(result));
3974 GetThemeMargins(themeData.handle(), 0, themeData.partId, themeData.stateId, prop.propValue, 0, &result);
3975 printf(" (%smargins) %-20S: (%d, %d, %d, %d)\n", originStr,
3976 prop.propName, result.cxLeftWidth, result.cyTopHeight, result.cxRightWidth, result.cyBottomHeight);
3977 }
3978 break;
3979 case TMT_FILENAME:
3980 {
3981 wchar_t buffer[512];
3982 GetThemeFilename(themeData.handle(), themeData.partId, themeData.stateId, prop.propValue, buffer, 512);
3983 printf(" (%sfilename)%-20S: %S\n", originStr, prop.propName, buffer);
3984 }
3985 break;
3986 case TMT_SIZE:
3987 {
3988 SIZE result1;
3989 SIZE result2;
3990 SIZE result3;
3991 memset(&result1, 0, sizeof(result1));
3992 memset(&result2, 0, sizeof(result2));
3993 memset(&result3, 0, sizeof(result3));
3994 GetThemePartSize(themeData.handle(), 0, themeData.partId, themeData.stateId, 0, TS_MIN, &result1);
3995 GetThemePartSize(themeData.handle(), 0, themeData.partId, themeData.stateId, 0, TS_TRUE, &result2);
3996 GetThemePartSize(themeData.handle(), 0, themeData.partId, themeData.stateId, 0, TS_DRAW, &result3);
3997 printf(" (%ssize) %-20S: Min (%d, %d), True(%d, %d), Draw(%d, %d)\n", originStr, prop.propName,
3998 result1.cx, result1.cy, result2.cx, result2.cy, result3.cx, result3.cy);
3999 }
4000 break;
4001 case TMT_POSITION:
4002 {
4003 POINT result;
4004 memset(&result, 0, sizeof(result));
4005 GetThemePosition(themeData.handle(), themeData.partId, themeData.stateId, prop.propValue, &result);
4006 printf(" (%sPosition)%-20S: (%d, %d)\n", originStr, prop.propName, result.x, result.y);
4007 }
4008 break;
4009 case TMT_RECT:
4010 {
4011 RECT result;
4012 memset(&result, 0, sizeof(result));
4013 GetThemeRect(themeData.handle(), themeData.partId, themeData.stateId, prop.propValue, &result);
4014 printf(" (%sRect) %-20S: (%d, %d, %d, %d)\n", originStr, prop.propName, result.left, result.top, result.right, result.bottom);
4015 }
4016 break;
4017 case TMT_FONT:
4018 {
4019 LOGFONT result;
4020 memset(&result, 0, sizeof(result));
4021 GetThemeFont(themeData.handle(), 0, themeData.partId, themeData.stateId, prop.propValue, &result);
4022 printf(" (%sFont) %-20S: %S height(%d) width(%d) weight(%d)\n", originStr, prop.propName,
4023 result.lfFaceName, result.lfHeight, result.lfWidth, result.lfWeight);
4024 }
4025 break;
4026 case TMT_INTLIST:
4027 {
4028 INTLIST result;
4029 memset(&result, 0, sizeof(result));
4030 GetThemeIntList(themeData.handle(), themeData.partId, themeData.stateId, prop.propValue, &result);
4031 printf(" (%sInt list)%-20S: { ", originStr, prop.propName);
4032 for (int i = 0; i < result.iValueCount; ++i)
4033 printf("%d ", result.iValues[i]);
4034 printf("}\n");
4035 }
4036 break;
4037 default:
4038 printf(" %s%S : Unknown property type (%d)!\n", originStr, prop.propName, prop.propType);
4039 }
4040}
4041
4048void QWindowsXPStylePrivate::showProperties(XPThemeData &themeData)
4049{
4050 if (!all_props.count()) {
4051 const TMSCHEMAINFO *infoTable = GetSchemaInfo();
4052 for (int i = 0; i < infoTable->iPropCount; ++i) {
4053 int propType = infoTable->pPropTable[i].bPrimVal;
4054 int propValue = infoTable->pPropTable[i].sEnumVal;
4055 LPCWSTR propName = infoTable->pPropTable[i].pszName;
4056
4057 switch (propType) {
4058 case TMT_ENUMDEF:
4059 case TMT_ENUMVAL:
4060 continue;
4061 default:
4062 if (propType != propValue) {
4063 PropPair prop;
4064 prop.propValue = propValue;
4065 prop.propName = propName;
4066 prop.propType = propType;
4067 all_props.append(prop);
4068 }
4069 }
4070 }
4071 std::sort(all_props.begin(), all_props.end());
4072
4073 {// List all properties
4074 printf("part properties count = %d:\n", all_props.count());
4075 printf(" Enum Property Name Description\n");
4076 printf("-----------------------------------------------------------\n");
4077 wchar_t themeName[256];
4078 pGetCurrentThemeName(themeName, 256, 0, 0, 0, 0);
4079 for (int j = 0; j < all_props.count(); ++j) {
4080 PropPair prop = all_props.at(j);
4081 wchar_t buf[500];
4082 GetThemeDocumentationProperty(themeName, prop.propName, buf, 500);
4083 printf("%3d: (%4d) %-20S %S\n", j, prop.propValue, prop.propName, buf);
4084 }
4085 }
4086
4087 {// Show Global values
4088 printf("Global Properties:\n");
4089 for (int j = 0; j < all_props.count(); ++j) {
4090 PropPair prop = all_props.at(j);
4091 PROPERTYORIGIN origin = PO_NOTFOUND;
4092 GetThemePropertyOrigin(themeData.handle(), themeData.partId, themeData.stateId, prop.propValue, &origin);
4093 if (origin == PO_GLOBAL) {
4094 showProperty(themeData, prop);
4095 }
4096 }
4097 }
4098 }
4099
4100 for (int j = 0; j < all_props.count(); ++j) {
4101 PropPair prop = all_props.at(j);
4102 PROPERTYORIGIN origin = PO_NOTFOUND;
4103 GetThemePropertyOrigin(themeData.handle(), themeData.partId, themeData.stateId, prop.propValue, &origin);
4104 if (origin != PO_NOTFOUND)
4105 {
4106 showProperty(themeData, prop);
4107 }
4108 }
4109}
4110#endif
4111// Debugging code -----------------------------------------------------------------------[ END ]---
4112
4113} //namespace QQC2
4114
bool isActive
\inmodule QtGui
Definition qbrush.h:30
\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
QColor toRgb() const noexcept
Create and returns an RGB QColor based on this color.
Definition qcolor.cpp:2035
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
static QCoreApplication * instance() noexcept
Returns a pointer to the application's QCoreApplication (or QGuiApplication/QApplication) instance.
\inmodule QtCore
\inmodule QtCore
\reentrant
Definition qfont.h:22
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
static QPlatformNativeInterface * platformNativeInterface()
static QWindowList allWindows()
Returns a list of all the windows in the application.
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
\inmodule QtCore\compares equality \compareswith equality QLineF \endcompareswith
Definition qline.h:18
\inmodule QtCore
Definition qmargins.h:270
\inmodule QtCore
Definition qmargins.h:24
constexpr void setTop(int top) noexcept
Sets the Top margin to Top.
Definition qmargins.h:122
constexpr void setBottom(int bottom) noexcept
Sets the bottom margin to bottom.
Definition qmargins.h:128
constexpr void setLeft(int left) noexcept
Sets the left margin to left.
Definition qmargins.h:119
constexpr void setRight(int right) noexcept
Sets the right margin to right.
Definition qmargins.h:125
virtual int devType() const
QRegion systemClip() const
The QPainter class performs low-level painting on widgets and other paint devices.
Definition qpainter.h:46
void setClipping(bool enable)
Enables clipping if enable is true, or disables clipping if enable is false.
QPaintDevice * device() const
Returns the paint device on which this painter is currently painting, or \nullptr if the painter is n...
QPaintEngine * paintEngine() const
Returns the paint engine that the painter is currently operating on if the painter is active; otherwi...
void restore()
Restores the current painter state (pops a saved state off the stack).
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...
QRegion clipRegion() const
Returns the currently set clip region.
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.
bool isActive() const
Returns true if begin() has been called and end() has not yet been called; otherwise returns false.
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
@ HighlightedText
Definition qpalette.h:53
@ ButtonText
Definition qpalette.h:52
@ WindowText
Definition qpalette.h:51
@ Highlight
Definition qpalette.h:53
\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.
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.
\inmodule QtCore\reentrant
Definition qpoint.h:217
\inmodule QtCore\reentrant
Definition qpoint.h:25
QMargins ninePatchMargins(ControlElement ce, const QStyleOption *opt, const QSize &imageSize) const override
QRect subElementRect(SubElement r, const QStyleOption *opt) const override
QRect subControlRect(ComplexControl cc, const QStyleOptionComplex *opt, SubControl sc) const override
\reimp
const QStyle * proxy() const
virtual QPalette standardPalette() const
Returns the style's standard palette.
virtual int pixelMetric(PixelMetric metric, const QStyleOption *option=nullptr) const =0
@ SC_TitleBarNormalButton
@ SC_TitleBarUnshadeButton
@ SC_ComboBoxListBoxPopup
@ SC_TitleBarContextHelpButton
virtual void drawItemPixmap(QPainter *painter, const QRect &rect, int alignment, const QPixmap &pixmap) const
Draws the given pixmap in the specified rectangle, according to the specified alignment,...
@ SE_DockWidgetCloseButton
@ SE_DockWidgetFloatButton
@ SE_TabWidgetTabContents
virtual void drawControl(ControlElement element, const QStyleOption *opt, QPainter *p) const =0
virtual void drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPainter *p) const =0
static int sliderPositionFromValue(int min, int max, int val, int space, bool upsideDown=false)
Converts the given logicalValue to a pixel position.
virtual QRect subControlRect(ComplexControl cc, const QStyleOptionComplex *opt, SubControl sc) const =0
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.
@ SH_GroupBox_TextLabelColor
@ SH_SpinControls_DisableOnBounds
@ SH_ItemView_DrawDelegateFrame
virtual int styleHint(StyleHint stylehint, const QStyleOption *opt=nullptr, QStyleHintReturn *returnData=nullptr) const =0
@ PE_IndicatorItemViewItemCheck
@ PE_IndicatorHeaderArrow
@ PE_IndicatorRadioButton
@ PE_IndicatorArrowLeft
Definition qquickstyle.h:99
@ PE_IndicatorToolBarHandle
@ PE_FrameStatusBarItem
Definition qquickstyle.h:84
@ PE_IndicatorButtonDropDown
@ PE_IndicatorMenuCheckMark
@ PE_IndicatorToolBarSeparator
@ PE_IndicatorProgressChunk
@ PE_IndicatorArrowDown
Definition qquickstyle.h:98
@ PE_IndicatorDockWidgetResizeHandle
virtual QIcon standardIcon(StandardPixmap standardIcon, const QStyleOption *option=nullptr) const =0
@ PM_ButtonDefaultIndicator
@ PM_SliderTickmarkOffset
@ PM_MdiSubWindowFrameWidth
@ PM_SliderSpaceAvailable
@ PM_ProgressBarChunkWidth
@ PM_ExclusiveIndicatorHeight
@ PM_MdiSubWindowMinimizedWidth
@ PM_ExclusiveIndicatorWidth
@ PM_ButtonShiftHorizontal
@ PM_SliderControlThickness
@ PM_DockWidgetFrameWidth
@ PM_DockWidgetSeparatorExtent
@ PM_DockWidgetTitleMargin
virtual void drawItemText(QPainter *painter, const QRect &rect, int flags, const QPalette &pal, bool enabled, const QString &text, QPalette::ColorRole textRole=QPalette::NoRole) const
Draws the given text in the specified rectangle using the provided painter and palette.
@ SP_TitleBarNormalButton
static qreal nativeMetricScaleFactor(const QStyleOption *option=nullptr)
The QWindowsStyle class provides a Microsoft Windows-like look and feel.
QIcon standardIcon(StandardPixmap standardIcon, const QStyleOption *option=nullptr) const override
\reimp
void drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPainter *p) const override
\reimp
void drawComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, QPainter *p) const override
\reimp
int pixelMetric(PixelMetric pm, const QStyleOption *option=nullptr) const override
\reimp
int styleHint(StyleHint hint, const QStyleOption *opt=nullptr, QStyleHintReturn *returnData=nullptr) const override
\reimp
QPixmap standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt) const override
\reimp
void drawControl(ControlElement element, const QStyleOption *opt, QPainter *p) const override
\reimp
QRect subElementRect(SubElement r, const QStyleOption *opt) const override
\reimp
QSize sizeFromContents(ContentsType ct, const QStyleOption *opt, const QSize &contentsSize) const override
\reimp
bool fixAlphaChannel(const QRect &rect)
bool drawBackground(XPThemeData &themeData, qreal correctionFactor=1)
bool drawBackgroundDirectly(HDC dc, XPThemeData &themeData, qreal aditionalDevicePixelRatio)
bool hasAlphaChannel(const QRect &rect)
static HWND winId(const QWindow *window)
QRegion region(XPThemeData &themeData)
static QRect scrollBarGripperBounds(QStyle::State flags, XPThemeData *theme)
HBITMAP buffer(int w=0, int h=0)
static QString themeName(int theme)
bool drawBackgroundThruNativeBuffer(XPThemeData &themeData, qreal aditionalDevicePixelRatio, qreal correctionFactor)
bool isTransparent(XPThemeData &themeData)
static bool useXP(bool update=false)
bool swapAlphaChannel(const QRect &rect, bool allPixels=false)
static int pixelMetricFromSystemDp(QStyle::PixelMetric pm, const QStyleOption *option=nullptr)
static HTHEME createTheme(int theme, HWND hwnd)
QPixmap standardPixmap(StandardPixmap standardIcon, const QStyleOption *option) const override
\reimp
void drawPrimitive(PrimitiveElement pe, const QStyleOption *option, QPainter *p) const override
\reimp
QRect subElementRect(SubElement r, const QStyleOption *option) const override
\reimp
QMargins ninePatchMargins(QStyle::ComplexControl cc, const QStyleOptionComplex *opt, const QSize &imageSize) const override
int styleHint(StyleHint hint, const QStyleOption *option=nullptr, QStyleHintReturn *returnData=nullptr) const override
\reimp
~QWindowsXPStyle() override
Destroys the style.
QSize sizeFromContents(ContentsType ct, const QStyleOption *option, const QSize &contentsSize) const override
\reimp
QIcon standardIcon(StandardPixmap standardIcon, const QStyleOption *option=nullptr) const override
\reimp
void drawComplexControl(ComplexControl cc, const QStyleOptionComplex *option, QPainter *p) const override
\reimp
QWindowsXPStyle()
Constructs a QWindowsStyle.
void drawControl(ControlElement element, const QStyleOption *option, QPainter *p) const override
\reimp
int pixelMetric(PixelMetric pm, const QStyleOption *option=nullptr) const override
\reimp
QPalette standardPalette() const override
\reimp
QRect subControlRect(ComplexControl cc, const QStyleOptionComplex *option, SubControl sc) const override
\reimp
QMarginsF margins(const QRect &rect, int propId=TMT_CONTENTMARGINS)
static RECT toRECT(const QRect &qr)
static QSizeF themeSize(const QWindow *w=nullptr, QPainter *p=nullptr, int themeIn=-1, int part=0, int state=0)
\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 QRectF adjusted(qreal x1, qreal y1, qreal x2, qreal y2) const noexcept
Returns a new rectangle with dx1, dy1, dx2 and dy2 added respectively to the existing coordinates of ...
Definition qrect.h:813
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 QPoint topLeft() const noexcept
Returns the position of the rectangle's top-left corner.
Definition qrect.h:221
constexpr void setSize(const QSize &s) noexcept
Sets the size of the rectangle to the given size.
Definition qrect.h:387
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 QPoint topRight() const noexcept
Returns the position of the rectangle's top-right corner.
Definition qrect.h:227
constexpr int x() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:185
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 QPoint center() const noexcept
Returns the center point of the rectangle.
Definition qrect.h:233
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 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 QSize expandedTo(const QSize &) const noexcept
Returns a size holding the maximum width and height of this size and the given otherSize.
Definition qsize.h:192
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
void transpose() noexcept
Swaps the width and height values.
Definition qsize.cpp:130
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
qsizetype indexOf(QLatin1StringView s, qsizetype from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition qstring.cpp:4517
static QString fromWCharArray(const wchar_t *string, qsizetype size=-1)
Definition qstring.h:1309
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
ButtonFeatures features
@ 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
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)
QRect rect
the internal geometry of the widget excluding any window frame
Definition qwidget.h:116
bool isWindow() const
Returns true if the widget is an independent window, otherwise returns false.
Definition qwidget.h:811
\inmodule QtGui
Definition qwindow.h:63
QOpenGLWidget * widget
[1]
QPixmap p2
QPixmap p1
[0]
QPushButton * button
[2]
opt iconSize
rect
[4]
QPixmap pix
uint alignment
QStyleOptionButton opt
QRect textRect
const QStyleOptionButton * btn
[3]
void qErrnoWarning(const char *msg,...)
qreal dpi(const QStyleOption *option)
qreal dpiScaled(qreal value, qreal dpi)
void drawDial(const QStyleOptionSlider *option, QPainter *painter)
static void populateTitleBarButtonTheme(const QStyle *proxy, const QStyleOptionComplex *option, QStyle::SubControl subControl, bool isTitleBarActive, int part, XPThemeData *theme)
static HRGN qt_hrgn_from_qregion(const QRegion &region)
static const int windowsArrowHMargin
static const int windowsItemVMargin
static HWND createTreeViewHelperWindow()
static const int windowsRightBorder
static const wchar_t * themeNames[QWindowsXPStylePrivate::NThemes]
static QRegion scaleRegion(const QRegion &region, qreal factor)
static void qt_add_rect(HRGN &winRegion, QRect r)
static Qt::Orientation progressBarOrientation(const QStyleOption *option=nullptr)
QDebug operator<<(QDebug debug, const QStyleOption::OptionType &optionType)
static const int windowsItemFrame
static bool buttonVisible(const QStyle::SubControl sc, const QStyleOptionTitleBar *tb)
static QRectF scaleRect(const QRectF &r, qreal factor)
static const int windowsItemHMargin
Combined button and popup list for selecting options.
@ WindowMinimized
Definition qnamespace.h:253
@ WindowMaximized
Definition qnamespace.h:254
@ BottomLeftCorner
@ TopRightCorner
@ TopLeftCorner
@ BottomRightCorner
@ AlignBottom
Definition qnamespace.h:154
@ AlignVCenter
Definition qnamespace.h:155
@ AlignCenter
Definition qnamespace.h:163
@ AlignLeft
Definition qnamespace.h:144
@ SmoothTransformation
@ 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
@ DirectConnection
@ 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
@ Tool
Definition qnamespace.h:212
@ WindowSystemMenuHint
Definition qnamespace.h:227
@ ElideRight
Definition qnamespace.h:190
Definition brush.cpp:5
#define Q_BASIC_ATOMIC_INITIALIZER(a)
#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)
bool qFuzzyCompare(qfloat16 p1, qfloat16 p2) noexcept
Definition qfloat16.h:333
int qRound(qfloat16 d) noexcept
Definition qfloat16.h:327
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
#define SIZE(large, small, mini)
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
#define Q_RETURN_ARG(Type, data)
Definition qobjectdefs.h:64
#define Q_ARG(Type, data)
Definition qobjectdefs.h:63
static QString themeName()
GLboolean GLboolean GLboolean b
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]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLboolean r
[2]
GLuint GLuint end
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLint GLenum GLsizei GLsizei GLsizei GLint border
GLenum GLuint buffer
GLint GLsizei width
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 GLenum GLsizei GLsizei GLsizei GLint GLsizei imageSize
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
GLuint64EXT * result
[6]
GLfloat GLfloat p
[1]
GLuint GLenum option
GLenum GLsizei len
GLfloat GLfloat GLfloat alpha
Definition qopenglext.h:418
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
static bool operator<(const QSettingsIniKey &k1, const QSettingsIniKey &k2)
#define qPrintable(string)
Definition qstring.h:1531
#define QStringLiteral(str)
static QT_BEGIN_NAMESPACE QVariant hint(QPlatformIntegration::StyleHint h)
#define QT_BEGIN_INCLUDE_NAMESPACE
#define QT_END_INCLUDE_NAMESPACE
unsigned int uint
Definition qtypes.h:34
double qreal
Definition qtypes.h:187
long HRESULT
#define RBS_INACTIVE
#define TMT_TEXTSHADOWCOLOR
#define MAXBS_INACTIVE
#define CBS_INACTIVE
#define TST_NONE
static bool isFullyOpaque(const QWindowsThemeData &themeData)
#define TMT_CONTENTMARGINS
#define TMT_SIZINGMARGINS
@ SimpleTransform
@ HighDpiScalingTransform
@ ComplexTransform
QWidget * panel
Definition settings.cpp:7
QRandomGenerator64 rd
[10]
ba fill(true)
rect deviceTransform(view->viewportTransform()).map(QPointF(0
widget render & pixmap
QPainter painter(this)
[7]
aWidget window() -> setWindowTitle("New Window Title")
[2]
QFrame frame
[0]
QNetworkProxy proxy
[0]
\inmodule QtCore \reentrant
Definition qchar.h:18
static bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType, QGenericReturnArgument ret, QGenericArgument val0=QGenericArgument(nullptr), QGenericArgument val1=QGenericArgument(), QGenericArgument val2=QGenericArgument(), QGenericArgument val3=QGenericArgument(), QGenericArgument val4=QGenericArgument(), QGenericArgument val5=QGenericArgument(), QGenericArgument val6=QGenericArgument(), QGenericArgument val7=QGenericArgument(), QGenericArgument val8=QGenericArgument(), QGenericArgument val9=QGenericArgument())
\threadsafe This is an overloaded member function, provided for convenience. It differs from the abov...