1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtGui module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qwindowsvistastyle.h"
43 #include "qwindowsvistastyle_p.h"
46 #include <private/qstylehelper_p.h>
47 #include <private/qsystemlibrary_p.h>
48 #include <private/qapplication_p.h>
49 #include <qplatformnativeinterface_qpa.h>
51 #if !defined(QT_NO_STYLE_WINDOWSVISTA) || defined(QT_PLUGIN)
55 static const int windowsItemFrame = 2; // menu item frame width
56 static const int windowsItemHMargin = 3; // menu item hor text margin
57 static const int windowsItemVMargin = 4; // menu item ver text margin
58 static const int windowsArrowHMargin = 6; // arrow horizontal margin
59 static const int windowsRightBorder = 15; // right border on windows
61 #ifndef TMT_CONTENTMARGINS
62 # define TMT_CONTENTMARGINS 3602
64 #ifndef TMT_SIZINGMARGINS
65 # define TMT_SIZINGMARGINS 3601
68 # define LISS_NORMAL 1
70 # define LISS_SELECTED 3
71 # define LISS_DISABLED 4
72 # define LISS_SELECTEDNOTFOCUS 5
73 # define LISS_HOTSELECTED 6
75 #ifndef BP_COMMANDLINK
76 # define BP_COMMANDLINK 6
77 # define BP_COMMANDLINKGLYPH 7
78 # define CMDLGS_NORMAL 1
80 # define CMDLGS_PRESSED 3
81 # define CMDLGS_DISABLED 4
84 // Runtime resolved theme engine function calls
87 typedef HRESULT (WINAPI *PtrGetThemePartSize)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, OPTIONAL RECT *prc, enum THEMESIZE eSize, OUT SIZE *psz);
88 typedef HTHEME (WINAPI *PtrOpenThemeData)(HWND hwnd, LPCWSTR pszClassList);
89 typedef HTHEME (WINAPI *PtrOpenThemeData)(HWND hwnd, LPCWSTR pszClassList);
90 typedef HRESULT (WINAPI *PtrCloseThemeData)(HTHEME hTheme);
91 typedef HRESULT (WINAPI *PtrDrawThemeBackground)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, OPTIONAL const RECT *pClipRect);
92 typedef HRESULT (WINAPI *PtrDrawThemeBackgroundEx)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, OPTIONAL const DTBGOPTS *pOptions);
93 typedef HRESULT (WINAPI *PtrGetCurrentThemeName)(OUT LPWSTR pszThemeFileName, int cchMaxNameChars, OUT OPTIONAL LPWSTR pszColorBuff, int cchMaxColorChars, OUT OPTIONAL LPWSTR pszSizeBuff, int cchMaxSizeChars);
94 typedef HRESULT (WINAPI *PtrGetThemeBool)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT BOOL *pfVal);
95 typedef HRESULT (WINAPI *PtrGetThemeColor)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT COLORREF *pColor);
96 typedef HRESULT (WINAPI *PtrGetThemeEnumValue)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT int *piVal);
97 typedef HRESULT (WINAPI *PtrGetThemeFilename)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT LPWSTR pszThemeFileName, int cchMaxBuffChars);
98 typedef HRESULT (WINAPI *PtrGetThemeFont)(HTHEME hTheme, OPTIONAL HDC hdc, int iPartId, int iStateId, int iPropId, OUT LOGFONT *pFont);
99 typedef HRESULT (WINAPI *PtrGetThemeInt)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT int *piVal);
100 typedef HRESULT (WINAPI *PtrGetThemeIntList)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT INTLIST *pIntList);
101 typedef HRESULT (WINAPI *PtrGetThemeMargins)(HTHEME hTheme, OPTIONAL HDC hdc, int iPartId, int iStateId, int iPropId, OPTIONAL RECT *prc, OUT MARGINS *pMargins);
102 typedef HRESULT (WINAPI *PtrGetThemeMetric)(HTHEME hTheme, OPTIONAL HDC hdc, int iPartId, int iStateId, int iPropId, OUT int *piVal);
103 typedef HRESULT (WINAPI *PtrGetThemePartSize)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, OPTIONAL RECT *prc, enum THEMESIZE eSize, OUT SIZE *psz);
104 typedef HRESULT (WINAPI *PtrGetThemePosition)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT POINT *pPoint);
105 typedef HRESULT (WINAPI *PtrGetThemeRect)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT RECT *pRect);
106 typedef HRESULT (WINAPI *PtrGetThemeString)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT LPWSTR pszBuff, int cchMaxBuffChars);
107 typedef HRESULT (WINAPI *PtrGetThemeTransitionDuration)(HTHEME hTheme, int iPartId, int iStateFromId, int iStateToId, int iPropId, int *pDuration);
108 typedef HRESULT (WINAPI *PtrIsThemePartDefined)(HTHEME hTheme, int iPartId, int iStateId);
109 typedef HRESULT (WINAPI *PtrSetWindowTheme)(HWND hwnd, LPCWSTR pszSubAppName, LPCWSTR pszSubIdList);
110 typedef HRESULT (WINAPI *PtrGetThemePropertyOrigin)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT enum PROPERTYORIGIN *pOrigin);
112 static PtrIsThemePartDefined pIsThemePartDefined = 0;
113 static PtrOpenThemeData pOpenThemeData = 0;
114 static PtrCloseThemeData pCloseThemeData = 0;
115 static PtrDrawThemeBackground pDrawThemeBackground = 0;
116 static PtrDrawThemeBackgroundEx pDrawThemeBackgroundEx = 0;
117 static PtrGetCurrentThemeName pGetCurrentThemeName = 0;
118 static PtrGetThemeBool pGetThemeBool = 0;
119 static PtrGetThemeColor pGetThemeColor = 0;
120 static PtrGetThemeEnumValue pGetThemeEnumValue = 0;
121 static PtrGetThemeFilename pGetThemeFilename = 0;
122 static PtrGetThemeFont pGetThemeFont = 0;
123 static PtrGetThemeInt pGetThemeInt = 0;
124 static PtrGetThemeIntList pGetThemeIntList = 0;
125 static PtrGetThemeMargins pGetThemeMargins = 0;
126 static PtrGetThemeMetric pGetThemeMetric = 0;
127 static PtrGetThemePartSize pGetThemePartSize = 0;
128 static PtrGetThemePosition pGetThemePosition = 0;
129 static PtrGetThemeRect pGetThemeRect = 0;
130 static PtrGetThemeString pGetThemeString = 0;
131 static PtrGetThemeTransitionDuration pGetThemeTransitionDuration= 0;
132 static PtrSetWindowTheme pSetWindowTheme = 0;
133 static PtrGetThemePropertyOrigin pGetThemePropertyOrigin = 0;
136 Checks if we should use Vista style , or if we should
137 fall back to Windows style.
139 bool QWindowsVistaStylePrivate::useVista()
141 return (QWindowsVistaStylePrivate::useXP() &&
142 (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA &&
143 (QSysInfo::WindowsVersion & QSysInfo::WV_NT_based)));
147 \class QWindowsVistaStyle
148 \brief The QWindowsVistaStyle class provides a look and feel suitable for applications on Microsoft Windows Vista.
153 \warning This style is only available on the Windows Vista platform
154 because it makes use of Windows Vista's style engine.
156 \sa QMacStyle, QWindowsXPStyle, QPlastiqueStyle, QCleanlooksStyle, QMotifStyle
160 Constructs a QWindowsVistaStyle object.
162 QWindowsVistaStyle::QWindowsVistaStyle()
163 : QWindowsXPStyle(*new QWindowsVistaStylePrivate)
167 //convert Qt state flags to uxtheme button states
168 static int buttonStateId(int flags, int partId)
171 if (partId == BP_RADIOBUTTON || partId == BP_CHECKBOX) {
172 if (!(flags & QStyle::State_Enabled))
173 stateId = RBS_UNCHECKEDDISABLED;
174 else if (flags & QStyle::State_Sunken)
175 stateId = RBS_UNCHECKEDPRESSED;
176 else if (flags & QStyle::State_MouseOver)
177 stateId = RBS_UNCHECKEDHOT;
179 stateId = RBS_UNCHECKEDNORMAL;
181 if (flags & QStyle::State_On)
182 stateId += RBS_CHECKEDNORMAL-1;
184 } else if (partId == BP_PUSHBUTTON) {
185 if (!(flags & QStyle::State_Enabled))
186 stateId = PBS_DISABLED;
187 else if (flags & (QStyle::State_Sunken | QStyle::State_On))
188 stateId = PBS_PRESSED;
189 else if (flags & QStyle::State_MouseOver)
192 stateId = PBS_NORMAL;
199 void QWindowsVistaAnimation::paint(QPainter *painter, const QStyleOption *option)
207 Helperfunction to paint the current transition state between two
210 The result is a blended image consisting of ((alpha)*_primaryImage)
211 + ((1-alpha)*_secondaryImage)
214 void QWindowsVistaAnimation::drawBlendedImage(QPainter *painter, QRect rect, float alpha) {
215 if (_secondaryImage.isNull() || _primaryImage.isNull())
218 if (_tempImage.isNull())
219 _tempImage = _secondaryImage;
221 const int a = qRound(alpha*256);
222 const int ia = 256 - a;
223 const int sw = _primaryImage.width();
224 const int sh = _primaryImage.height();
225 const int bpl = _primaryImage.bytesPerLine();
226 switch(_primaryImage.depth()) {
229 uchar *mixed_data = _tempImage.bits();
230 const uchar *back_data = _primaryImage.bits();
231 const uchar *front_data = _secondaryImage.bits();
232 for (int sy = 0; sy < sh; sy++) {
233 quint32* mixed = (quint32*)mixed_data;
234 const quint32* back = (const quint32*)back_data;
235 const quint32* front = (const quint32*)front_data;
236 for (int sx = 0; sx < sw; sx++) {
237 quint32 bp = back[sx];
238 quint32 fp = front[sx];
239 mixed[sx] = qRgba ((qRed(bp)*ia + qRed(fp)*a)>>8,
240 (qGreen(bp)*ia + qGreen(fp)*a)>>8,
241 (qBlue(bp)*ia + qBlue(fp)*a)>>8,
242 (qAlpha(bp)*ia + qAlpha(fp)*a)>>8);
252 painter->drawImage(rect, _tempImage);
256 Paints a transition state. The result will be a mix between the
257 initial and final state of the transition, depending on the time
258 difference between _startTime and current time.
260 void QWindowsVistaTransition::paint(QPainter *painter, const QStyleOption *option)
264 QTime current = QTime::currentTime();
266 if (_startTime > current)
267 _startTime = current;
269 int timeDiff = _startTime.msecsTo(current);
270 alpha = timeDiff/(float)_duration;
271 if (timeDiff > _duration) {
279 drawBlendedImage(painter, option->rect, alpha);
283 Paints a pulse. The result will be a mix between the primary and
284 secondary pulse images depending on the time difference between
285 _startTime and current time.
287 void QWindowsVistaPulse::paint(QPainter *painter, const QStyleOption *option)
291 QTime current = QTime::currentTime();
293 if (_startTime > current)
294 _startTime = current;
296 int timeDiff = _startTime.msecsTo(current) % _duration*2;
297 if (timeDiff > _duration)
298 timeDiff = _duration*2 - timeDiff;
299 alpha = timeDiff/(float)_duration;
303 drawBlendedImage(painter, option->rect, alpha);
310 Animations are used for some state transitions on specific widgets.
312 Only one running animation can exist for a widget at any specific
313 time. Animations can be added through
314 QWindowsVistaStylePrivate::startAnimation(Animation *) and any
315 existing animation on a widget can be retrieved with
316 QWindowsVistaStylePrivate::widgetAnimation(Widget *).
318 Once an animation has been started,
319 QWindowsVistaStylePrivate::timerEvent(QTimerEvent *) will
320 continuously call update() on the widget until it is stopped,
321 meaning that drawPrimitive will be called many times until the
322 transition has completed. During this time, the result will be
323 retrieved by the Animation::paint(...) function and not by the style
326 To determine if a transition should occur, the style needs to know
327 the previous state of the widget as well as the current one. This is
328 solved by updating dynamic properties on the widget every time the
331 Transitions interrupting existing transitions should always be
332 smooth, so whenever a hover-transition is started on a pulsating
333 button, it uses the current frame of the pulse-animation as the
334 starting image for the hover transition.
337 void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOption *option,
338 QPainter *painter, const QWidget *widget) const
340 QWindowsVistaStylePrivate *d = const_cast<QWindowsVistaStylePrivate*>(d_func());
342 int state = option->state;
343 if (!QWindowsVistaStylePrivate::useVista()) {
344 QWindowsStyle::drawPrimitive(element, option, painter, widget);
351 if (widget && d->transitionsEnabled())
353 /* all widgets that supports state transitions : */
355 #ifndef QT_NO_LINEEDIT
356 (qobject_cast<const QLineEdit*>(widget) && element == PE_FrameLineEdit) ||
357 #endif // QT_NO_LINEEDIT
358 (qobject_cast<const QRadioButton*>(widget)&& element == PE_IndicatorRadioButton) ||
359 (qobject_cast<const QCheckBox*>(widget) && element == PE_IndicatorCheckBox) ||
360 (qobject_cast<const QGroupBox *>(widget)&& element == PE_IndicatorCheckBox) ||
361 (qobject_cast<const QToolButton*>(widget) && element == PE_PanelButtonBevel)
364 // Retrieve and update the dynamic properties tracking
365 // the previous state of the widget:
366 QWidget *w = const_cast<QWidget *> (widget);
367 int oldState = w->property("_q_stylestate").toInt();
368 oldRect = w->property("_q_stylerect").toRect();
370 w->setProperty("_q_stylestate", (int)option->state);
371 w->setProperty("_q_stylerect", w->rect());
373 bool doTransition = oldState &&
374 ((state & State_Sunken) != (oldState & State_Sunken) ||
375 (state & State_On) != (oldState & State_On) ||
376 (state & State_MouseOver) != (oldState & State_MouseOver));
378 if (oldRect != newRect ||
379 (state & State_Enabled) != (oldState & State_Enabled) ||
380 (state & State_Active) != (oldState & State_Active))
381 d->stopAnimation(widget);
383 #ifndef QT_NO_LINEEDIT
384 if (const QLineEdit *edit = qobject_cast<const QLineEdit *>(widget))
385 if (edit->isReadOnly() && element == PE_FrameLineEdit) // Do not animate read only line edits
386 doTransition = false;
387 #endif // QT_NO_LINEEDIT
391 // We create separate images for the initial and final transition states and store them in the
392 // Transition object.
393 QImage startImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
394 QImage endImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
395 QStyleOption opt = *option;
397 opt.rect.setRect(0, 0, option->rect.width(), option->rect.height());
398 opt.state = (QStyle::State)oldState;
400 QPainter startPainter(&startImage);
402 QWindowsVistaAnimation *anim = d->widgetAnimation(widget);
403 QWindowsVistaTransition *t = new QWindowsVistaTransition;
406 // If we have a running animation on the widget already, we will use that to paint the initial
407 // state of the new transition, this ensures a smooth transition from a current animation such as a
408 // pulsating default button into the intended target state.
411 proxy()->drawPrimitive(element, &opt, &startPainter, 0); // Note that the widget pointer is intentionally 0
412 else // this ensures that we do not recurse in the animation logic above
413 anim->paint(&startPainter, &opt);
415 d->startAnimation(t);
416 t->setStartImage(startImage);
418 // The end state of the transition is simply the result we would have painted
419 // if the style was not animated.
421 QPainter endPainter(&endImage);
423 QStyleOption opt2 = opt;
424 opt2.state = option->state;
425 proxy()->drawPrimitive(element, &opt2, &endPainter, 0); // Note that the widget pointer is intentionally 0
426 // this ensures that we do not recurse in the animation logic above
427 t->setEndImage(endImage);
435 //translate state flags to UXTHEME states :
436 if (element == PE_FrameLineEdit) {
437 theme = pOpenThemeData(0, L"Edit");
438 partId = EP_EDITBORDER_NOSCROLL;
440 if (oldState & State_MouseOver)
442 else if (oldState & State_HasFocus)
443 fromState = ETS_FOCUSED;
445 fromState = ETS_NORMAL;
447 if (state & State_MouseOver)
449 else if (state & State_HasFocus)
450 toState = ETS_FOCUSED;
452 toState = ETS_NORMAL;
455 theme = pOpenThemeData(0, L"Button");
456 if (element == PE_IndicatorRadioButton)
457 partId = BP_RADIOBUTTON;
458 else if (element == PE_IndicatorCheckBox)
459 partId = BP_CHECKBOX;
461 partId = BP_PUSHBUTTON;
463 fromState = buttonStateId(oldState, partId);
464 toState = buttonStateId(option->state, partId);
467 // Retrieve the transition time between the states from the system.
468 if (theme && pGetThemeTransitionDuration(theme, partId, fromState, toState,
469 TMT_TRANSITIONDURATIONS, &duration) == S_OK)
471 t->setDuration(duration);
473 t->setStartTime(QTime::currentTime());
476 } // End of animation part
479 QRect rect = option->rect;
482 case PE_IndicatorHeaderArrow:
483 if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) {
484 int stateId = HSAS_SORTEDDOWN;
485 if (header->sortIndicator & QStyleOptionHeader::SortDown)
486 stateId = HSAS_SORTEDUP; //note that the uxtheme sort down indicator is the inverse of ours
487 XPThemeData theme(widget, painter,
488 QWindowsXPStylePrivate::HeaderTheme,
489 HP_HEADERSORTARROW, stateId, option->rect);
490 d->drawBackground(theme);
494 case PE_IndicatorBranch:
496 XPThemeData theme(0, painter, QWindowsXPStylePrivate::TreeViewTheme);
497 static int decoration_size = 0;
498 if (d->initTreeViewTheming() && theme.isValid() && !decoration_size) {
500 pGetThemePartSize(theme.handle(), 0, TVP_HOTGLYPH, GLPS_OPENED, 0, TS_TRUE, &size);
501 decoration_size = qMax(size.cx, size.cy);
503 int mid_h = option->rect.x() + option->rect.width() / 2;
504 int mid_v = option->rect.y() + option->rect.height() / 2;
509 if (option->state & State_Children) {
510 int delta = decoration_size / 2;
511 theme.rect = QRect(bef_h - delta, bef_v - delta, decoration_size, decoration_size);
512 theme.partId = option->state & State_MouseOver ? TVP_HOTGLYPH : TVP_GLYPH;
513 theme.stateId = option->state & QStyle::State_Open ? GLPS_OPENED : GLPS_CLOSED;
514 if (option->direction == Qt::RightToLeft)
515 theme.mirrorHorizontally = true;
516 d->drawBackground(theme);
523 QBrush brush(option->palette.dark().color(), Qt::Dense4Pattern);
524 if (option->state & State_Item) {
525 if (option->direction == Qt::RightToLeft)
526 painter->fillRect(option->rect.left(), mid_v, bef_h - option->rect.left(), 1, brush);
528 painter->fillRect(aft_h, mid_v, option->rect.right() - aft_h + 1, 1, brush);
530 if (option->state & State_Sibling && option->rect.bottom() > aft_v)
531 painter->fillRect(mid_h, aft_v, 1, option->rect.bottom() - aft_v + 1, brush);
532 if (option->state & (State_Open | State_Children | State_Item | State_Sibling) && (bef_v > option->rect.y()))
533 painter->fillRect(mid_h, option->rect.y(), 1, bef_v - option->rect.y(), brush);
538 case PE_PanelButtonBevel:
539 case PE_IndicatorCheckBox:
540 case PE_IndicatorRadioButton:
542 if (QWindowsVistaAnimation *a = d->widgetAnimation(widget)) {
543 a->paint(painter, option);
545 QWindowsXPStyle::drawPrimitive(element, option, painter, widget);
552 int stateId = option->state & State_Active ? MB_ACTIVE : MB_INACTIVE;
553 XPThemeData theme(widget, painter,
554 QWindowsXPStylePrivate::MenuTheme,
555 MENU_POPUPBORDERS, stateId, option->rect);
556 d->drawBackground(theme);
560 #ifndef QT_NO_TEXTEDIT
561 if (const QTextEdit *edit = qobject_cast<const QTextEdit*>(widget)) {
563 int stateId = ETS_NORMAL;
564 if (!(state & State_Enabled))
565 stateId = ETS_DISABLED;
566 else if (edit->isReadOnly())
567 stateId = ETS_READONLY;
568 else if (state & State_HasFocus)
569 stateId = ETS_SELECTED;
570 XPThemeData theme(widget, painter,
571 QWindowsXPStylePrivate::EditTheme,
572 EP_EDITBORDER_HVSCROLL, stateId, option->rect);
573 uint resolve_mask = option->palette.resolve();
574 if (resolve_mask & (1 << QPalette::Base)) {
575 // Since EP_EDITBORDER_HVSCROLL does not us borderfill, theme.noContent cannot be used for clipping
577 pGetThemeInt(theme.handle(), theme.partId, theme.stateId, TMT_BORDERSIZE, &borderSize);
578 QRegion clipRegion = option->rect;
579 QRegion content = option->rect.adjusted(borderSize, borderSize, -borderSize, -borderSize);
580 clipRegion ^= content;
581 painter->setClipRegion(clipRegion);
583 d->drawBackground(theme);
586 #endif // QT_NO_TEXTEDIT
587 QWindowsXPStyle::drawPrimitive(element, option, painter, widget);
590 case PE_PanelLineEdit:
591 if (const QStyleOptionFrame *panel = qstyleoption_cast<const QStyleOptionFrame *>(option)) {
593 bool usePalette = false;
594 bool isEnabled = option->state & State_Enabled;
595 uint resolve_mask = panel->palette.resolve();
597 // Since spin box includes a line edit we need to resolve the palette mask also from
598 // the parent, as while the color is always correct on the palette supplied by panel,
599 // the mask can still be empty. If either mask specifies custom base color, use that.
600 #ifndef QT_NO_SPINBOX
601 if (QAbstractSpinBox *spinbox = qobject_cast<QAbstractSpinBox*>(widget->parentWidget()))
602 resolve_mask |= spinbox->palette().resolve();
603 #endif // QT_NO_SPINBOX
605 if (resolve_mask & (1 << QPalette::Base)) {
606 // Base color is set for this widget, so use it
607 bg = panel->palette.brush(QPalette::Base);
611 painter->fillRect(panel->rect, bg);
613 int partId = EP_BACKGROUND;
614 int stateId = EBS_NORMAL;
616 stateId = EBS_DISABLED;
617 else if (state & State_ReadOnly)
618 stateId = EBS_READONLY;
619 else if (state & State_MouseOver)
622 XPThemeData theme(0, painter, QWindowsXPStylePrivate::EditTheme,
623 partId, stateId, rect);
624 if (!theme.isValid()) {
625 QWindowsStyle::drawPrimitive(element, option, painter, widget);
629 pGetThemeEnumValue( theme.handle(),
634 if( bgType == BT_IMAGEFILE ) {
635 d->drawBackground(theme);
637 QBrush fillColor = option->palette.brush(QPalette::Base);
639 PROPERTYORIGIN origin = PO_NOTFOUND;
640 pGetThemePropertyOrigin(theme.handle(), theme.partId, theme.stateId, TMT_FILLCOLOR, &origin);
641 // Use only if the fill property comes from our part
642 if ((origin == PO_PART || origin == PO_STATE)) {
644 pGetThemeColor(theme.handle(), partId, stateId, TMT_FILLCOLOR, &bgRef);
645 fillColor = QBrush(qRgb(GetRValue(bgRef), GetGValue(bgRef), GetBValue(bgRef)));
648 painter->fillRect(option->rect, fillColor);
651 if (panel->lineWidth > 0)
652 proxy()->drawPrimitive(PE_FrameLineEdit, panel, painter, widget);
657 case PE_FrameLineEdit:
658 if (QWindowsVistaAnimation *anim = d->widgetAnimation(widget)) {
659 anim->paint(painter, option);
661 QPainter *p = painter;
662 QWidget *parentWidget = 0;
664 parentWidget = widget->parentWidget();
666 parentWidget = parentWidget->parentWidget();
668 if (widget && widget->inherits("QLineEdit")
669 && parentWidget && parentWidget->inherits("QAbstractItemView")) {
670 // we try to check if this lineedit is a delegate on a QAbstractItemView-derived class.
671 QPen oldPen = p->pen();
672 // Inner white border
673 p->setPen(QPen(option->palette.base().color(), 1));
674 p->drawRect(option->rect.adjusted(1, 1, -2, -2));
676 p->setPen(QPen(option->palette.shadow().color(), 1));
677 p->drawRect(option->rect.adjusted(0, 0, -1, -1));
681 int stateId = ETS_NORMAL;
682 if (!(state & State_Enabled))
683 stateId = ETS_DISABLED;
684 else if (state & State_ReadOnly)
685 stateId = ETS_READONLY;
686 else if (state & State_MouseOver)
688 else if (state & State_HasFocus)
689 stateId = ETS_SELECTED;
690 XPThemeData theme(widget, painter,
691 QWindowsXPStylePrivate::EditTheme,
692 EP_EDITBORDER_NOSCROLL, stateId, option->rect);
694 QRegion clipRegion = option->rect;
695 clipRegion -= option->rect.adjusted(2, 2, -2, -2);
696 painter->setClipRegion(clipRegion);
697 d->drawBackground(theme);
703 case PE_IndicatorToolBarHandle:
707 if (option->state & State_Horizontal) {
708 theme = XPThemeData(widget, painter,
709 QWindowsXPStylePrivate::RebarTheme,
710 RP_GRIPPER, ETS_NORMAL, option->rect.adjusted(0, 1, -2, -2));
711 rect = option->rect.adjusted(0, 1, 0, -2);
714 theme = XPThemeData(widget, painter, QWindowsXPStylePrivate::RebarTheme,
715 RP_GRIPPERVERT, ETS_NORMAL, option->rect.adjusted(0, 1, -2, -2));
716 rect = option->rect.adjusted(1, 0, -1, 0);
720 d->drawBackground(theme);
724 case PE_IndicatorToolBarSeparator:
726 QPen pen = painter->pen();
728 painter->setPen(option->palette.background().color().darker(114));
729 if (option->state & State_Horizontal) {
730 int x1 = option->rect.center().x();
731 painter->drawLine(QPoint(x1, option->rect.top() + margin), QPoint(x1, option->rect.bottom() - margin));
733 int y1 = option->rect.center().y();
734 painter->drawLine(QPoint(option->rect.left() + margin, y1), QPoint(option->rect.right() - margin, y1));
736 painter->setPen(pen);
740 case PE_PanelTipLabel: {
741 XPThemeData theme(widget, painter,
742 QWindowsXPStylePrivate::ToolTipTheme,
743 TTP_STANDARD, TTSS_NORMAL, option->rect);
744 d->drawBackground(theme);
748 case PE_PanelItemViewItem:
750 const QStyleOptionViewItemV4 *vopt;
751 const QAbstractItemView *view = qobject_cast<const QAbstractItemView *>(widget);
752 bool newStyle = true;
754 if (qobject_cast<const QTableView*>(widget))
757 if (newStyle && view && (vopt = qstyleoption_cast<const QStyleOptionViewItemV4 *>(option))) {
758 bool selected = vopt->state & QStyle::State_Selected;
759 bool hover = vopt->state & QStyle::State_MouseOver;
760 bool active = vopt->state & QStyle::State_Active;
762 if (vopt->features & QStyleOptionViewItemV2::Alternate)
763 painter->fillRect(vopt->rect, vopt->palette.alternateBase());
765 QPalette::ColorGroup cg = vopt->state & QStyle::State_Enabled
766 ? QPalette::Normal : QPalette::Disabled;
767 if (cg == QPalette::Normal && !(vopt->state & QStyle::State_Active))
768 cg = QPalette::Inactive;
770 QRect itemRect = subElementRect(QStyle::SE_ItemViewItemFocusRect, option, widget).adjusted(-1, 0, 1, 0);
771 itemRect.setTop(vopt->rect.top());
772 itemRect.setBottom(vopt->rect.bottom());
774 QSize sectionSize = itemRect.size();
775 if (vopt->showDecorationSelected)
776 sectionSize = vopt->rect.size();
778 if (view->selectionBehavior() == QAbstractItemView::SelectRows)
779 sectionSize.setWidth(vopt->rect.width());
780 if (view->selectionMode() == QAbstractItemView::NoSelection)
784 if (vopt->backgroundBrush.style() != Qt::NoBrush) {
785 painter->setBrushOrigin(vopt->rect.topLeft());
786 painter->fillRect(vopt->rect, vopt->backgroundBrush);
789 if (hover || selected) {
790 QString key = QString::fromLatin1("qvdelegate-%1-%2-%3-%4-%5").arg(sectionSize.width())
791 .arg(sectionSize.height()).arg(selected).arg(active).arg(hover);
792 if (!QPixmapCache::find(key, pixmap)) {
793 pixmap = QPixmap(sectionSize);
794 pixmap.fill(Qt::transparent);
797 if (selected && hover)
798 state = LISS_HOTSELECTED;
799 else if (selected && !active)
800 state = LISS_SELECTEDNOTFOCUS;
802 state = LISS_SELECTED;
806 QPainter pixmapPainter(&pixmap);
807 XPThemeData theme(0, &pixmapPainter,
808 QWindowsXPStylePrivate::TreeViewTheme,
809 LVP_LISTITEM, state, QRect(0, 0, sectionSize.width(), sectionSize.height()));
810 if (d->initTreeViewTheming() && theme.isValid()) {
811 d->drawBackground(theme);
813 QWindowsXPStyle::drawPrimitive(PE_PanelItemViewItem, option, painter, widget);
816 QPixmapCache::insert(key, pixmap);
819 if (vopt->showDecorationSelected) {
820 const int frame = 2; //Assumes a 2 pixel pixmap border
821 QRect srcRect = QRect(0, 0, sectionSize.width(), sectionSize.height());
822 QRect pixmapRect = vopt->rect;
823 bool reverse = vopt->direction == Qt::RightToLeft;
824 bool leftSection = vopt->viewItemPosition == QStyleOptionViewItemV4::Beginning;
825 bool rightSection = vopt->viewItemPosition == QStyleOptionViewItemV4::End;
826 if (vopt->viewItemPosition == QStyleOptionViewItemV4::OnlyOne
827 || vopt->viewItemPosition == QStyleOptionViewItemV4::Invalid)
828 painter->drawPixmap(pixmapRect.topLeft(), pixmap);
829 else if (reverse ? rightSection : leftSection){
830 painter->drawPixmap(QRect(pixmapRect.topLeft(),
831 QSize(frame, pixmapRect.height())), pixmap,
832 QRect(QPoint(0, 0), QSize(frame, pixmapRect.height())));
833 painter->drawPixmap(pixmapRect.adjusted(frame, 0, 0, 0),
834 pixmap, srcRect.adjusted(frame, 0, -frame, 0));
835 } else if (reverse ? leftSection : rightSection) {
836 painter->drawPixmap(QRect(pixmapRect.topRight() - QPoint(frame - 1, 0),
837 QSize(frame, pixmapRect.height())), pixmap,
838 QRect(QPoint(pixmapRect.width() - frame, 0),
839 QSize(frame, pixmapRect.height())));
840 painter->drawPixmap(pixmapRect.adjusted(0, 0, -frame, 0),
841 pixmap, srcRect.adjusted(frame, 0, -frame, 0));
842 } else if (vopt->viewItemPosition == QStyleOptionViewItemV4::Middle)
843 painter->drawPixmap(pixmapRect, pixmap,
844 srcRect.adjusted(frame, 0, -frame, 0));
846 if (vopt->text.isEmpty() && vopt->icon.isNull())
848 painter->drawPixmap(itemRect.topLeft(), pixmap);
852 QWindowsXPStyle::drawPrimitive(element, option, painter, widget);
858 const QDialogButtonBox *buttonBox = 0;
860 if (qobject_cast<const QMessageBox *> (widget))
861 buttonBox = widget->findChild<const QDialogButtonBox *>(QLatin1String("qt_msgbox_buttonbox"));
862 #ifndef QT_NO_INPUTDIALOG
863 else if (qobject_cast<const QInputDialog *> (widget))
864 buttonBox = widget->findChild<const QDialogButtonBox *>(QLatin1String("qt_inputdlg_buttonbox"));
865 #endif // QT_NO_INPUTDIALOG
868 //draw white panel part
869 XPThemeData theme(widget, painter,
870 QWindowsXPStylePrivate::TaskDialogTheme,
871 TDLG_PRIMARYPANEL, 0, option->rect);
872 QRect toprect = option->rect;
873 toprect.setBottom(buttonBox->geometry().top());
874 theme.rect = toprect;
875 d->drawBackground(theme);
877 //draw bottom panel part
878 QRect buttonRect = option->rect;
879 buttonRect.setTop(buttonBox->geometry().top());
880 theme.rect = buttonRect;
881 theme.partId = TDLG_SECONDARYPANEL;
882 d->drawBackground(theme);
887 QWindowsXPStyle::drawPrimitive(element, option, painter, widget);
896 see drawPrimitive for comments on the animation support
898 void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption *option,
899 QPainter *painter, const QWidget *widget) const
901 QWindowsVistaStylePrivate *d = const_cast<QWindowsVistaStylePrivate*>(d_func());
903 if (!QWindowsVistaStylePrivate::useVista()) {
904 QWindowsStyle::drawControl(element, option, painter, widget);
908 bool selected = option->state & State_Selected;
909 bool pressed = option->state & State_Sunken;
910 bool disabled = !(option->state & State_Enabled);
912 int state = option->state;
913 int themeNumber = -1;
915 QRect rect(option->rect);
916 State flags = option->state;
923 if (d->transitionsEnabled() && widget) {
924 if (const QStyleOptionButton *button = qstyleoption_cast<const QStyleOptionButton *>(option)) {
925 if ((qobject_cast<const QPushButton*>(widget) && element == CE_PushButtonBevel))
927 QWidget *w = const_cast<QWidget *> (widget);
928 int oldState = w->property("_q_stylestate").toInt();
929 oldRect = w->property("_q_stylerect").toRect();
931 w->setProperty("_q_stylestate", (int)option->state);
932 w->setProperty("_q_stylerect", w->rect());
934 bool wasDefault = w->property("_q_isdefault").toBool();
935 bool isDefault = button->features & QStyleOptionButton::DefaultButton;
936 w->setProperty("_q_isdefault", isDefault);
938 bool doTransition = ((state & State_Sunken) != (oldState & State_Sunken) ||
939 (state & State_On) != (oldState & State_On) ||
940 (state & State_MouseOver) != (oldState & State_MouseOver));
942 if (oldRect != newRect || (wasDefault && !isDefault))
944 doTransition = false;
945 d->stopAnimation(widget);
949 QImage startImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
950 QImage endImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
951 QWindowsVistaAnimation *anim = d->widgetAnimation(widget);
953 QStyleOptionButton opt = *button;
954 opt.state = (QStyle::State)oldState;
957 QWindowsVistaTransition *t = new QWindowsVistaTransition;
959 QPainter startPainter(&startImage);
962 proxy()->drawControl(element, &opt, &startPainter, 0 /* Intentional */);
964 anim->paint(&startPainter, &opt);
965 d->stopAnimation(widget);
968 t->setStartImage(startImage);
969 d->startAnimation(t);
972 QPainter endPainter(&endImage);
973 proxy()->drawControl(element, option, &endPainter, 0 /* Intentional */);
974 t->setEndImage(endImage);
976 HTHEME theme = pOpenThemeData(0, L"Button");
978 int fromState = buttonStateId(oldState, BP_PUSHBUTTON);
979 int toState = buttonStateId(option->state, BP_PUSHBUTTON);
980 if (pGetThemeTransitionDuration(theme, BP_PUSHBUTTON, fromState, toState, TMT_TRANSITIONDURATIONS, &duration) == S_OK)
981 t->setDuration(duration);
984 t->setStartTime(QTime::currentTime());
990 case CE_PushButtonBevel:
991 if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option))
993 QWindowsVistaAnimation *anim = d->widgetAnimation(widget);
994 if (anim && (btn->state & State_Enabled)) {
995 anim->paint(painter, option);
997 themeNumber = QWindowsXPStylePrivate::ButtonTheme;
998 partId = BP_PUSHBUTTON;
999 if (btn->features & QStyleOptionButton::CommandLinkButton)
1000 partId = BP_COMMANDLINK;
1001 bool justFlat = (btn->features & QStyleOptionButton::Flat) && !(flags & (State_On|State_Sunken));
1002 if (!(flags & State_Enabled) && !(btn->features & QStyleOptionButton::Flat))
1003 stateId = PBS_DISABLED;
1006 else if (flags & (State_Sunken | State_On))
1007 stateId = PBS_PRESSED;
1008 else if (flags & State_MouseOver)
1010 else if (btn->features & QStyleOptionButton::DefaultButton && (state & State_Active))
1011 stateId = PBS_DEFAULTED;
1013 stateId = PBS_NORMAL;
1017 if (widget && d->transitionsEnabled() && (btn->features & QStyleOptionButton::DefaultButton) &&
1018 !(state & (State_Sunken | State_On)) && !(state & State_MouseOver) &&
1019 (state & State_Enabled) && (state & State_Active))
1021 if (!anim && widget) {
1022 QImage startImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
1024 QImage alternateImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
1025 alternateImage.fill(0);
1027 QWindowsVistaPulse *pulse = new QWindowsVistaPulse;
1028 pulse->setWidget(const_cast<QWidget*>(widget));
1030 QPainter startPainter(&startImage);
1031 stateId = PBS_DEFAULTED;
1032 XPThemeData theme(widget, &startPainter, themeNumber, partId, stateId, rect);
1033 d->drawBackground(theme);
1035 QPainter alternatePainter(&alternateImage);
1036 theme.stateId = PBS_DEFAULTED_ANIMATING;
1037 theme.painter = &alternatePainter;
1038 d->drawBackground(theme);
1039 pulse->setPrimaryImage(startImage);
1040 pulse->setAlternateImage(alternateImage);
1041 pulse->setStartTime(QTime::currentTime());
1042 pulse->setDuration(2000);
1043 d->startAnimation(pulse);
1048 anim->paint(painter, option);
1050 XPThemeData theme(widget, painter, themeNumber, partId, stateId, rect);
1051 d->drawBackground(theme);
1055 d->stopAnimation(widget);
1056 XPThemeData theme(widget, painter, themeNumber, partId, stateId, rect);
1057 d->drawBackground(theme);
1061 if (btn->features & QStyleOptionButton::HasMenu) {
1062 int mbiw = 0, mbih = 0;
1063 XPThemeData theme(widget, 0, QWindowsXPStylePrivate::ToolBarTheme,
1065 if (theme.isValid()) {
1067 if (pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size) == S_OK) {
1072 QRect ir = subElementRect(SE_PushButtonContents, option, 0);
1073 QStyleOptionButton newBtn = *btn;
1074 newBtn.rect = QStyle::visualRect(option->direction, option->rect,
1075 QRect(ir.right() - mbiw - 2,
1076 option->rect.top() + (option->rect.height()/2) - (mbih/2),
1077 mbiw + 1, mbih + 1));
1078 proxy()->drawPrimitive(PE_IndicatorArrowDown, &newBtn, painter, widget);
1083 #ifndef QT_NO_PROGRESSBAR
1084 case CE_ProgressBarContents:
1085 if (const QStyleOptionProgressBar *bar
1086 = qstyleoption_cast<const QStyleOptionProgressBar *>(option)) {
1087 bool isIndeterminate = (bar->minimum == 0 && bar->maximum == 0);
1088 bool vertical = false;
1089 bool inverted = false;
1090 if (const QStyleOptionProgressBarV2 *pb2 = qstyleoption_cast<const QStyleOptionProgressBarV2 *>(option)) {
1091 vertical = (pb2->orientation == Qt::Vertical);
1092 inverted = pb2->invertedAppearance;
1095 if (const QProgressBar *progressbar = qobject_cast<const QProgressBar *>(widget)) {
1096 if (isIndeterminate || (progressbar->value() > 0 && (progressbar->value() < progressbar->maximum()) && d->transitionsEnabled())) {
1097 if (!d->widgetAnimation(progressbar)) {
1098 QWindowsVistaAnimation *a = new QWindowsVistaAnimation;
1099 a->setWidget(const_cast<QWidget*>(widget));
1100 a->setStartTime(QTime::currentTime());
1101 d->startAnimation(a);
1104 d->stopAnimation(progressbar);
1108 XPThemeData theme(widget, painter,
1109 QWindowsXPStylePrivate::ProgressTheme,
1110 vertical ? PP_FILLVERT : PP_FILL);
1111 theme.rect = option->rect;
1112 bool reverse = (bar->direction == Qt::LeftToRight && inverted) || (bar->direction == Qt::RightToLeft && !inverted);
1113 QTime current = QTime::currentTime();
1115 if (isIndeterminate) {
1116 if (QWindowsVistaAnimation *a = d->widgetAnimation(widget)) {
1118 int animationWidth = glowSize * 2 + (vertical ? theme.rect.height() : theme.rect.width());
1119 int animOffset = a->startTime().msecsTo(current) / 4;
1120 if (animOffset > animationWidth)
1121 a->setStartTime(QTime::currentTime());
1123 painter->setClipRect(theme.rect);
1125 QSize pixmapSize(14, 14);
1127 animRect = QRect(theme.rect.left(),
1128 inverted ? rect.top() - glowSize + animOffset :
1129 rect.bottom() + glowSize - animOffset,
1130 rect.width(), glowSize);
1131 pixmapSize.setHeight(animRect.height());
1133 animRect = QRect(rect.left() - glowSize + animOffset,
1134 rect.top(), glowSize, rect.height());
1135 animRect = QStyle::visualRect(reverse ? Qt::RightToLeft : Qt::LeftToRight,
1136 option->rect, animRect);
1137 pixmapSize.setWidth(animRect.width());
1139 QString name = QString::fromLatin1("qiprogress-%1-%2").arg(pixmapSize.width()).arg(pixmapSize.height());
1141 if (!QPixmapCache::find(name, pixmap)) {
1142 QImage image(pixmapSize, QImage::Format_ARGB32);
1143 image.fill(Qt::transparent);
1144 QPainter imagePainter(&image);
1145 theme.painter = &imagePainter;
1146 theme.partId = vertical ? PP_FILLVERT : PP_FILL;
1147 theme.rect = QRect(QPoint(0,0), theme.rect.size());
1148 QLinearGradient alphaGradient(0, 0, vertical ? 0 : image.width(),
1149 vertical ? image.height() : 0);
1150 alphaGradient.setColorAt(0, QColor(0, 0, 0, 0));
1151 alphaGradient.setColorAt(0.5, QColor(0, 0, 0, 220));
1152 alphaGradient.setColorAt(1, QColor(0, 0, 0, 0));
1153 imagePainter.fillRect(image.rect(), alphaGradient);
1154 imagePainter.setCompositionMode(QPainter::CompositionMode_SourceIn);
1155 d->drawBackground(theme);
1157 pixmap = QPixmap::fromImage(image);
1158 QPixmapCache::insert(name, pixmap);
1160 painter->drawPixmap(animRect, pixmap);
1165 qint64 progress = qMax<qint64>(bar->progress, bar->minimum); // workaround for bug in QProgressBar
1168 int maxHeight = option->rect.height();
1170 double vc6_workaround = ((progress - qint64(bar->minimum)) / qMax(double(1.0), double(qint64(bar->maximum) - qint64(bar->minimum))) * maxHeight);
1171 int height = isIndeterminate ? maxHeight: qMax(int(vc6_workaround), minHeight);
1172 theme.rect.setHeight(height);
1174 theme.rect.moveTop(rect.height() - theme.rect.height());
1176 int maxWidth = option->rect.width();
1178 double vc6_workaround = ((progress - qint64(bar->minimum)) / qMax(double(1.0), double(qint64(bar->maximum) - qint64(bar->minimum))) * maxWidth);
1179 int width = isIndeterminate ? maxWidth : qMax(int(vc6_workaround), minWidth);
1180 theme.rect.setWidth(width);
1181 theme.rect = QStyle::visualRect(reverse ? Qt::RightToLeft : Qt::LeftToRight,
1182 option->rect, theme.rect);
1184 d->drawBackground(theme);
1186 if (QWindowsVistaAnimation *a = d->widgetAnimation(widget)) {
1188 int animationWidth = glowSize * 2 + (vertical ? theme.rect.height() : theme.rect.width());
1189 int animOffset = a->startTime().msecsTo(current) / 4;
1190 theme.partId = vertical ? PP_MOVEOVERLAYVERT : PP_MOVEOVERLAY;
1191 if (animOffset > animationWidth) {
1192 if (bar->progress < bar->maximum)
1193 a->setStartTime(QTime::currentTime());
1195 d->stopAnimation(widget); //we stop the glow motion only after it has
1199 painter->setClipRect(theme.rect);
1201 theme.rect = QRect(theme.rect.left(),
1202 inverted ? rect.top() - glowSize + animOffset :
1203 rect.bottom() + glowSize - animOffset,
1204 rect.width(), glowSize);
1206 theme.rect = QRect(rect.left() - glowSize + animOffset,rect.top(), glowSize, rect.height());
1207 theme.rect = QStyle::visualRect(reverse ? Qt::RightToLeft : Qt::LeftToRight, option->rect, theme.rect);
1209 d->drawBackground(theme);
1215 #endif // QT_NO_PROGRESSBAR
1216 case CE_MenuBarItem:
1219 if (const QStyleOptionMenuItem *mbi = qstyleoption_cast<const QStyleOptionMenuItem *>(option))
1221 if (mbi->menuItemType == QStyleOptionMenuItem::DefaultItem)
1224 QPalette::ColorRole textRole = disabled ? QPalette::Text : QPalette::ButtonText;
1225 QPixmap pix = mbi->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize, option, widget), QIcon::Normal);
1227 uint alignment = Qt::AlignCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine;
1228 if (!proxy()->styleHint(SH_UnderlineShortcut, mbi, widget))
1229 alignment |= Qt::TextHideMnemonic;
1231 //The rect adjustment is a workaround for the menu not really filling its background.
1232 XPThemeData theme(widget, painter,
1233 QWindowsXPStylePrivate::MenuTheme,
1234 MENU_BARBACKGROUND, 0, option->rect.adjusted(-1, 0, 2, 1));
1235 d->drawBackground(theme);
1237 int stateId = MBI_NORMAL;
1239 stateId = MBI_DISABLED;
1241 stateId = MBI_PUSHED;
1245 XPThemeData theme2(widget, painter,
1246 QWindowsXPStylePrivate::MenuTheme,
1247 MENU_BARITEM, stateId, option->rect);
1248 d->drawBackground(theme2);
1251 drawItemPixmap(painter, mbi->rect, alignment, pix);
1253 drawItemText(painter, mbi->rect, alignment, mbi->palette, mbi->state & State_Enabled, mbi->text, textRole);
1259 if (const QStyleOptionMenuItem *menuitem = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) {
1260 // windows always has a check column, regardless whether we have an icon or not
1265 XPThemeData theme(widget, 0, QWindowsXPStylePrivate::MenuTheme,
1266 MENU_POPUPCHECKBACKGROUND, MBI_HOT);
1267 pGetThemePartSize(theme.handle(), NULL, MENU_POPUPCHECK, 0, NULL,TS_TRUE, &size);
1268 pGetThemeMargins(theme.handle(), NULL, MENU_POPUPCHECK, 0, TMT_CONTENTMARGINS, NULL, &margins);
1269 checkcol = qMax(menuitem->maxIconWidth, int(6 + size.cx + margins.cxLeftWidth + margins.cxRightWidth));
1271 QRect rect = option->rect;
1273 //draw vertical menu line
1274 QPoint p1 = QStyle::visualPos(option->direction, menuitem->rect, QPoint(checkcol, rect.top()));
1275 QPoint p2 = QStyle::visualPos(option->direction, menuitem->rect, QPoint(checkcol, rect.bottom()));
1276 QRect gutterRect(p1.x(), p1.y(), 3, p2.y() - p1.y() + 1);
1277 XPThemeData theme2(widget, painter, QWindowsXPStylePrivate::MenuTheme,
1278 MENU_POPUPGUTTER, stateId, gutterRect);
1279 d->drawBackground(theme2);
1282 menuitem->rect.getRect(&x, &y, &w, &h);
1283 int tab = menuitem->tabWidth;
1284 bool dis = !(menuitem->state & State_Enabled);
1285 bool checked = menuitem->checkType != QStyleOptionMenuItem::NotCheckable
1286 ? menuitem->checked : false;
1287 bool act = menuitem->state & State_Selected;
1289 if (menuitem->menuItemType == QStyleOptionMenuItem::Separator) {
1290 int yoff = y-2 + h / 2;
1291 QPoint p1 = QPoint(x + checkcol, yoff);
1292 QPoint p2 = QPoint(x + w + 6 , yoff);
1294 QRect subRect(p1.x(), p1.y(), p2.x() - p1.x(), 6);
1295 subRect = QStyle::visualRect(option->direction, option->rect, subRect );
1296 XPThemeData theme2(widget, painter,
1297 QWindowsXPStylePrivate::MenuTheme,
1298 MENU_POPUPSEPARATOR, stateId, subRect);
1299 d->drawBackground(theme2);
1303 QRect vCheckRect = visualRect(option->direction, menuitem->rect, QRect(menuitem->rect.x(),
1304 menuitem->rect.y(), checkcol - 6, menuitem->rect.height()));
1308 XPThemeData theme2(widget, painter,
1309 QWindowsXPStylePrivate::MenuTheme,
1310 MENU_POPUPITEM, stateId, option->rect);
1311 d->drawBackground(theme2);
1315 XPThemeData theme(widget, painter,
1316 QWindowsXPStylePrivate::MenuTheme,
1317 MENU_POPUPCHECKBACKGROUND,
1318 menuitem->icon.isNull() ? MBI_HOT : MBI_PUSHED, vCheckRect);
1321 pGetThemePartSize(theme.handle(), NULL, MENU_POPUPCHECK, 0, NULL,TS_TRUE, &size);
1322 pGetThemeMargins(theme.handle(), NULL, MENU_POPUPCHECK, 0,
1323 TMT_CONTENTMARGINS, NULL, &margins);
1324 QRect checkRect(0, 0, size.cx + margins.cxLeftWidth + margins.cxRightWidth ,
1325 size.cy + margins.cyBottomHeight + margins.cyTopHeight);
1326 checkRect.moveCenter(vCheckRect.center());
1327 theme.rect = checkRect;
1329 d->drawBackground(theme);
1331 if (menuitem->icon.isNull()) {
1332 checkRect = QRect(0, 0, size.cx, size.cy);
1333 checkRect.moveCenter(theme.rect.center());
1334 theme.rect = checkRect;
1336 theme.partId = MENU_POPUPCHECK;
1337 bool bullet = menuitem->checkType & QStyleOptionMenuItem::Exclusive;
1339 theme.stateId = bullet ? MC_BULLETDISABLED: MC_CHECKMARKDISABLED;
1341 theme.stateId = bullet ? MC_BULLETNORMAL: MC_CHECKMARKNORMAL;
1342 d->drawBackground(theme);
1346 if (!menuitem->icon.isNull()) {
1347 QIcon::Mode mode = dis ? QIcon::Disabled : QIcon::Normal;
1349 mode = QIcon::Active;
1352 pixmap = menuitem->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize, option, widget), mode, QIcon::On);
1354 pixmap = menuitem->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize, option, widget), mode);
1355 int pixw = pixmap.width();
1356 int pixh = pixmap.height();
1357 QRect pmr(0, 0, pixw, pixh);
1358 pmr.moveCenter(vCheckRect.center());
1359 painter->setPen(menuitem->palette.text().color());
1360 painter->drawPixmap(pmr.topLeft(), pixmap);
1363 painter->setPen(menuitem->palette.buttonText().color());
1367 discol = menuitem->palette.text().color();
1368 painter->setPen(discol);
1371 int xm = windowsItemFrame + checkcol + windowsItemHMargin;
1372 int xpos = menuitem->rect.x() + xm;
1373 QRect textRect(xpos, y + windowsItemVMargin, w - xm - windowsRightBorder - tab + 1, h - 2 * windowsItemVMargin);
1374 QRect vTextRect = visualRect(option->direction, menuitem->rect, textRect);
1375 QString s = menuitem->text;
1376 if (!s.isEmpty()) { // draw text
1378 int t = s.indexOf(QLatin1Char('\t'));
1379 int text_flags = Qt::AlignVCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine;
1380 if (!proxy()->styleHint(SH_UnderlineShortcut, menuitem, widget))
1381 text_flags |= Qt::TextHideMnemonic;
1382 text_flags |= Qt::AlignLeft;
1384 QRect vShortcutRect = visualRect(option->direction, menuitem->rect,
1385 QRect(textRect.topRight(), QPoint(menuitem->rect.right(), textRect.bottom())));
1386 painter->drawText(vShortcutRect, text_flags, s.mid(t + 1));
1389 QFont font = menuitem->font;
1390 if (menuitem->menuItemType == QStyleOptionMenuItem::DefaultItem)
1392 painter->setFont(font);
1393 painter->setPen(discol);
1394 painter->drawText(vTextRect, text_flags, s.left(t));
1397 if (menuitem->menuItemType == QStyleOptionMenuItem::SubMenu) {// draw sub menu arrow
1398 int dim = (h - 2 * windowsItemFrame) / 2;
1399 PrimitiveElement arrow;
1400 arrow = (option->direction == Qt::RightToLeft) ? PE_IndicatorArrowLeft : PE_IndicatorArrowRight;
1401 xpos = x + w - windowsArrowHMargin - windowsItemFrame - dim;
1402 QRect vSubMenuRect = visualRect(option->direction, menuitem->rect, QRect(xpos, y + h / 2 - dim / 2, dim, dim));
1403 QStyleOptionMenuItem newMI = *menuitem;
1404 newMI.rect = vSubMenuRect;
1405 newMI.state = dis ? State_None : State_Enabled;
1406 proxy()->drawPrimitive(arrow, &newMI, painter, widget);
1410 #endif // QT_NO_MENU
1411 case CE_HeaderSection:
1412 if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) {
1413 partId = HP_HEADERITEM;
1414 if (flags & State_Sunken)
1415 stateId = HIS_PRESSED;
1416 else if (flags & State_MouseOver)
1419 stateId = HIS_NORMAL;
1421 if (header->sortIndicator != QStyleOptionHeader::None)
1424 XPThemeData theme(widget, painter,
1425 QWindowsXPStylePrivate::HeaderTheme,
1426 partId, stateId, option->rect);
1427 d->drawBackground(theme);
1430 case CE_MenuBarEmptyArea:
1432 stateId = MBI_NORMAL;
1433 if (!(state & State_Enabled))
1434 stateId = MBI_DISABLED;
1435 XPThemeData theme(widget, painter,
1436 QWindowsXPStylePrivate::MenuTheme,
1437 MENU_BARBACKGROUND, stateId, option->rect);
1438 d->drawBackground(theme);
1442 if (const QStyleOptionToolBar *toolbar = qstyleoption_cast<const QStyleOptionToolBar *>(option)) {
1443 QPalette pal = option->palette;
1444 pal.setColor(QPalette::Dark, option->palette.background().color().darker(130));
1445 QStyleOptionToolBar copyOpt = *toolbar;
1446 copyOpt.palette = pal;
1447 QWindowsStyle::drawControl(element, ©Opt, painter, widget);
1450 case CE_DockWidgetTitle:
1451 if (const QDockWidget *dockWidget = qobject_cast<const QDockWidget *>(widget)) {
1452 QRect rect = option->rect;
1453 if (dockWidget->isFloating()) {
1454 QWindowsXPStyle::drawControl(element, option, painter, widget);
1455 break; //otherwise fall through
1458 if (const QStyleOptionDockWidget *dwOpt = qstyleoption_cast<const QStyleOptionDockWidget *>(option)) {
1460 const QStyleOptionDockWidgetV2 *v2
1461 = qstyleoption_cast<const QStyleOptionDockWidgetV2*>(dwOpt);
1462 bool verticalTitleBar = v2 == 0 ? false : v2->verticalTitleBar;
1464 if (verticalTitleBar) {
1465 QSize s = rect.size();
1469 painter->translate(rect.left() - 1, rect.top() + rect.width());
1470 painter->rotate(-90);
1471 painter->translate(-rect.left() + 1, -rect.top());
1474 painter->setBrush(option->palette.background().color().darker(110));
1475 painter->setPen(option->palette.background().color().darker(130));
1476 painter->drawRect(rect.adjusted(0, 1, -1, -3));
1478 int buttonMargin = 4;
1479 int mw = proxy()->pixelMetric(QStyle::PM_DockWidgetTitleMargin, dwOpt, widget);
1480 int fw = proxy()->pixelMetric(PM_DockWidgetFrameWidth, dwOpt, widget);
1481 const QDockWidget *dw = qobject_cast<const QDockWidget *>(widget);
1482 bool isFloating = dw != 0 && dw->isFloating();
1484 QRect r = option->rect.adjusted(0, 2, -1, -3);
1485 QRect titleRect = r;
1487 if (dwOpt->closable) {
1488 QSize sz = standardIcon(QStyle::SP_TitleBarCloseButton, dwOpt, widget).actualSize(QSize(10, 10));
1489 titleRect.adjust(0, 0, -sz.width() - mw - buttonMargin, 0);
1492 if (dwOpt->floatable) {
1493 QSize sz = standardIcon(QStyle::SP_TitleBarMaxButton, dwOpt, widget).actualSize(QSize(10, 10));
1494 titleRect.adjust(0, 0, -sz.width() - mw - buttonMargin, 0);
1498 titleRect.adjust(0, -fw, 0, 0);
1499 if (widget != 0 && widget->windowIcon().cacheKey() != QApplication::windowIcon().cacheKey())
1500 titleRect.adjust(titleRect.height() + mw, 0, 0, 0);
1502 titleRect.adjust(mw, 0, 0, 0);
1503 if (!dwOpt->floatable && !dwOpt->closable)
1504 titleRect.adjust(0, 0, -mw, 0);
1506 if (!verticalTitleBar)
1507 titleRect = visualRect(dwOpt->direction, r, titleRect);
1509 if (!dwOpt->title.isEmpty()) {
1510 QString titleText = painter->fontMetrics().elidedText(dwOpt->title, Qt::ElideRight,
1511 verticalTitleBar ? titleRect.height() : titleRect.width());
1512 const int indent = painter->fontMetrics().descent();
1513 drawItemText(painter, rect.adjusted(indent + 1, 1, -indent - 1, -1),
1514 Qt::AlignLeft | Qt::AlignVCenter, dwOpt->palette,
1515 dwOpt->state & State_Enabled, titleText,
1516 QPalette::WindowText);
1521 #ifndef QT_NO_ITEMVIEWS
1522 case CE_ItemViewItem:
1524 const QStyleOptionViewItemV4 *vopt;
1525 const QAbstractItemView *view = qobject_cast<const QAbstractItemView *>(widget);
1526 bool newStyle = true;
1528 if (qobject_cast<const QTableView*>(widget))
1531 if (newStyle && view && (vopt = qstyleoption_cast<const QStyleOptionViewItemV4 *>(option))) {
1533 // We cannot currently get the correct selection color for "explorer style" views
1535 XPThemeData theme(d->treeViewHelper(), 0, QLatin1String("LISTVIEW"), 0, 0);
1536 unsigned int res = pGetThemeColor(theme.handle(), LVP_LISTITEM, LISS_SELECTED, TMT_TEXTCOLOR, &cref);
1537 QColor textColor(GetRValue(cref), GetGValue(cref), GetBValue(cref));
1539 QPalette palette = vopt->palette;
1540 palette.setColor(QPalette::All, QPalette::HighlightedText, palette.color(QPalette::Active, QPalette::Text));
1541 // Note that setting a saturated color here results in ugly XOR colors in the focus rect
1542 palette.setColor(QPalette::All, QPalette::Highlight, palette.base().color().darker(108));
1543 QStyleOptionViewItemV4 adjustedOption = *vopt;
1544 adjustedOption.palette = palette;
1545 // We hide the focusrect in singleselection as it is not required
1546 if ((view->selectionMode() == QAbstractItemView::SingleSelection)
1547 && !(vopt->state & State_KeyboardFocusChange))
1548 adjustedOption.state &= ~State_HasFocus;
1549 QWindowsXPStyle::drawControl(element, &adjustedOption, painter, widget);
1551 QWindowsXPStyle::drawControl(element, option, painter, widget);
1555 #endif // QT_NO_ITEMVIEWS
1558 QWindowsXPStyle::drawControl(element, option, painter, widget);
1566 see drawPrimitive for comments on the animation support
1569 void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyleOptionComplex *option,
1570 QPainter *painter, const QWidget *widget) const
1572 QWindowsVistaStylePrivate *d = const_cast<QWindowsVistaStylePrivate*>(d_func());
1573 if (!QWindowsVistaStylePrivate::useVista()) {
1574 QWindowsStyle::drawComplexControl(control, option, painter, widget);
1578 State state = option->state;
1579 SubControls sub = option->subControls;
1580 QRect r = option->rect;
1585 State flags = option->state;
1586 if (widget && widget->testAttribute(Qt::WA_UnderMouse) && widget->isActiveWindow())
1587 flags |= State_MouseOver;
1589 if (d->transitionsEnabled() && widget) {
1590 if ((qobject_cast<const QScrollBar *>(widget) && control == CC_ScrollBar)
1591 #ifndef QT_NO_SPINBOX
1592 || (qobject_cast<const QAbstractSpinBox*>(widget) && control == CC_SpinBox)
1593 #endif // QT_NO_SPINBOX
1594 #ifndef QT_NO_COMBOBOX
1595 || (qobject_cast<const QComboBox*>(widget) && control == CC_ComboBox)
1596 #endif // QT_NO_COMBOBOX
1599 QWidget *w = const_cast<QWidget *> (widget);
1601 int oldState = w->property("_q_stylestate").toInt();
1602 int oldActiveControls = w->property("_q_stylecontrols").toInt();
1603 QRect oldRect = w->property("_q_stylerect").toRect();
1604 w->setProperty("_q_stylestate", (int)option->state);
1605 w->setProperty("_q_stylecontrols", (int)option->activeSubControls);
1606 w->setProperty("_q_stylerect", w->rect());
1608 bool doTransition = ((state & State_Sunken) != (oldState & State_Sunken) ||
1609 (state & State_On) != (oldState & State_On) ||
1610 (state & State_MouseOver) != (oldState & State_MouseOver) ||
1611 oldActiveControls != option->activeSubControls);
1614 if (qstyleoption_cast<const QStyleOptionSlider *>(option)) {
1615 QRect oldSliderPos = w->property("_q_stylesliderpos").toRect();
1616 QRect currentPos = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget);
1617 w->setProperty("_q_stylesliderpos", currentPos);
1618 if (oldSliderPos != currentPos) {
1619 doTransition = false;
1620 d->stopAnimation(widget);
1622 } else if (control == CC_SpinBox) {
1623 //spinboxes have a transition when focus changes
1625 doTransition = (state & State_HasFocus) != (oldState & State_HasFocus);
1628 if (oldRect != option->rect) {
1629 doTransition = false;
1630 d->stopAnimation(widget);
1634 QImage startImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
1635 QImage endImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
1636 QWindowsVistaAnimation *anim = d->widgetAnimation(widget);
1637 QWindowsVistaTransition *t = new QWindowsVistaTransition;
1640 if (const QStyleOptionComboBox *combo = qstyleoption_cast<const QStyleOptionComboBox*>(option)) {
1641 //Combo boxes are special cased to avoid cleartype issues
1643 QPainter startPainter(&startImage);
1644 QStyleOptionComboBox startCombo = *combo;
1645 startCombo.state = (QStyle::State)oldState;
1646 startCombo.activeSubControls = (QStyle::SubControl)oldActiveControls;
1647 proxy()->drawComplexControl(control, &startCombo, &startPainter, 0 /* Intentional */);
1648 t->setStartImage(startImage);
1649 } else if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider*>(option)) {
1650 //This is a workaround for the direct3d engine as it currently has some issues with grabWindow
1652 QPainter startPainter(&startImage);
1653 QStyleOptionSlider startSlider = *slider;
1654 startSlider.state = (QStyle::State)oldState;
1655 startSlider.activeSubControls = (QStyle::SubControl)oldActiveControls;
1656 proxy()->drawComplexControl(control, &startSlider, &startPainter, 0 /* Intentional */);
1657 t->setStartImage(startImage);
1659 QPoint offset(0, 0);
1660 QWindow *window = widget->windowHandle();
1662 if (const QWidget *nativeParent = widget->nativeParentWidget()) {
1663 offset = widget->mapTo(nativeParent, offset);
1664 window = nativeParent->windowHandle();
1667 if (window && window->handle()) {
1668 const QPixmap pixmap = window->screen()->grabWindow(window->winId(),
1669 offset.x(), offset.y(), option->rect.width(), option->rect.height());
1670 t->setStartImage(pixmap.toImage());
1675 QPainter startPainter(&startImage);
1676 anim->paint(&startPainter, option);
1677 t->setStartImage(startImage);
1679 d->startAnimation(t);
1681 QPainter endPainter(&endImage);
1682 proxy()->drawComplexControl(control, option, &endPainter, 0 /* Intentional */);
1683 t->setEndImage(endImage);
1684 t->setStartTime(QTime::currentTime());
1686 if (option->state & State_MouseOver || option->state & State_Sunken)
1687 t->setDuration(150);
1689 t->setDuration(500);
1692 if (QWindowsVistaAnimation *anim = d->widgetAnimation(widget)) {
1693 anim->paint(painter, option);
1702 if (const QStyleOptionComboBox *cmb = qstyleoption_cast<const QStyleOptionComboBox *>(option))
1704 if (cmb->editable) {
1705 if (sub & SC_ComboBoxEditField) {
1706 partId = EP_EDITBORDER_NOSCROLL;
1707 if (!(flags & State_Enabled))
1708 stateId = ETS_DISABLED;
1709 else if (flags & State_MouseOver)
1711 else if (flags & State_HasFocus)
1712 stateId = ETS_FOCUSED;
1714 stateId = ETS_NORMAL;
1716 XPThemeData theme(widget, painter,
1717 QWindowsXPStylePrivate::EditTheme,
1718 partId, stateId, r);
1720 d->drawBackground(theme);
1722 if (sub & SC_ComboBoxArrow) {
1723 QRect subRect = proxy()->subControlRect(CC_ComboBox, option, SC_ComboBoxArrow, widget);
1724 XPThemeData theme(widget, painter, QWindowsXPStylePrivate::ComboboxTheme);
1725 theme.rect = subRect;
1726 partId = option->direction == Qt::RightToLeft ? CP_DROPDOWNBUTTONLEFT : CP_DROPDOWNBUTTONRIGHT;
1728 if (!(cmb->state & State_Enabled))
1729 stateId = CBXS_DISABLED;
1730 else if (cmb->state & State_Sunken || cmb->state & State_On)
1731 stateId = CBXS_PRESSED;
1732 else if (cmb->state & State_MouseOver && option->activeSubControls & SC_ComboBoxArrow)
1735 stateId = CBXS_NORMAL;
1737 theme.partId = partId;
1738 theme.stateId = stateId;
1739 d->drawBackground(theme);
1743 if (sub & SC_ComboBoxFrame) {
1744 QStyleOptionButton btn;
1745 btn.QStyleOption::operator=(*option);
1746 btn.rect = option->rect.adjusted(-1, -1, 1, 1);
1747 if (sub & SC_ComboBoxArrow)
1748 btn.features = QStyleOptionButton::HasMenu;
1749 proxy()->drawControl(QStyle::CE_PushButton, &btn, painter, widget);
1755 if (const QStyleOptionSlider *scrollbar = qstyleoption_cast<const QStyleOptionSlider *>(option))
1757 XPThemeData theme(widget, painter, QWindowsXPStylePrivate::ScrollBarTheme);
1758 bool maxedOut = (scrollbar->maximum == scrollbar->minimum);
1760 flags &= ~State_Enabled;
1762 bool isHorz = flags & State_Horizontal;
1763 bool isRTL = option->direction == Qt::RightToLeft;
1764 if (sub & SC_ScrollBarAddLine) {
1765 theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarAddLine, widget);
1766 partId = SBP_ARROWBTN;
1767 if (!(flags & State_Enabled))
1768 stateId = (isHorz ? (isRTL ? ABS_LEFTDISABLED : ABS_RIGHTDISABLED) : ABS_DOWNDISABLED);
1769 else if (scrollbar->activeSubControls & SC_ScrollBarAddLine && (scrollbar->state & State_Sunken))
1770 stateId = (isHorz ? (isRTL ? ABS_LEFTPRESSED : ABS_RIGHTPRESSED) : ABS_DOWNPRESSED);
1771 else if (scrollbar->activeSubControls & SC_ScrollBarAddLine && (scrollbar->state & State_MouseOver))
1772 stateId = (isHorz ? (isRTL ? ABS_LEFTHOT : ABS_RIGHTHOT) : ABS_DOWNHOT);
1773 else if (scrollbar->state & State_MouseOver)
1774 stateId = (isHorz ? (isRTL ? ABS_LEFTHOVER : ABS_RIGHTHOVER) : ABS_DOWNHOVER);
1776 stateId = (isHorz ? (isRTL ? ABS_LEFTNORMAL : ABS_RIGHTNORMAL) : ABS_DOWNNORMAL);
1777 theme.partId = partId;
1778 theme.stateId = stateId;
1779 d->drawBackground(theme);
1781 if (sub & SC_ScrollBarSubLine) {
1782 theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSubLine, widget);
1783 partId = SBP_ARROWBTN;
1784 if (!(flags & State_Enabled))
1785 stateId = (isHorz ? (isRTL ? ABS_RIGHTDISABLED : ABS_LEFTDISABLED) : ABS_UPDISABLED);
1786 else if (scrollbar->activeSubControls & SC_ScrollBarSubLine && (scrollbar->state & State_Sunken))
1787 stateId = (isHorz ? (isRTL ? ABS_RIGHTPRESSED : ABS_LEFTPRESSED) : ABS_UPPRESSED);
1788 else if (scrollbar->activeSubControls & SC_ScrollBarSubLine && (scrollbar->state & State_MouseOver))
1789 stateId = (isHorz ? (isRTL ? ABS_RIGHTHOT : ABS_LEFTHOT) : ABS_UPHOT);
1790 else if (scrollbar->state & State_MouseOver)
1791 stateId = (isHorz ? (isRTL ? ABS_RIGHTHOVER : ABS_LEFTHOVER) : ABS_UPHOVER);
1793 stateId = (isHorz ? (isRTL ? ABS_RIGHTNORMAL : ABS_LEFTNORMAL) : ABS_UPNORMAL);
1794 theme.partId = partId;
1795 theme.stateId = stateId;
1796 d->drawBackground(theme);
1799 theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget);
1800 theme.rect = theme.rect.united(proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSubPage, widget));
1801 theme.rect = theme.rect.united(proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarAddPage, widget));
1802 partId = flags & State_Horizontal ? SBP_LOWERTRACKHORZ : SBP_LOWERTRACKVERT;
1803 stateId = SCRBS_DISABLED;
1804 theme.partId = partId;
1805 theme.stateId = stateId;
1806 d->drawBackground(theme);
1808 if (sub & SC_ScrollBarSubPage) {
1809 theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSubPage, widget);
1810 partId = flags & State_Horizontal ? SBP_UPPERTRACKHORZ : SBP_UPPERTRACKVERT;
1811 if (!(flags & State_Enabled))
1812 stateId = SCRBS_DISABLED;
1813 else if (scrollbar->activeSubControls & SC_ScrollBarSubPage && (scrollbar->state & State_Sunken))
1814 stateId = SCRBS_PRESSED;
1815 else if (scrollbar->activeSubControls & SC_ScrollBarSubPage && (scrollbar->state & State_MouseOver))
1816 stateId = SCRBS_HOT;
1818 stateId = SCRBS_NORMAL;
1819 theme.partId = partId;
1820 theme.stateId = stateId;
1821 d->drawBackground(theme);
1823 if (sub & SC_ScrollBarAddPage) {
1824 theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarAddPage, widget);
1825 partId = flags & State_Horizontal ? SBP_LOWERTRACKHORZ : SBP_LOWERTRACKVERT;
1826 if (!(flags & State_Enabled))
1827 stateId = SCRBS_DISABLED;
1828 else if (scrollbar->activeSubControls & SC_ScrollBarAddPage && (scrollbar->state & State_Sunken))
1829 stateId = SCRBS_PRESSED;
1830 else if (scrollbar->activeSubControls & SC_ScrollBarAddPage && (scrollbar->state & State_MouseOver))
1831 stateId = SCRBS_HOT;
1833 stateId = SCRBS_NORMAL;
1834 theme.partId = partId;
1835 theme.stateId = stateId;
1836 d->drawBackground(theme);
1838 if (sub & SC_ScrollBarSlider) {
1839 theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget);
1840 if (!(flags & State_Enabled))
1841 stateId = SCRBS_DISABLED;
1842 else if (scrollbar->activeSubControls & SC_ScrollBarSlider && (scrollbar->state & State_Sunken))
1843 stateId = SCRBS_PRESSED;
1844 else if (scrollbar->activeSubControls & SC_ScrollBarSlider && (scrollbar->state & State_MouseOver))
1845 stateId = SCRBS_HOT;
1846 else if (option->state & State_MouseOver)
1847 stateId = SCRBS_HOVER;
1849 stateId = SCRBS_NORMAL;
1852 theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget);
1853 theme.partId = flags & State_Horizontal ? SBP_THUMBBTNHORZ : SBP_THUMBBTNVERT;
1854 theme.stateId = stateId;
1855 d->drawBackground(theme);
1857 // Calculate rect of gripper
1858 const int swidth = theme.rect.width();
1859 const int sheight = theme.rect.height();
1861 MARGINS contentsMargin;
1862 RECT rect = theme.toRECT(theme.rect);
1863 pGetThemeMargins(theme.handle(), 0, theme.partId, theme.stateId, TMT_SIZINGMARGINS, &rect, &contentsMargin);
1866 theme.partId = flags & State_Horizontal ? SBP_GRIPPERHORZ : SBP_GRIPPERVERT;
1867 pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size);
1868 int gw = size.cx, gh = size.cy;
1871 QRect gripperBounds;
1872 if (flags & State_Horizontal && ((swidth - contentsMargin.cxLeftWidth - contentsMargin.cxRightWidth) > gw)) {
1873 gripperBounds.setLeft(theme.rect.left() + swidth/2 - gw/2);
1874 gripperBounds.setTop(theme.rect.top() + sheight/2 - gh/2);
1875 gripperBounds.setWidth(gw);
1876 gripperBounds.setHeight(gh);
1877 } else if ((sheight - contentsMargin.cyTopHeight - contentsMargin.cyBottomHeight) > gh) {
1878 gripperBounds.setLeft(theme.rect.left() + swidth/2 - gw/2);
1879 gripperBounds.setTop(theme.rect.top() + sheight/2 - gh/2);
1880 gripperBounds.setWidth(gw);
1881 gripperBounds.setHeight(gh);
1884 // Draw gripper if there is enough space
1885 if (!gripperBounds.isEmpty() && flags & State_Enabled) {
1887 XPThemeData grippBackground = theme;
1888 grippBackground.partId = flags & State_Horizontal ? SBP_LOWERTRACKHORZ : SBP_LOWERTRACKVERT;
1889 theme.rect = gripperBounds;
1890 painter->setClipRegion(d->region(theme));// Only change inside the region of the gripper
1891 d->drawBackground(grippBackground);// The gutter is the grippers background
1892 d->drawBackground(theme); // Transparent gripper ontop of background
1899 #ifndef QT_NO_SPINBOX
1901 if (const QStyleOptionSpinBox *sb = qstyleoption_cast<const QStyleOptionSpinBox *>(option))
1903 XPThemeData theme(widget, painter, QWindowsXPStylePrivate::SpinTheme);
1904 if (sb->frame && (sub & SC_SpinBoxFrame)) {
1905 partId = EP_EDITBORDER_NOSCROLL;
1906 if (!(flags & State_Enabled))
1907 stateId = ETS_DISABLED;
1908 else if (flags & State_MouseOver)
1910 else if (flags & State_HasFocus)
1911 stateId = ETS_SELECTED;
1913 stateId = ETS_NORMAL;
1915 XPThemeData ftheme(widget, painter,
1916 QWindowsXPStylePrivate::EditTheme,
1917 partId, stateId, r);
1918 ftheme.noContent = true;
1919 d->drawBackground(ftheme);
1921 if (sub & SC_SpinBoxUp) {
1922 theme.rect = proxy()->subControlRect(CC_SpinBox, option, SC_SpinBoxUp, widget).adjusted(0, 0, 0, 1);
1924 if (!(sb->stepEnabled & QAbstractSpinBox::StepUpEnabled) || !(flags & State_Enabled))
1925 stateId = UPS_DISABLED;
1926 else if (sb->activeSubControls == SC_SpinBoxUp && (sb->state & State_Sunken))
1927 stateId = UPS_PRESSED;
1928 else if (sb->activeSubControls == SC_SpinBoxUp && (sb->state & State_MouseOver))
1931 stateId = UPS_NORMAL;
1932 theme.partId = partId;
1933 theme.stateId = stateId;
1934 d->drawBackground(theme);
1936 if (sub & SC_SpinBoxDown) {
1937 theme.rect = proxy()->subControlRect(CC_SpinBox, option, SC_SpinBoxDown, widget);
1939 if (!(sb->stepEnabled & QAbstractSpinBox::StepDownEnabled) || !(flags & State_Enabled))
1940 stateId = DNS_DISABLED;
1941 else if (sb->activeSubControls == SC_SpinBoxDown && (sb->state & State_Sunken))
1942 stateId = DNS_PRESSED;
1943 else if (sb->activeSubControls == SC_SpinBoxDown && (sb->state & State_MouseOver))
1946 stateId = DNS_NORMAL;
1947 theme.partId = partId;
1948 theme.stateId = stateId;
1949 d->drawBackground(theme);
1953 #endif // QT_NO_SPINBOX
1955 QWindowsXPStyle::drawComplexControl(control, option, painter, widget);
1963 QSize QWindowsVistaStyle::sizeFromContents(ContentsType type, const QStyleOption *option,
1964 const QSize &size, const QWidget *widget) const
1966 if (!QWindowsVistaStylePrivate::useVista())
1967 return QWindowsStyle::sizeFromContents(type, option, size, widget);
1972 sz = QWindowsXPStyle::sizeFromContents(type, option, size, widget);
1977 XPThemeData theme(widget, 0,
1978 QWindowsXPStylePrivate::MenuTheme,
1979 MENU_POPUPCHECKBACKGROUND, MBI_HOT);
1980 pGetThemePartSize(theme.handle(), NULL, MENU_POPUPCHECK, 0, NULL,TS_TRUE, &size);
1981 pGetThemeMargins(theme.handle(), NULL, MENU_POPUPCHECK, 0, TMT_CONTENTMARGINS, NULL, &margins);
1982 minimumHeight = qMax<qint32>(size.cy + margins.cyBottomHeight+ margins.cyTopHeight, sz.height());
1983 sz.rwidth() += size.cx + margins.cxLeftWidth + margins.cxRightWidth;
1986 if (const QStyleOptionMenuItem *menuitem = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) {
1987 if (menuitem->menuItemType != QStyleOptionMenuItem::Separator)
1988 sz.setHeight(minimumHeight);
1991 #ifndef QT_NO_MENUBAR
1992 case CT_MenuBarItem:
1994 sz += QSize(windowsItemHMargin * 5 + 1, 5);
1998 case CT_ItemViewItem:
1999 sz = QWindowsXPStyle::sizeFromContents(type, option, size, widget);
2004 //Spinbox adds frame twice
2005 sz = QWindowsStyle::sizeFromContents(type, option, size, widget);
2006 int border = proxy()->pixelMetric(PM_SpinBoxFrameWidth, option, widget);
2007 sz -= QSize(2*border, 2*border);
2013 return QWindowsXPStyle::sizeFromContents(type, option, size, widget);
2019 QRect QWindowsVistaStyle::subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const
2021 if (!QWindowsVistaStylePrivate::useVista())
2022 return QWindowsStyle::subElementRect(element, option, widget);
2024 QRect rect = QWindowsXPStyle::subElementRect(element, option, widget);
2027 case SE_PushButtonContents:
2028 if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) {
2030 HTHEME theme = pOpenThemeData(widget ? QWindowsVistaStylePrivate::winId(widget) : 0, L"Button");
2032 int stateId = PBS_NORMAL;
2033 if (!(option->state & State_Enabled))
2034 stateId = PBS_DISABLED;
2035 else if (option->state & State_Sunken)
2036 stateId = PBS_PRESSED;
2037 else if (option->state & State_MouseOver)
2039 else if (btn->features & QStyleOptionButton::DefaultButton)
2040 stateId = PBS_DEFAULTED;
2042 int border = proxy()->pixelMetric(PM_DefaultFrameWidth, btn, widget);
2043 rect = option->rect.adjusted(border, border, -border, -border);
2045 int result = pGetThemeMargins(theme,
2053 if (result == S_OK) {
2054 rect.adjust(borderSize.cxLeftWidth, borderSize.cyTopHeight,
2055 -borderSize.cxRightWidth, -borderSize.cyBottomHeight);
2056 rect = visualRect(option->direction, option->rect, rect);
2062 case SE_HeaderArrow:
2065 int h = option->rect.height();
2066 int w = option->rect.width();
2067 int x = option->rect.x();
2068 int y = option->rect.y();
2069 int margin = proxy()->pixelMetric(QStyle::PM_HeaderMargin, option, widget);
2071 XPThemeData theme(widget, 0,
2072 QWindowsXPStylePrivate::HeaderTheme,
2073 HP_HEADERSORTARROW, HSAS_SORTEDDOWN, option->rect);
2075 int arrowWidth = 13;
2076 int arrowHeight = 5;
2077 if (theme.isValid()) {
2079 if (pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size) == S_OK) {
2080 arrowWidth = size.cx;
2081 arrowHeight = size.cy;
2084 if (option->state & State_Horizontal) {
2085 r.setRect(x + w/2 - arrowWidth/2, y , arrowWidth, arrowHeight);
2087 int vert_size = w / 2;
2088 r.setRect(x + 5, y + h - margin * 2 - vert_size,
2089 w - margin * 2 - 5, vert_size);
2091 rect = visualRect(option->direction, option->rect, r);
2095 case SE_HeaderLabel:
2097 int margin = proxy()->pixelMetric(QStyle::PM_HeaderMargin, option, widget);
2098 QRect r = option->rect;
2099 r.setRect(option->rect.x() + margin, option->rect.y() + margin,
2100 option->rect.width() - margin * 2, option->rect.height() - margin * 2);
2101 if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) {
2102 // Subtract width needed for arrow, if there is one
2103 if (header->sortIndicator != QStyleOptionHeader::None) {
2104 if (!(option->state & State_Horizontal)) //horizontal arrows are positioned on top
2105 r.setHeight(r.height() - (option->rect.width() / 2) - (margin * 2));
2108 rect = visualRect(option->direction, option->rect, r);
2111 case SE_ProgressBarContents:
2112 rect = QCommonStyle::subElementRect(SE_ProgressBarGroove, option, widget);
2114 case SE_ItemViewItemDecoration:
2115 if (qstyleoption_cast<const QStyleOptionViewItemV4 *>(option))
2116 rect.adjust(-2, 0, 2, 0);
2118 case SE_ItemViewItemFocusRect:
2119 if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast<const QStyleOptionViewItemV4 *>(option)) {
2120 QRect textRect = subElementRect(QStyle::SE_ItemViewItemText, option, widget);
2121 QRect displayRect = subElementRect(QStyle::SE_ItemViewItemDecoration, option, widget);
2122 if (!vopt->icon.isNull())
2123 rect = textRect.united(displayRect);
2126 rect = rect.adjusted(1, 0, -1, 0);
2137 This function is used by subControlRect to check if a button
2138 should be drawn for the given subControl given a set of window flags.
2140 static bool buttonVisible(const QStyle::SubControl sc, const QStyleOptionTitleBar *tb){
2142 bool isMinimized = tb->titleBarState & Qt::WindowMinimized;
2143 bool isMaximized = tb->titleBarState & Qt::WindowMaximized;
2144 const uint flags = tb->titleBarFlags;
2145 bool retVal = false;
2147 case QStyle::SC_TitleBarContextHelpButton:
2148 if (flags & Qt::WindowContextHelpButtonHint)
2151 case QStyle::SC_TitleBarMinButton:
2152 if (!isMinimized && (flags & Qt::WindowMinimizeButtonHint))
2155 case QStyle::SC_TitleBarNormalButton:
2156 if (isMinimized && (flags & Qt::WindowMinimizeButtonHint))
2158 else if (isMaximized && (flags & Qt::WindowMaximizeButtonHint))
2161 case QStyle::SC_TitleBarMaxButton:
2162 if (!isMaximized && (flags & Qt::WindowMaximizeButtonHint))
2165 case QStyle::SC_TitleBarShadeButton:
2166 if (!isMinimized && flags & Qt::WindowShadeButtonHint)
2169 case QStyle::SC_TitleBarUnshadeButton:
2170 if (isMinimized && flags & Qt::WindowShadeButtonHint)
2173 case QStyle::SC_TitleBarCloseButton:
2174 if (flags & Qt::WindowSystemMenuHint)
2177 case QStyle::SC_TitleBarSysMenu:
2178 if (flags & Qt::WindowSystemMenuHint)
2189 int QWindowsVistaStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget,
2190 QStyleHintReturn *returnData) const
2192 QWindowsVistaStylePrivate *d = const_cast<QWindowsVistaStylePrivate*>(d_func());
2195 case SH_MessageBox_CenterButtons:
2198 case SH_ToolTip_Mask:
2200 if (QStyleHintReturnMask *mask = qstyleoption_cast<QStyleHintReturnMask*>(returnData)) {
2202 XPThemeData themeData(widget, 0,
2203 QWindowsXPStylePrivate::ToolTipTheme,
2204 TTP_STANDARD, TTSS_NORMAL, option->rect);
2205 mask->region = d->region(themeData);
2209 case SH_Table_GridLineColor:
2211 ret = option->palette.color(QPalette::Base).darker(118).rgb();
2216 ret = QWindowsXPStyle::styleHint(hint, option, widget, returnData);
2226 QRect QWindowsVistaStyle::subControlRect(ComplexControl control, const QStyleOptionComplex *option,
2227 SubControl subControl, const QWidget *widget) const
2229 if (!QWindowsVistaStylePrivate::useVista())
2230 return QWindowsStyle::subControlRect(control, option, subControl, widget);
2232 QRect rect = QWindowsXPStyle::subControlRect(control, option, subControl, widget);
2234 #ifndef QT_NO_COMBOBOX
2236 if (const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
2237 int x = cb->rect.x(),
2239 wi = cb->rect.width(),
2240 he = cb->rect.height();
2242 int margin = cb->frame ? 3 : 0;
2243 int bmarg = cb->frame ? 2 : 0;
2244 int arrowButtonWidth = bmarg + 16;
2245 xpos += wi - arrowButtonWidth;
2247 switch (subControl) {
2248 case SC_ComboBoxFrame:
2251 case SC_ComboBoxArrow:
2252 rect.setRect(xpos, y , arrowButtonWidth, he);
2254 case SC_ComboBoxEditField:
2255 rect.setRect(x + margin, y + margin, wi - 2 * margin - 16, he - 2 * margin);
2257 case SC_ComboBoxListBoxPopup:
2263 rect = visualRect(cb->direction, cb->rect, rect);
2266 #endif // QT_NO_COMBOBOX
2268 if (const QStyleOptionTitleBar *tb = qstyleoption_cast<const QStyleOptionTitleBar *>(option)) {
2269 if (!buttonVisible(subControl, tb))
2271 const bool isToolTitle = false;
2272 const int height = tb->rect.height();
2273 const int width = tb->rect.width();
2274 int buttonWidth = GetSystemMetrics(SM_CXSIZE) - 4;
2276 const int frameWidth = proxy()->pixelMetric(PM_MdiSubWindowFrameWidth, option, widget);
2277 const bool sysmenuHint = (tb->titleBarFlags & Qt::WindowSystemMenuHint) != 0;
2278 const bool minimizeHint = (tb->titleBarFlags & Qt::WindowMinimizeButtonHint) != 0;
2279 const bool maximizeHint = (tb->titleBarFlags & Qt::WindowMaximizeButtonHint) != 0;
2280 const bool contextHint = (tb->titleBarFlags & Qt::WindowContextHelpButtonHint) != 0;
2281 const bool shadeHint = (tb->titleBarFlags & Qt::WindowShadeButtonHint) != 0;
2283 switch (subControl) {
2284 case SC_TitleBarLabel:
2285 rect = QRect(frameWidth, 0, width - (buttonWidth + frameWidth + 10), height);
2288 rect.adjust(0, 0, -buttonWidth - 3, 0);
2290 if (minimizeHint || maximizeHint)
2291 rect.adjust(0, 0, -buttonWidth - 2, 0);
2294 const int leftOffset = height - 8;
2295 rect.adjust(leftOffset, 0, 0, 4);
2298 rect.adjust(0, 0, -buttonWidth - 2, 0);
2300 rect.adjust(0, 0, -buttonWidth - 2, 0);
2302 rect.adjust(0, 0, -buttonWidth - 2, 0);
2304 rect.adjust(0, 0, -buttonWidth - 2, 0);
2306 rect.translate(0, 2);
2307 rect = visualRect(option->direction, option->rect, rect);
2309 case SC_TitleBarSysMenu:
2311 const int controlTop = 6;
2312 const int controlHeight = height - controlTop - 3;
2313 int iconExtent = proxy()->pixelMetric(PM_SmallIconSize);
2314 QSize iconSize = tb->icon.actualSize(QSize(iconExtent, iconExtent));
2315 if (tb->icon.isNull())
2316 iconSize = QSize(controlHeight, controlHeight);
2317 int hPad = (controlHeight - iconSize.height())/2;
2318 int vPad = (controlHeight - iconSize.width())/2;
2319 rect = QRect(frameWidth + hPad, controlTop + vPad, iconSize.width(), iconSize.height());
2320 rect.translate(0, 3);
2321 rect = visualRect(option->direction, option->rect, rect);
2338 bool QWindowsVistaStyle::event(QEvent *e)
2340 Q_D(QWindowsVistaStyle);
2341 switch (e->type()) {
2344 QTimerEvent *timerEvent = (QTimerEvent *)e;
2345 if (d->animationTimer.timerId() == timerEvent->timerId()) {
2355 return QWindowsXPStyle::event(e);
2361 QStyle::SubControl QWindowsVistaStyle::hitTestComplexControl(ComplexControl control, const QStyleOptionComplex *option,
2362 const QPoint &pos, const QWidget *widget) const
2364 if (!QWindowsVistaStylePrivate::useVista()) {
2365 return QWindowsStyle::hitTestComplexControl(control, option, pos, widget);
2367 return QWindowsXPStyle::hitTestComplexControl(control, option, pos, widget);
2373 int QWindowsVistaStyle::pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const
2375 if (!QWindowsVistaStylePrivate::useVista()) {
2376 return QWindowsStyle::pixelMetric(metric, option, widget);
2380 case PM_DockWidgetTitleBarButtonMargin:
2381 return int(QStyleHelper::dpiScaled(5.));
2382 case PM_ScrollBarSliderMin:
2383 return int(QStyleHelper::dpiScaled(18.));
2384 case PM_MenuHMargin:
2385 case PM_MenuVMargin:
2387 case PM_MenuPanelWidth:
2392 return QWindowsXPStyle::pixelMetric(metric, option, widget);
2398 QPalette QWindowsVistaStyle::standardPalette() const
2400 return QWindowsXPStyle::standardPalette();
2406 void QWindowsVistaStyle::polish(QApplication *app)
2408 QWindowsXPStyle::polish(app);
2414 void QWindowsVistaStyle::polish(QWidget *widget)
2416 QWindowsXPStyle::polish(widget);
2417 #ifndef QT_NO_LINEEDIT
2418 if (qobject_cast<QLineEdit*>(widget))
2419 widget->setAttribute(Qt::WA_Hover);
2421 #endif // QT_NO_LINEEDIT
2422 if (qobject_cast<QGroupBox*>(widget))
2423 widget->setAttribute(Qt::WA_Hover);
2424 else if (qobject_cast<QCommandLinkButton*>(widget)) {
2425 QFont buttonFont = widget->font();
2426 buttonFont.setFamily(QLatin1String("Segoe UI"));
2427 widget->setFont(buttonFont);
2429 else if (widget->inherits("QTipLabel")){
2430 //note that since tooltips are not reused
2431 //we do not have to care about unpolishing
2432 widget->setContentsMargins(3, 0, 4, 0);
2434 HTHEME theme = pOpenThemeData(widget ? QWindowsVistaStylePrivate::winId(widget) : 0, L"TOOLTIP");
2436 if (pGetThemeColor(theme, TTP_STANDARD, TTSS_NORMAL, TMT_TEXTCOLOR, &bgRef) == S_OK) {
2437 QColor textColor = QColor::fromRgb(bgRef);
2439 pal.setColor(QPalette::All, QPalette::ToolTipText, textColor);
2440 widget->setPalette(pal);
2443 } else if (qobject_cast<QMessageBox *> (widget)) {
2444 widget->setAttribute(Qt::WA_StyledBackground);
2445 QDialogButtonBox *buttonBox = widget->findChild<QDialogButtonBox *>(QLatin1String("qt_msgbox_buttonbox"));
2447 buttonBox->setContentsMargins(0, 9, 0, 0);
2449 #ifndef QT_NO_INPUTDIALOG
2450 else if (qobject_cast<QInputDialog *> (widget)) {
2451 widget->setAttribute(Qt::WA_StyledBackground);
2452 QDialogButtonBox *buttonBox = widget->findChild<QDialogButtonBox *>(QLatin1String("qt_inputdlg_buttonbox"));
2454 buttonBox->setContentsMargins(0, 9, 0, 0);
2456 #endif // QT_NO_INPUTDIALOG
2457 else if (QTreeView *tree = qobject_cast<QTreeView *> (widget)) {
2458 tree->viewport()->setAttribute(Qt::WA_Hover);
2460 else if (QListView *list = qobject_cast<QListView *> (widget)) {
2461 list->viewport()->setAttribute(Qt::WA_Hover);
2468 void QWindowsVistaStyle::unpolish(QWidget *widget)
2470 QWindowsXPStyle::unpolish(widget);
2472 QWindowsVistaStylePrivate *d = const_cast<QWindowsVistaStylePrivate*>(d_func());
2473 d->stopAnimation(widget);
2475 #ifndef QT_NO_LINEEDIT
2476 if (qobject_cast<QLineEdit*>(widget))
2477 widget->setAttribute(Qt::WA_Hover, false);
2479 #endif // QT_NO_LINEEDIT
2480 if (qobject_cast<QGroupBox*>(widget))
2481 widget->setAttribute(Qt::WA_Hover, false);
2482 else if (qobject_cast<QMessageBox *> (widget)) {
2483 widget->setAttribute(Qt::WA_StyledBackground, false);
2484 QDialogButtonBox *buttonBox = widget->findChild<QDialogButtonBox *>(QLatin1String("qt_msgbox_buttonbox"));
2486 buttonBox->setContentsMargins(0, 0, 0, 0);
2488 #ifndef QT_NO_INPUTDIALOG
2489 else if (qobject_cast<QInputDialog *> (widget)) {
2490 widget->setAttribute(Qt::WA_StyledBackground, false);
2491 QDialogButtonBox *buttonBox = widget->findChild<QDialogButtonBox *>(QLatin1String("qt_inputdlg_buttonbox"));
2493 buttonBox->setContentsMargins(0, 0, 0, 0);
2495 #endif // QT_NO_INPUTDIALOG
2496 else if (QTreeView *tree = qobject_cast<QTreeView *> (widget)) {
2497 tree->viewport()->setAttribute(Qt::WA_Hover, false);
2498 } else if (qobject_cast<QCommandLinkButton*>(widget)) {
2499 QFont font = QApplication::font("QCommandLinkButton");
2500 QFont widgetFont = widget->font();
2501 widgetFont.setFamily(font.family()); //Only family set by polish
2502 widget->setFont(widgetFont);
2510 void QWindowsVistaStyle::unpolish(QApplication *app)
2512 QWindowsXPStyle::unpolish(app);
2518 void QWindowsVistaStyle::polish(QPalette &pal)
2520 QWindowsStyle::polish(pal);
2521 pal.setBrush(QPalette::AlternateBase, pal.base().color().darker(104));
2527 QPixmap QWindowsVistaStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *option,
2528 const QWidget *widget) const
2530 if (!QWindowsVistaStylePrivate::useVista()) {
2531 return QWindowsStyle::standardPixmap(standardPixmap, option, widget);
2533 return QWindowsXPStyle::standardPixmap(standardPixmap, option, widget);
2536 QWindowsVistaStylePrivate::QWindowsVistaStylePrivate() :
2537 QWindowsXPStylePrivate(), m_treeViewHelper(0)
2542 QWindowsVistaStylePrivate::~QWindowsVistaStylePrivate()
2544 qDeleteAll(animations);
2545 if (m_treeViewHelper)
2546 DestroyWindow(m_treeViewHelper);
2549 void QWindowsVistaStylePrivate::timerEvent()
2551 for (int i = animations.size() - 1 ; i >= 0 ; --i) {
2553 if (animations[i]->widget())
2554 animations[i]->widget()->update();
2556 if (!animations[i]->widget() ||
2557 !animations[i]->widget()->isVisible() ||
2558 animations[i]->widget()->window()->isMinimized() ||
2559 !animations[i]->running() ||
2560 !QWindowsVistaStylePrivate::useVista())
2562 QWindowsVistaAnimation *a = animations.takeAt(i);
2566 if (animations.size() == 0 && animationTimer.isActive()) {
2567 animationTimer.stop();
2571 void QWindowsVistaStylePrivate::stopAnimation(const QWidget *w)
2573 for (int i = animations.size() - 1 ; i >= 0 ; --i) {
2574 if (animations[i]->widget() == w) {
2575 QWindowsVistaAnimation *a = animations.takeAt(i);
2582 void QWindowsVistaStylePrivate::startAnimation(QWindowsVistaAnimation *t)
2584 Q_Q(QWindowsVistaStyle);
2585 stopAnimation(t->widget());
2586 animations.append(t);
2587 if (animations.size() > 0 && !animationTimer.isActive()) {
2588 animationTimer.start(45, q);
2592 bool QWindowsVistaStylePrivate::transitionsEnabled() const
2594 BOOL animEnabled = false;
2595 if (SystemParametersInfo(SPI_GETCLIENTAREAANIMATION, 0, &animEnabled, 0))
2604 QWindowsVistaAnimation * QWindowsVistaStylePrivate::widgetAnimation(const QWidget *widget) const
2608 foreach (QWindowsVistaAnimation *a, animations) {
2609 if (a->widget() == widget)
2617 Returns true if all the necessary theme engine symbols were
2620 bool QWindowsVistaStylePrivate::resolveSymbols()
2622 static bool tried = false;
2625 QSystemLibrary themeLib(QLatin1String("uxtheme"));
2626 pSetWindowTheme = (PtrSetWindowTheme )themeLib.resolve("SetWindowTheme");
2627 pIsThemePartDefined = (PtrIsThemePartDefined )themeLib.resolve("IsThemePartDefined");
2628 pGetThemePartSize = (PtrGetThemePartSize )themeLib.resolve("GetThemePartSize");
2629 pOpenThemeData = (PtrOpenThemeData )themeLib.resolve("OpenThemeData");
2630 pCloseThemeData = (PtrCloseThemeData )themeLib.resolve("CloseThemeData");
2631 pDrawThemeBackground = (PtrDrawThemeBackground )themeLib.resolve("DrawThemeBackground");
2632 pDrawThemeBackgroundEx = (PtrDrawThemeBackgroundEx )themeLib.resolve("DrawThemeBackgroundEx");
2633 pGetCurrentThemeName = (PtrGetCurrentThemeName )themeLib.resolve("GetCurrentThemeName");
2634 pGetThemeBool = (PtrGetThemeBool )themeLib.resolve("GetThemeBool");
2635 pGetThemeColor = (PtrGetThemeColor )themeLib.resolve("GetThemeColor");
2636 pGetThemeEnumValue = (PtrGetThemeEnumValue )themeLib.resolve("GetThemeEnumValue");
2637 pGetThemeFilename = (PtrGetThemeFilename )themeLib.resolve("GetThemeFilename");
2638 pGetThemeFont = (PtrGetThemeFont )themeLib.resolve("GetThemeFont");
2639 pGetThemeInt = (PtrGetThemeInt )themeLib.resolve("GetThemeInt");
2640 pGetThemeIntList = (PtrGetThemeIntList )themeLib.resolve("GetThemeIntList");
2641 pGetThemeMargins = (PtrGetThemeMargins )themeLib.resolve("GetThemeMargins");
2642 pGetThemeMetric = (PtrGetThemeMetric )themeLib.resolve("GetThemeMetric");
2643 pGetThemePartSize = (PtrGetThemePartSize )themeLib.resolve("GetThemePartSize");
2644 pGetThemePosition = (PtrGetThemePosition )themeLib.resolve("GetThemePosition");
2645 pGetThemeRect = (PtrGetThemeRect )themeLib.resolve("GetThemeRect");
2646 pGetThemeString = (PtrGetThemeString )themeLib.resolve("GetThemeString");
2647 pGetThemeTransitionDuration = (PtrGetThemeTransitionDuration)themeLib.resolve("GetThemeTransitionDuration");
2648 pGetThemePropertyOrigin = (PtrGetThemePropertyOrigin)themeLib.resolve("GetThemePropertyOrigin");
2650 return pGetThemeTransitionDuration != 0;
2654 * We need to set the windows "explorer" theme explicitly on a native
2655 * window and open the "TREEVIEW" theme handle passing its window handle
2656 * in order to get Vista-style item view themes (particulary drawBackground()
2657 * for selected items needs this).
2658 * We invoke a service of the native Windows interface to create
2659 * a non-visible window handle, open the theme on it and insert it into
2660 * the cache so that it is found by XPThemeData::handle() first.
2663 static inline HWND createTreeViewHelperWindow()
2665 if (QPlatformNativeInterface *ni = QGuiApplication::platformNativeInterface()) {
2667 void *wndProc = reinterpret_cast<void *>(DefWindowProc);
2668 if (QMetaObject::invokeMethod(ni, "createMessageWindow", Qt::DirectConnection,
2669 Q_RETURN_ARG(void *, hwnd),
2670 Q_ARG(QString, QStringLiteral("QTreeViewThemeHelperWindowClass")),
2671 Q_ARG(QString, QStringLiteral("QTreeViewThemeHelperWindow")),
2672 Q_ARG(void *, wndProc)) && hwnd) {
2673 return reinterpret_cast<HWND>(hwnd);
2679 bool QWindowsVistaStylePrivate::initTreeViewTheming()
2681 if (m_treeViewHelper)
2684 m_treeViewHelper = createTreeViewHelperWindow();
2685 if (!m_treeViewHelper) {
2686 qWarning("%s: Unable to create the treeview helper window.", Q_FUNC_INFO);
2689 const HRESULT hr = pSetWindowTheme(m_treeViewHelper, L"explorer", NULL);
2691 qErrnoWarning("%s: SetWindowTheme() failed.", Q_FUNC_INFO);
2694 return QWindowsXPStylePrivate::createTheme(QWindowsXPStylePrivate::TreeViewTheme, m_treeViewHelper);
2700 QIcon QWindowsVistaStyle::standardIconImplementation(StandardPixmap standardIcon,
2701 const QStyleOption *option,
2702 const QWidget *widget) const
2704 if (!QWindowsVistaStylePrivate::useVista()) {
2705 return QWindowsStyle::standardIconImplementation(standardIcon, option, widget);
2708 QWindowsVistaStylePrivate *d = const_cast<QWindowsVistaStylePrivate *>(d_func());
2709 switch(standardIcon) {
2710 case SP_CommandLink:
2712 XPThemeData theme(0, 0,
2713 QWindowsXPStylePrivate::ButtonTheme,
2714 BP_COMMANDLINKGLYPH, CMDLGS_NORMAL);
2715 if (theme.isValid()) {
2717 pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size);
2719 QPixmap pm = QPixmap(size.cx, size.cy);
2720 pm.fill(Qt::transparent);
2723 theme.rect = QRect(0, 0, size.cx, size.cy);
2724 d->drawBackground(theme);
2725 linkGlyph.addPixmap(pm, QIcon::Normal, QIcon::Off); // Normal
2726 pm.fill(Qt::transparent);
2728 theme.stateId = CMDLGS_PRESSED;
2729 d->drawBackground(theme);
2730 linkGlyph.addPixmap(pm, QIcon::Normal, QIcon::On); // Pressed
2731 pm.fill(Qt::transparent);
2733 theme.stateId = CMDLGS_HOT;
2734 d->drawBackground(theme);
2735 linkGlyph.addPixmap(pm, QIcon::Active, QIcon::Off); // Hover
2736 pm.fill(Qt::transparent);
2738 theme.stateId = CMDLGS_DISABLED;
2739 d->drawBackground(theme);
2740 linkGlyph.addPixmap(pm, QIcon::Disabled, QIcon::Off); // Disabled
2748 return QWindowsXPStyle::standardIconImplementation(standardIcon, option, widget);
2753 #endif //QT_NO_WINDOWSVISTA