1 /****************************************************************************
3 ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
6 ** This file is part of the QtGui module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
40 ****************************************************************************/
42 #include "qwindowsvistastyle.h"
43 #include "qwindowsvistastyle_p.h"
44 #include <private/qstylehelper_p.h>
45 #include <private/qsystemlibrary_p.h>
47 #if !defined(QT_NO_STYLE_WINDOWSVISTA) || defined(QT_PLUGIN)
51 static const int windowsItemFrame = 2; // menu item frame width
52 static const int windowsItemHMargin = 3; // menu item hor text margin
53 static const int windowsItemVMargin = 4; // menu item ver text margin
54 static const int windowsArrowHMargin = 6; // arrow horizontal margin
55 static const int windowsRightBorder = 15; // right border on windows
57 #ifndef TMT_CONTENTMARGINS
58 # define TMT_CONTENTMARGINS 3602
60 #ifndef TMT_SIZINGMARGINS
61 # define TMT_SIZINGMARGINS 3601
64 # define LISS_NORMAL 1
66 # define LISS_SELECTED 3
67 # define LISS_DISABLED 4
68 # define LISS_SELECTEDNOTFOCUS 5
69 # define LISS_HOTSELECTED 6
71 #ifndef BP_COMMANDLINK
72 # define BP_COMMANDLINK 6
73 # define BP_COMMANDLINKGLYPH 7
74 # define CMDLGS_NORMAL 1
76 # define CMDLGS_PRESSED 3
77 # define CMDLGS_DISABLED 4
79 #ifndef PP_TRANSPARENTBAR
80 # define PP_TRANSPARENTBAR 11
81 # define PP_TRANSPARENTBARVERT 12
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.
152 \warning This style is only available on the Windows Vista platform
153 because it makes use of Windows Vista's style engine.
155 \sa QMacStyle, QWindowsXPStyle, QPlastiqueStyle, QCleanlooksStyle, QMotifStyle
159 Constructs a QWindowsVistaStyle object.
161 QWindowsVistaStyle::QWindowsVistaStyle()
162 : QWindowsXPStyle(*new QWindowsVistaStylePrivate)
166 //convert Qt state flags to uxtheme button states
167 static int buttonStateId(int flags, int partId)
170 if (partId == BP_RADIOBUTTON || partId == BP_CHECKBOX) {
171 if (!(flags & QStyle::State_Enabled))
172 stateId = RBS_UNCHECKEDDISABLED;
173 else if (flags & QStyle::State_Sunken)
174 stateId = RBS_UNCHECKEDPRESSED;
175 else if (flags & QStyle::State_MouseOver)
176 stateId = RBS_UNCHECKEDHOT;
178 stateId = RBS_UNCHECKEDNORMAL;
180 if (flags & QStyle::State_On)
181 stateId += RBS_CHECKEDNORMAL-1;
183 } else if (partId == BP_PUSHBUTTON) {
184 if (!(flags & QStyle::State_Enabled))
185 stateId = PBS_DISABLED;
186 else if (flags & (QStyle::State_Sunken | QStyle::State_On))
187 stateId = PBS_PRESSED;
188 else if (flags & QStyle::State_MouseOver)
191 stateId = PBS_NORMAL;
198 void QWindowsVistaAnimation::paint(QPainter *painter, const QStyleOption *option)
206 Helperfunction to paint the current transition state between two
209 The result is a blended image consisting of ((alpha)*_primaryImage)
210 + ((1-alpha)*_secondaryImage)
213 void QWindowsVistaAnimation::drawBlendedImage(QPainter *painter, QRect rect, float alpha) {
214 if (_secondaryImage.isNull() || _primaryImage.isNull())
217 if (_tempImage.isNull())
218 _tempImage = _secondaryImage;
220 const int a = qRound(alpha*256);
221 const int ia = 256 - a;
222 const int sw = _primaryImage.width();
223 const int sh = _primaryImage.height();
224 const int bpl = _primaryImage.bytesPerLine();
225 switch(_primaryImage.depth()) {
228 uchar *mixed_data = _tempImage.bits();
229 const uchar *back_data = _primaryImage.bits();
230 const uchar *front_data = _secondaryImage.bits();
231 for (int sy = 0; sy < sh; sy++) {
232 quint32* mixed = (quint32*)mixed_data;
233 const quint32* back = (const quint32*)back_data;
234 const quint32* front = (const quint32*)front_data;
235 for (int sx = 0; sx < sw; sx++) {
236 quint32 bp = back[sx];
237 quint32 fp = front[sx];
238 mixed[sx] = qRgba ((qRed(bp)*ia + qRed(fp)*a)>>8,
239 (qGreen(bp)*ia + qGreen(fp)*a)>>8,
240 (qBlue(bp)*ia + qBlue(fp)*a)>>8,
241 (qAlpha(bp)*ia + qAlpha(fp)*a)>>8);
251 painter->drawImage(rect, _tempImage);
255 Paints a transition state. The result will be a mix between the
256 initial and final state of the transition, depending on the time
257 difference between _startTime and current time.
259 void QWindowsVistaTransition::paint(QPainter *painter, const QStyleOption *option)
263 QTime current = QTime::currentTime();
265 if (_startTime > current)
266 _startTime = current;
268 int timeDiff = _startTime.msecsTo(current);
269 alpha = timeDiff/(float)_duration;
270 if (timeDiff > _duration) {
278 drawBlendedImage(painter, option->rect, alpha);
282 Paints a pulse. The result will be a mix between the primary and
283 secondary pulse images depending on the time difference between
284 _startTime and current time.
286 void QWindowsVistaPulse::paint(QPainter *painter, const QStyleOption *option)
290 QTime current = QTime::currentTime();
292 if (_startTime > current)
293 _startTime = current;
295 int timeDiff = _startTime.msecsTo(current) % _duration*2;
296 if (timeDiff > _duration)
297 timeDiff = _duration*2 - timeDiff;
298 alpha = timeDiff/(float)_duration;
302 drawBlendedImage(painter, option->rect, alpha);
309 Animations are used for some state transitions on specific widgets.
311 Only one running animation can exist for a widget at any specific
312 time. Animations can be added through
313 QWindowsVistaStylePrivate::startAnimation(Animation *) and any
314 existing animation on a widget can be retrieved with
315 QWindowsVistaStylePrivate::widgetAnimation(Widget *).
317 Once an animation has been started,
318 QWindowsVistaStylePrivate::timerEvent(QTimerEvent *) will
319 continuously call update() on the widget until it is stopped,
320 meaning that drawPrimitive will be called many times until the
321 transition has completed. During this time, the result will be
322 retrieved by the Animation::paint(...) function and not by the style
325 To determine if a transition should occur, the style needs to know
326 the previous state of the widget as well as the current one. This is
327 solved by updating dynamic properties on the widget every time the
330 Transitions interrupting existing transitions should always be
331 smooth, so whenever a hover-transition is started on a pulsating
332 button, it uses the current frame of the pulse-animation as the
333 starting image for the hover transition.
336 void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOption *option,
337 QPainter *painter, const QWidget *widget) const
339 QWindowsVistaStylePrivate *d = const_cast<QWindowsVistaStylePrivate*>(d_func());
341 int state = option->state;
342 if (!QWindowsVistaStylePrivate::useVista()) {
343 QWindowsStyle::drawPrimitive(element, option, painter, widget);
350 if (widget && d->transitionsEnabled())
352 /* all widgets that supports state transitions : */
354 #ifndef QT_NO_LINEEDIT
355 (qobject_cast<const QLineEdit*>(widget) && element == PE_FrameLineEdit) ||
356 #endif // QT_NO_LINEEDIT
357 (qobject_cast<const QRadioButton*>(widget)&& element == PE_IndicatorRadioButton) ||
358 (qobject_cast<const QCheckBox*>(widget) && element == PE_IndicatorCheckBox) ||
359 (qobject_cast<const QGroupBox *>(widget)&& element == PE_IndicatorCheckBox) ||
360 (qobject_cast<const QToolButton*>(widget) && element == PE_PanelButtonBevel)
363 // Retrieve and update the dynamic properties tracking
364 // the previous state of the widget:
365 QWidget *w = const_cast<QWidget *> (widget);
366 int oldState = w->property("_q_stylestate").toInt();
367 oldRect = w->property("_q_stylerect").toRect();
369 w->setProperty("_q_stylestate", (int)option->state);
370 w->setProperty("_q_stylerect", w->rect());
372 bool doTransition = oldState &&
373 ((state & State_Sunken) != (oldState & State_Sunken) ||
374 (state & State_On) != (oldState & State_On) ||
375 (state & State_MouseOver) != (oldState & State_MouseOver));
377 if (oldRect != newRect ||
378 (state & State_Enabled) != (oldState & State_Enabled) ||
379 (state & State_Active) != (oldState & State_Active))
380 d->stopAnimation(widget);
382 #ifndef QT_NO_LINEEDIT
383 if (const QLineEdit *edit = qobject_cast<const QLineEdit *>(widget))
384 if (edit->isReadOnly() && element == PE_FrameLineEdit) // Do not animate read only line edits
385 doTransition = false;
386 #endif // QT_NO_LINEEDIT
390 // We create separate images for the initial and final transition states and store them in the
391 // Transition object.
392 QImage startImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
393 QImage endImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
394 QStyleOption opt = *option;
396 opt.rect.setRect(0, 0, option->rect.width(), option->rect.height());
397 opt.state = (QStyle::State)oldState;
399 QPainter startPainter(&startImage);
401 QWindowsVistaAnimation *anim = d->widgetAnimation(widget);
402 QWindowsVistaTransition *t = new QWindowsVistaTransition;
405 // If we have a running animation on the widget already, we will use that to paint the initial
406 // state of the new transition, this ensures a smooth transition from a current animation such as a
407 // pulsating default button into the intended target state.
410 proxy()->drawPrimitive(element, &opt, &startPainter, 0); // Note that the widget pointer is intentionally 0
411 else // this ensures that we do not recurse in the animation logic above
412 anim->paint(&startPainter, &opt);
414 d->startAnimation(t);
415 t->setStartImage(startImage);
417 // The end state of the transition is simply the result we would have painted
418 // if the style was not animated.
420 QPainter endPainter(&endImage);
422 QStyleOption opt2 = opt;
423 opt2.state = option->state;
424 proxy()->drawPrimitive(element, &opt2, &endPainter, 0); // Note that the widget pointer is intentionally 0
425 // this ensures that we do not recurse in the animation logic above
426 t->setEndImage(endImage);
434 //translate state flags to UXTHEME states :
435 if (element == PE_FrameLineEdit) {
436 theme = pOpenThemeData(0, L"Edit");
437 partId = EP_EDITBORDER_NOSCROLL;
439 if (oldState & State_MouseOver)
441 else if (oldState & State_HasFocus)
442 fromState = ETS_FOCUSED;
444 fromState = ETS_NORMAL;
446 if (state & State_MouseOver)
448 else if (state & State_HasFocus)
449 toState = ETS_FOCUSED;
451 toState = ETS_NORMAL;
454 theme = pOpenThemeData(0, L"Button");
455 if (element == PE_IndicatorRadioButton)
456 partId = BP_RADIOBUTTON;
457 else if (element == PE_IndicatorCheckBox)
458 partId = BP_CHECKBOX;
460 partId = BP_PUSHBUTTON;
462 fromState = buttonStateId(oldState, partId);
463 toState = buttonStateId(option->state, partId);
466 // Retrieve the transition time between the states from the system.
467 if (theme && pGetThemeTransitionDuration(theme, partId, fromState, toState,
468 TMT_TRANSITIONDURATIONS, &duration) == S_OK)
470 t->setDuration(duration);
472 t->setStartTime(QTime::currentTime());
475 } // End of animation part
478 QRect rect = option->rect;
481 case PE_IndicatorHeaderArrow:
482 if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) {
483 int stateId = HSAS_SORTEDDOWN;
484 if (header->sortIndicator & QStyleOptionHeader::SortDown)
485 stateId = HSAS_SORTEDUP; //note that the uxtheme sort down indicator is the inverse of ours
486 XPThemeData theme(widget, painter, QLatin1String("HEADER"), HP_HEADERSORTARROW, stateId, option->rect);
487 d->drawBackground(theme);
491 case PE_IndicatorBranch:
493 XPThemeData theme(d->treeViewHelper(), painter, QLatin1String("TREEVIEW"));
494 static int decoration_size = 0;
495 if (theme.isValid() && !decoration_size) {
497 pGetThemePartSize(theme.handle(), 0, TVP_HOTGLYPH, GLPS_OPENED, 0, TS_TRUE, &size);
498 decoration_size = qMax(size.cx, size.cy);
500 int mid_h = option->rect.x() + option->rect.width() / 2;
501 int mid_v = option->rect.y() + option->rect.height() / 2;
506 if (option->state & State_Children) {
507 int delta = decoration_size / 2;
508 theme.rect = QRect(bef_h - delta, bef_v - delta, decoration_size, decoration_size);
509 theme.partId = option->state & State_MouseOver ? TVP_HOTGLYPH : TVP_GLYPH;
510 theme.stateId = option->state & QStyle::State_Open ? GLPS_OPENED : GLPS_CLOSED;
511 if (option->direction == Qt::RightToLeft)
512 theme.mirrorHorizontally = true;
513 d->drawBackground(theme);
520 QBrush brush(option->palette.dark().color(), Qt::Dense4Pattern);
521 if (option->state & State_Item) {
522 if (option->direction == Qt::RightToLeft)
523 painter->fillRect(option->rect.left(), mid_v, bef_h - option->rect.left(), 1, brush);
525 painter->fillRect(aft_h, mid_v, option->rect.right() - aft_h + 1, 1, brush);
527 if (option->state & State_Sibling && option->rect.bottom() > aft_v)
528 painter->fillRect(mid_h, aft_v, 1, option->rect.bottom() - aft_v + 1, brush);
529 if (option->state & (State_Open | State_Children | State_Item | State_Sibling) && (bef_v > option->rect.y()))
530 painter->fillRect(mid_h, option->rect.y(), 1, bef_v - option->rect.y(), brush);
535 case PE_PanelButtonBevel:
536 case PE_IndicatorCheckBox:
537 case PE_IndicatorRadioButton:
539 if (QWindowsVistaAnimation *a = d->widgetAnimation(widget)) {
540 a->paint(painter, option);
542 QWindowsXPStyle::drawPrimitive(element, option, painter, widget);
549 int stateId = option->state & State_Active ? MB_ACTIVE : MB_INACTIVE;
550 XPThemeData theme(widget, painter, QLatin1String("MENU"), MENU_POPUPBORDERS, stateId, option->rect);
551 d->drawBackground(theme);
555 #ifndef QT_NO_TEXTEDIT
556 if (const QTextEdit *edit = qobject_cast<const QTextEdit*>(widget)) {
558 int stateId = ETS_NORMAL;
559 if (!(state & State_Enabled))
560 stateId = ETS_DISABLED;
561 else if (edit->isReadOnly())
562 stateId = ETS_READONLY;
563 else if (state & State_HasFocus)
564 stateId = ETS_SELECTED;
565 XPThemeData theme(widget, painter, QLatin1String("EDIT"), EP_EDITBORDER_HVSCROLL, stateId, option->rect);
566 // Since EP_EDITBORDER_HVSCROLL does not us borderfill, theme.noContent cannot be used for clipping
568 pGetThemeInt(theme.handle(), theme.partId, theme.stateId, TMT_BORDERSIZE, &borderSize);
569 QRegion clipRegion = option->rect;
570 QRegion content = option->rect.adjusted(borderSize, borderSize, -borderSize, -borderSize);
571 clipRegion ^= content;
572 painter->setClipRegion(clipRegion);
573 d->drawBackground(theme);
576 #endif // QT_NO_TEXTEDIT
577 QWindowsXPStyle::drawPrimitive(element, option, painter, widget);
580 case PE_PanelLineEdit:
581 if (const QStyleOptionFrame *panel = qstyleoption_cast<const QStyleOptionFrame *>(option)) {
583 bool usePalette = false;
584 bool isEnabled = option->state & State_Enabled;
585 uint resolve_mask = panel->palette.resolve();
587 //Since spin box and combo box includes a line edit we need to resolve the palette on the parent instead
588 #ifndef QT_NO_SPINBOX
589 if (QAbstractSpinBox *spinbox = qobject_cast<QAbstractSpinBox*>(widget->parentWidget()))
590 resolve_mask = spinbox->palette().resolve();
591 #endif // QT_NO_SPINBOX
593 if (resolve_mask & (1 << QPalette::Base)) {
594 // Base color is set for this widget, so use it
595 bg = panel->palette.brush(QPalette::Base);
599 painter->fillRect(panel->rect, bg);
601 int partId = EP_BACKGROUND;
602 int stateId = EBS_NORMAL;
604 stateId = EBS_DISABLED;
605 else if (state & State_ReadOnly)
606 stateId = EBS_READONLY;
607 else if (state & State_MouseOver)
610 XPThemeData theme(0, painter, QLatin1String("EDIT"), partId, stateId, rect);
611 if (!theme.isValid()) {
612 QWindowsStyle::drawPrimitive(element, option, painter, widget);
616 pGetThemeEnumValue( theme.handle(),
621 if( bgType == BT_IMAGEFILE ) {
622 d->drawBackground(theme);
624 QBrush fillColor = option->palette.brush(QPalette::Base);
626 PROPERTYORIGIN origin = PO_NOTFOUND;
627 pGetThemePropertyOrigin(theme.handle(), theme.partId, theme.stateId, TMT_FILLCOLOR, &origin);
628 // Use only if the fill property comes from our part
629 if ((origin == PO_PART || origin == PO_STATE)) {
631 pGetThemeColor(theme.handle(), partId, stateId, TMT_FILLCOLOR, &bgRef);
632 fillColor = QBrush(qRgb(GetRValue(bgRef), GetGValue(bgRef), GetBValue(bgRef)));
635 painter->fillRect(option->rect, fillColor);
638 if (panel->lineWidth > 0)
639 proxy()->drawPrimitive(PE_FrameLineEdit, panel, painter, widget);
644 case PE_FrameLineEdit:
645 if (QWindowsVistaAnimation *anim = d->widgetAnimation(widget)) {
646 anim->paint(painter, option);
648 QPainter *p = painter;
649 QWidget *parentWidget = 0;
651 parentWidget = widget->parentWidget();
653 parentWidget = parentWidget->parentWidget();
655 if (widget && widget->inherits("QLineEdit")
656 && parentWidget && parentWidget->inherits("QAbstractItemView")) {
657 // we try to check if this lineedit is a delegate on a QAbstractItemView-derived class.
658 QPen oldPen = p->pen();
659 // Inner white border
660 p->setPen(QPen(option->palette.base().color(), 1));
661 p->drawRect(option->rect.adjusted(1, 1, -2, -2));
663 p->setPen(QPen(option->palette.shadow().color(), 1));
664 p->drawRect(option->rect.adjusted(0, 0, -1, -1));
668 int stateId = ETS_NORMAL;
669 if (!(state & State_Enabled))
670 stateId = ETS_DISABLED;
671 else if (state & State_ReadOnly)
672 stateId = ETS_READONLY;
673 else if (state & State_MouseOver)
675 else if (state & State_HasFocus)
676 stateId = ETS_SELECTED;
677 XPThemeData theme(widget, painter, QLatin1String("EDIT"), EP_EDITBORDER_NOSCROLL, stateId, option->rect);
679 QRegion clipRegion = option->rect;
680 clipRegion -= option->rect.adjusted(2, 2, -2, -2);
681 painter->setClipRegion(clipRegion);
682 d->drawBackground(theme);
688 case PE_IndicatorToolBarHandle:
692 if (option->state & State_Horizontal) {
693 theme = XPThemeData(widget, painter, QLatin1String("REBAR"), RP_GRIPPER, ETS_NORMAL, option->rect.adjusted(0, 1, -2, -2));
694 rect = option->rect.adjusted(0, 1, 0, -2);
697 theme = XPThemeData(widget, painter, QLatin1String("REBAR"), RP_GRIPPERVERT, ETS_NORMAL, option->rect.adjusted(0, 1, -2, -2));
698 rect = option->rect.adjusted(1, 0, -1, 0);
702 d->drawBackground(theme);
706 case PE_IndicatorToolBarSeparator:
708 QPen pen = painter->pen();
710 painter->setPen(option->palette.background().color().darker(114));
711 if (option->state & State_Horizontal) {
712 int x1 = option->rect.center().x();
713 painter->drawLine(QPoint(x1, option->rect.top() + margin), QPoint(x1, option->rect.bottom() - margin));
715 int y1 = option->rect.center().y();
716 painter->drawLine(QPoint(option->rect.left() + margin, y1), QPoint(option->rect.right() - margin, y1));
718 painter->setPen(pen);
722 case PE_PanelTipLabel: {
723 XPThemeData theme(widget, painter, QLatin1String("TOOLTIP"), TTP_STANDARD, TTSS_NORMAL, option->rect);
724 d->drawBackground(theme);
728 case PE_PanelItemViewItem:
730 const QStyleOptionViewItemV4 *vopt;
731 const QAbstractItemView *view = qobject_cast<const QAbstractItemView *>(widget);
732 bool newStyle = true;
734 if (qobject_cast<const QTableView*>(widget))
737 if (newStyle && view && (vopt = qstyleoption_cast<const QStyleOptionViewItemV4 *>(option))) {
738 bool selected = vopt->state & QStyle::State_Selected;
739 bool hover = vopt->state & QStyle::State_MouseOver;
740 bool active = vopt->state & QStyle::State_Active;
742 if (vopt->features & QStyleOptionViewItemV2::Alternate)
743 painter->fillRect(vopt->rect, vopt->palette.alternateBase());
745 QPalette::ColorGroup cg = vopt->state & QStyle::State_Enabled
746 ? QPalette::Normal : QPalette::Disabled;
747 if (cg == QPalette::Normal && !(vopt->state & QStyle::State_Active))
748 cg = QPalette::Inactive;
750 QRect itemRect = subElementRect(QStyle::SE_ItemViewItemFocusRect, option, widget).adjusted(-1, 0, 1, 0);
751 itemRect.setTop(vopt->rect.top());
752 itemRect.setBottom(vopt->rect.bottom());
754 QSize sectionSize = itemRect.size();
755 if (vopt->showDecorationSelected)
756 sectionSize = vopt->rect.size();
758 if (view->selectionBehavior() == QAbstractItemView::SelectRows)
759 sectionSize.setWidth(vopt->rect.width());
760 if (view->selectionMode() == QAbstractItemView::NoSelection)
764 if (vopt->backgroundBrush.style() != Qt::NoBrush) {
765 const QPointF oldBrushOrigin = painter->brushOrigin();
766 painter->setBrushOrigin(vopt->rect.topLeft());
767 painter->fillRect(vopt->rect, vopt->backgroundBrush);
768 painter->setBrushOrigin(oldBrushOrigin);
771 if (hover || selected) {
772 if (sectionSize.width() > 0 && sectionSize.height() > 0) {
773 QString key = QString::fromLatin1("qvdelegate-%1-%2-%3-%4-%5").arg(sectionSize.width())
774 .arg(sectionSize.height()).arg(selected).arg(active).arg(hover);
775 if (!QPixmapCache::find(key, pixmap)) {
776 pixmap = QPixmap(sectionSize);
777 pixmap.fill(Qt::transparent);
780 if (selected && hover)
781 state = LISS_HOTSELECTED;
782 else if (selected && !active)
783 state = LISS_SELECTEDNOTFOCUS;
785 state = LISS_SELECTED;
789 QPainter pixmapPainter(&pixmap);
790 XPThemeData theme(d->treeViewHelper(), &pixmapPainter, QLatin1String("TREEVIEW"),
791 LVP_LISTITEM, state, QRect(0, 0, sectionSize.width(), sectionSize.height()));
792 if (theme.isValid()) {
793 d->drawBackground(theme);
795 QWindowsXPStyle::drawPrimitive(PE_PanelItemViewItem, option, painter, widget);
798 QPixmapCache::insert(key, pixmap);
802 if (vopt->showDecorationSelected) {
803 const int frame = 2; //Assumes a 2 pixel pixmap border
804 QRect srcRect = QRect(0, 0, sectionSize.width(), sectionSize.height());
805 QRect pixmapRect = vopt->rect;
806 bool reverse = vopt->direction == Qt::RightToLeft;
807 bool leftSection = vopt->viewItemPosition == QStyleOptionViewItemV4::Beginning;
808 bool rightSection = vopt->viewItemPosition == QStyleOptionViewItemV4::End;
809 if (vopt->viewItemPosition == QStyleOptionViewItemV4::OnlyOne
810 || vopt->viewItemPosition == QStyleOptionViewItemV4::Invalid)
811 painter->drawPixmap(pixmapRect.topLeft(), pixmap);
812 else if (reverse ? rightSection : leftSection){
813 painter->drawPixmap(QRect(pixmapRect.topLeft(),
814 QSize(frame, pixmapRect.height())), pixmap,
815 QRect(QPoint(0, 0), QSize(frame, pixmapRect.height())));
816 painter->drawPixmap(pixmapRect.adjusted(frame, 0, 0, 0),
817 pixmap, srcRect.adjusted(frame, 0, -frame, 0));
818 } else if (reverse ? leftSection : rightSection) {
819 painter->drawPixmap(QRect(pixmapRect.topRight() - QPoint(frame - 1, 0),
820 QSize(frame, pixmapRect.height())), pixmap,
821 QRect(QPoint(pixmapRect.width() - frame, 0),
822 QSize(frame, pixmapRect.height())));
823 painter->drawPixmap(pixmapRect.adjusted(0, 0, -frame, 0),
824 pixmap, srcRect.adjusted(frame, 0, -frame, 0));
825 } else if (vopt->viewItemPosition == QStyleOptionViewItemV4::Middle)
826 painter->drawPixmap(pixmapRect, pixmap,
827 srcRect.adjusted(frame, 0, -frame, 0));
829 if (vopt->text.isEmpty() && vopt->icon.isNull())
831 painter->drawPixmap(itemRect.topLeft(), pixmap);
835 QWindowsXPStyle::drawPrimitive(element, option, painter, widget);
841 const QDialogButtonBox *buttonBox = 0;
843 if (qobject_cast<const QMessageBox *> (widget))
844 buttonBox = widget->findChild<const QDialogButtonBox *>(QLatin1String("qt_msgbox_buttonbox"));
845 #ifndef QT_NO_INPUTDIALOG
846 else if (qobject_cast<const QInputDialog *> (widget))
847 buttonBox = widget->findChild<const QDialogButtonBox *>(QLatin1String("qt_inputdlg_buttonbox"));
848 #endif // QT_NO_INPUTDIALOG
851 //draw white panel part
852 XPThemeData theme(widget, painter, QLatin1String("TASKDIALOG"), TDLG_PRIMARYPANEL, 0, option->rect);
853 QRect toprect = option->rect;
854 toprect.setBottom(buttonBox->geometry().top());
855 theme.rect = toprect;
856 d->drawBackground(theme);
858 //draw bottom panel part
859 QRect buttonRect = option->rect;
860 buttonRect.setTop(buttonBox->geometry().top());
861 theme.rect = buttonRect;
862 theme.partId = TDLG_SECONDARYPANEL;
863 d->drawBackground(theme);
868 QWindowsXPStyle::drawPrimitive(element, option, painter, widget);
877 see drawPrimitive for comments on the animation support
879 void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption *option,
880 QPainter *painter, const QWidget *widget) const
882 QWindowsVistaStylePrivate *d = const_cast<QWindowsVistaStylePrivate*>(d_func());
884 if (!QWindowsVistaStylePrivate::useVista()) {
885 QWindowsStyle::drawControl(element, option, painter, widget);
889 bool selected = option->state & State_Selected;
890 bool pressed = option->state & State_Sunken;
891 bool disabled = !(option->state & State_Enabled);
893 int state = option->state;
896 QRect rect(option->rect);
897 State flags = option->state;
904 if (d->transitionsEnabled() && widget) {
905 if (const QStyleOptionButton *button = qstyleoption_cast<const QStyleOptionButton *>(option)) {
906 if ((qobject_cast<const QPushButton*>(widget) && element == CE_PushButtonBevel))
908 QWidget *w = const_cast<QWidget *> (widget);
909 int oldState = w->property("_q_stylestate").toInt();
910 oldRect = w->property("_q_stylerect").toRect();
912 w->setProperty("_q_stylestate", (int)option->state);
913 w->setProperty("_q_stylerect", w->rect());
915 bool wasDefault = w->property("_q_isdefault").toBool();
916 bool isDefault = button->features & QStyleOptionButton::DefaultButton;
917 w->setProperty("_q_isdefault", isDefault);
919 bool doTransition = ((state & State_Sunken) != (oldState & State_Sunken) ||
920 (state & State_On) != (oldState & State_On) ||
921 (state & State_MouseOver) != (oldState & State_MouseOver));
923 if (oldRect != newRect || (wasDefault && !isDefault))
925 doTransition = false;
926 d->stopAnimation(widget);
930 QImage startImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
931 QImage endImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
932 QWindowsVistaAnimation *anim = d->widgetAnimation(widget);
934 QStyleOptionButton opt = *button;
935 opt.state = (QStyle::State)oldState;
938 QWindowsVistaTransition *t = new QWindowsVistaTransition;
940 QPainter startPainter(&startImage);
943 proxy()->drawControl(element, &opt, &startPainter, 0 /* Intentional */);
945 anim->paint(&startPainter, &opt);
946 d->stopAnimation(widget);
949 t->setStartImage(startImage);
950 d->startAnimation(t);
953 QPainter endPainter(&endImage);
954 proxy()->drawControl(element, option, &endPainter, 0 /* Intentional */);
955 t->setEndImage(endImage);
957 HTHEME theme = pOpenThemeData(0, L"Button");
959 int fromState = buttonStateId(oldState, BP_PUSHBUTTON);
960 int toState = buttonStateId(option->state, BP_PUSHBUTTON);
961 if (pGetThemeTransitionDuration(theme, BP_PUSHBUTTON, fromState, toState, TMT_TRANSITIONDURATIONS, &duration) == S_OK)
962 t->setDuration(duration);
965 t->setStartTime(QTime::currentTime());
971 case CE_PushButtonBevel:
972 if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option))
975 QWindowsVistaAnimation *anim = d->widgetAnimation(widget);
976 if (anim && (btn->state & State_Enabled)) {
977 anim->paint(painter, option);
979 name = QLatin1String("BUTTON");
980 partId = BP_PUSHBUTTON;
981 if (btn->features & QStyleOptionButton::CommandLinkButton)
982 partId = BP_COMMANDLINK;
983 bool justFlat = (btn->features & QStyleOptionButton::Flat) && !(flags & (State_On|State_Sunken));
984 if (!(flags & State_Enabled) && !(btn->features & QStyleOptionButton::Flat))
985 stateId = PBS_DISABLED;
988 else if (flags & (State_Sunken | State_On))
989 stateId = PBS_PRESSED;
990 else if (flags & State_MouseOver)
992 else if (btn->features & QStyleOptionButton::DefaultButton && (state & State_Active))
993 stateId = PBS_DEFAULTED;
995 stateId = PBS_NORMAL;
999 if (widget && d->transitionsEnabled() && (btn->features & QStyleOptionButton::DefaultButton) &&
1000 !(state & (State_Sunken | State_On)) && !(state & State_MouseOver) &&
1001 (state & State_Enabled) && (state & State_Active))
1003 if (!anim && widget) {
1004 QImage startImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
1006 QImage alternateImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
1007 alternateImage.fill(0);
1009 QWindowsVistaPulse *pulse = new QWindowsVistaPulse;
1010 pulse->setWidget(const_cast<QWidget*>(widget));
1012 QPainter startPainter(&startImage);
1013 stateId = PBS_DEFAULTED;
1014 XPThemeData theme(widget, &startPainter, name, partId, stateId, rect);
1015 d->drawBackground(theme);
1017 QPainter alternatePainter(&alternateImage);
1018 theme.stateId = PBS_DEFAULTED_ANIMATING;
1019 theme.painter = &alternatePainter;
1020 d->drawBackground(theme);
1021 pulse->setPrimaryImage(startImage);
1022 pulse->setAlternateImage(alternateImage);
1023 pulse->setStartTime(QTime::currentTime());
1024 pulse->setDuration(2000);
1025 d->startAnimation(pulse);
1030 anim->paint(painter, option);
1032 XPThemeData theme(widget, painter, name, partId, stateId, rect);
1033 d->drawBackground(theme);
1037 d->stopAnimation(widget);
1038 XPThemeData theme(widget, painter, name, partId, stateId, rect);
1039 d->drawBackground(theme);
1043 if (btn->features & QStyleOptionButton::HasMenu) {
1044 int mbiw = 0, mbih = 0;
1045 XPThemeData theme(widget, 0, QLatin1String("TOOLBAR"), TP_DROPDOWNBUTTON);
1046 if (theme.isValid()) {
1048 if (pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size) == S_OK) {
1053 QRect ir = subElementRect(SE_PushButtonContents, option, 0);
1054 QStyleOptionButton newBtn = *btn;
1055 newBtn.rect = QStyle::visualRect(option->direction, option->rect,
1056 QRect(ir.right() - mbiw - 2,
1057 option->rect.top() + (option->rect.height()/2) - (mbih/2),
1058 mbiw + 1, mbih + 1));
1059 proxy()->drawPrimitive(PE_IndicatorArrowDown, &newBtn, painter, widget);
1064 #ifndef QT_NO_PROGRESSBAR
1065 case CE_ProgressBarGroove:
1067 Qt::Orientation orient = Qt::Horizontal;
1068 if (const QStyleOptionProgressBarV2 *pb2 = qstyleoption_cast<const QStyleOptionProgressBarV2 *>(option))
1069 orient = pb2->orientation;
1070 partId = (orient == Qt::Horizontal) ? PP_TRANSPARENTBAR : PP_TRANSPARENTBARVERT;
1071 name = QLatin1String("PROGRESS");
1074 XPThemeData theme(widget, painter, name, partId, stateId, rect);
1075 d->drawBackground(theme);
1078 case CE_ProgressBarContents:
1079 if (const QStyleOptionProgressBar *bar
1080 = qstyleoption_cast<const QStyleOptionProgressBar *>(option)) {
1081 bool isIndeterminate = (bar->minimum == 0 && bar->maximum == 0);
1082 bool vertical = false;
1083 bool inverted = false;
1084 if (const QStyleOptionProgressBarV2 *pb2 = qstyleoption_cast<const QStyleOptionProgressBarV2 *>(option)) {
1085 vertical = (pb2->orientation == Qt::Vertical);
1086 inverted = pb2->invertedAppearance;
1089 if (const QProgressBar *progressbar = qobject_cast<const QProgressBar *>(widget)) {
1090 if (isIndeterminate || (progressbar->value() > 0 && (progressbar->value() < progressbar->maximum()) && d->transitionsEnabled())) {
1091 if (!d->widgetAnimation(progressbar)) {
1092 QWindowsVistaAnimation *a = new QWindowsVistaAnimation;
1093 a->setWidget(const_cast<QWidget*>(widget));
1094 a->setStartTime(QTime::currentTime());
1095 d->startAnimation(a);
1098 d->stopAnimation(progressbar);
1102 XPThemeData theme(widget, painter, QLatin1String("PROGRESS"), vertical ? PP_FILLVERT : PP_FILL);
1103 theme.rect = option->rect;
1104 bool reverse = (bar->direction == Qt::LeftToRight && inverted) || (bar->direction == Qt::RightToLeft && !inverted);
1105 QTime current = QTime::currentTime();
1107 if (isIndeterminate) {
1108 if (QWindowsVistaAnimation *a = d->widgetAnimation(widget)) {
1110 int animationWidth = glowSize * 2 + (vertical ? theme.rect.height() : theme.rect.width());
1111 int animOffset = a->startTime().msecsTo(current) / 4;
1112 if (animOffset > animationWidth)
1113 a->setStartTime(QTime::currentTime());
1115 painter->setClipRect(theme.rect);
1117 QSize pixmapSize(14, 14);
1119 animRect = QRect(theme.rect.left(),
1120 inverted ? rect.top() - glowSize + animOffset :
1121 rect.bottom() + glowSize - animOffset,
1122 rect.width(), glowSize);
1123 pixmapSize.setHeight(animRect.height());
1125 animRect = QRect(rect.left() - glowSize + animOffset,
1126 rect.top(), glowSize, rect.height());
1127 animRect = QStyle::visualRect(reverse ? Qt::RightToLeft : Qt::LeftToRight,
1128 option->rect, animRect);
1129 pixmapSize.setWidth(animRect.width());
1131 QString name = QString::fromLatin1("qiprogress-%1-%2").arg(pixmapSize.width()).arg(pixmapSize.height());
1133 if (!QPixmapCache::find(name, pixmap)) {
1134 QImage image(pixmapSize, QImage::Format_ARGB32);
1135 image.fill(Qt::transparent);
1136 QPainter imagePainter(&image);
1137 theme.painter = &imagePainter;
1138 theme.partId = vertical ? PP_FILLVERT : PP_FILL;
1139 theme.rect = QRect(QPoint(0,0), theme.rect.size());
1140 QLinearGradient alphaGradient(0, 0, vertical ? 0 : image.width(),
1141 vertical ? image.height() : 0);
1142 alphaGradient.setColorAt(0, QColor(0, 0, 0, 0));
1143 alphaGradient.setColorAt(0.5, QColor(0, 0, 0, 220));
1144 alphaGradient.setColorAt(1, QColor(0, 0, 0, 0));
1145 imagePainter.fillRect(image.rect(), alphaGradient);
1146 imagePainter.setCompositionMode(QPainter::CompositionMode_SourceIn);
1147 d->drawBackground(theme);
1149 pixmap = QPixmap::fromImage(image);
1150 QPixmapCache::insert(name, pixmap);
1152 painter->drawPixmap(animRect, pixmap);
1157 qint64 progress = qMax<qint64>(bar->progress, bar->minimum); // workaround for bug in QProgressBar
1160 int maxHeight = option->rect.height();
1162 double vc6_workaround = ((progress - qint64(bar->minimum)) / qMax(double(1.0), double(qint64(bar->maximum) - qint64(bar->minimum))) * maxHeight);
1163 int height = isIndeterminate ? maxHeight: qMax(int(vc6_workaround), minHeight);
1164 theme.rect.setHeight(height);
1166 theme.rect.moveTop(rect.height() - theme.rect.height());
1168 int maxWidth = option->rect.width();
1170 double vc6_workaround = ((progress - qint64(bar->minimum)) / qMax(double(1.0), double(qint64(bar->maximum) - qint64(bar->minimum))) * maxWidth);
1171 int width = isIndeterminate ? maxWidth : qMax(int(vc6_workaround), minWidth);
1172 theme.rect.setWidth(width);
1173 theme.rect = QStyle::visualRect(reverse ? Qt::RightToLeft : Qt::LeftToRight,
1174 option->rect, theme.rect);
1176 d->drawBackground(theme);
1178 if (QWindowsVistaAnimation *a = d->widgetAnimation(widget)) {
1180 int animationWidth = glowSize * 2 + (vertical ? theme.rect.height() : theme.rect.width());
1181 int animOffset = a->startTime().msecsTo(current) / 4;
1182 theme.partId = vertical ? PP_MOVEOVERLAYVERT : PP_MOVEOVERLAY;
1183 if (animOffset > animationWidth) {
1184 if (bar->progress < bar->maximum)
1185 a->setStartTime(QTime::currentTime());
1187 d->stopAnimation(widget); //we stop the glow motion only after it has
1191 painter->setClipRect(theme.rect);
1193 theme.rect = QRect(theme.rect.left(),
1194 inverted ? rect.top() - glowSize + animOffset :
1195 rect.bottom() + glowSize - animOffset,
1196 rect.width(), glowSize);
1198 theme.rect = QRect(rect.left() - glowSize + animOffset,rect.top(), glowSize, rect.height());
1199 theme.rect = QStyle::visualRect(reverse ? Qt::RightToLeft : Qt::LeftToRight, option->rect, theme.rect);
1201 d->drawBackground(theme);
1207 #endif // QT_NO_PROGRESSBAR
1208 case CE_MenuBarItem:
1211 if (const QStyleOptionMenuItem *mbi = qstyleoption_cast<const QStyleOptionMenuItem *>(option))
1213 if (mbi->menuItemType == QStyleOptionMenuItem::DefaultItem)
1216 QPalette::ColorRole textRole = disabled ? QPalette::Text : QPalette::ButtonText;
1217 QPixmap pix = mbi->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize, option, widget), QIcon::Normal);
1219 uint alignment = Qt::AlignCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine;
1220 if (!proxy()->styleHint(SH_UnderlineShortcut, mbi, widget))
1221 alignment |= Qt::TextHideMnemonic;
1223 //The rect adjustment is a workaround for the menu not really filling its background.
1224 XPThemeData theme(widget, painter, QLatin1String("MENU"), MENU_BARBACKGROUND, 0, option->rect.adjusted(-1, 0, 2, 1));
1225 d->drawBackground(theme);
1227 int stateId = MBI_NORMAL;
1229 stateId = MBI_DISABLED;
1231 stateId = MBI_PUSHED;
1235 XPThemeData theme2(widget, painter, QLatin1String("MENU"), MENU_BARITEM, stateId, option->rect);
1236 d->drawBackground(theme2);
1239 drawItemPixmap(painter, mbi->rect, alignment, pix);
1241 drawItemText(painter, mbi->rect, alignment, mbi->palette, mbi->state & State_Enabled, mbi->text, textRole);
1247 if (const QStyleOptionMenuItem *menuitem = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) {
1248 // windows always has a check column, regardless whether we have an icon or not
1253 XPThemeData theme(widget, 0, QLatin1String("MENU"), MENU_POPUPCHECKBACKGROUND, MBI_HOT);
1254 pGetThemePartSize(theme.handle(), NULL, MENU_POPUPCHECK, 0, NULL,TS_TRUE, &size);
1255 pGetThemeMargins(theme.handle(), NULL, MENU_POPUPCHECK, 0, TMT_CONTENTMARGINS, NULL, &margins);
1256 checkcol = qMax(menuitem->maxIconWidth, int(3 + size.cx + margins.cxLeftWidth + margins.cxRightWidth));
1258 QRect rect = option->rect;
1260 //draw vertical menu line
1261 if (option->direction == Qt::LeftToRight)
1262 checkcol += rect.x();
1263 QPoint p1 = QStyle::visualPos(option->direction, menuitem->rect, QPoint(checkcol, rect.top()));
1264 QPoint p2 = QStyle::visualPos(option->direction, menuitem->rect, QPoint(checkcol, rect.bottom()));
1265 QRect gutterRect(p1.x(), p1.y(), 3, p2.y() - p1.y() + 1);
1266 XPThemeData theme2(widget, painter, QLatin1String("MENU"), MENU_POPUPGUTTER, stateId, gutterRect);
1267 d->drawBackground(theme2);
1270 menuitem->rect.getRect(&x, &y, &w, &h);
1271 int tab = menuitem->tabWidth;
1272 bool dis = !(menuitem->state & State_Enabled);
1273 bool checked = menuitem->checkType != QStyleOptionMenuItem::NotCheckable
1274 ? menuitem->checked : false;
1275 bool act = menuitem->state & State_Selected;
1277 if (menuitem->menuItemType == QStyleOptionMenuItem::Separator) {
1278 int yoff = y-2 + h / 2;
1279 QPoint p1 = QPoint(x + checkcol, yoff);
1280 QPoint p2 = QPoint(x + w + 6 , yoff);
1282 QRect subRect(p1.x(), p1.y(), p2.x() - p1.x(), 6);
1283 subRect = QStyle::visualRect(option->direction, option->rect, subRect );
1284 XPThemeData theme2(widget, painter, QLatin1String("MENU"), MENU_POPUPSEPARATOR, stateId, subRect);
1285 d->drawBackground(theme2);
1289 QRect vCheckRect = visualRect(option->direction, menuitem->rect, QRect(menuitem->rect.x(),
1290 menuitem->rect.y(), checkcol - 6, menuitem->rect.height()));
1293 stateId = dis ? MBI_DISABLED : MBI_HOT;
1294 XPThemeData theme2(widget, painter, QLatin1String("MENU"), MENU_POPUPITEM, stateId, option->rect);
1295 d->drawBackground(theme2);
1299 XPThemeData theme(widget, painter, QLatin1String("MENU"), MENU_POPUPCHECKBACKGROUND,
1300 menuitem->icon.isNull() ? MBI_HOT : MBI_PUSHED, vCheckRect);
1303 pGetThemePartSize(theme.handle(), NULL, MENU_POPUPCHECK, 0, NULL,TS_TRUE, &size);
1304 pGetThemeMargins(theme.handle(), NULL, MENU_POPUPCHECK, 0,
1305 TMT_CONTENTMARGINS, NULL, &margins);
1306 QRect checkRect(0, 0, size.cx + margins.cxLeftWidth + margins.cxRightWidth ,
1307 size.cy + margins.cyBottomHeight + margins.cyTopHeight);
1308 checkRect.moveCenter(vCheckRect.center());
1309 theme.rect = checkRect;
1311 d->drawBackground(theme);
1313 if (menuitem->icon.isNull()) {
1314 checkRect = QRect(0, 0, size.cx, size.cy);
1315 checkRect.moveCenter(theme.rect.center());
1316 theme.rect = checkRect;
1318 theme.partId = MENU_POPUPCHECK;
1319 bool bullet = menuitem->checkType & QStyleOptionMenuItem::Exclusive;
1321 theme.stateId = bullet ? MC_BULLETDISABLED: MC_CHECKMARKDISABLED;
1323 theme.stateId = bullet ? MC_BULLETNORMAL: MC_CHECKMARKNORMAL;
1324 d->drawBackground(theme);
1328 if (!menuitem->icon.isNull()) {
1329 QIcon::Mode mode = dis ? QIcon::Disabled : QIcon::Normal;
1331 mode = QIcon::Active;
1334 pixmap = menuitem->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize, option, widget), mode, QIcon::On);
1336 pixmap = menuitem->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize, option, widget), mode);
1337 int pixw = pixmap.width();
1338 int pixh = pixmap.height();
1339 QRect pmr(0, 0, pixw, pixh);
1340 pmr.moveCenter(vCheckRect.center());
1341 painter->setPen(menuitem->palette.text().color());
1342 painter->drawPixmap(pmr.topLeft(), pixmap);
1345 painter->setPen(menuitem->palette.buttonText().color());
1347 const QColor textColor = menuitem->palette.text().color();
1349 painter->setPen(textColor);
1351 int xm = windowsItemFrame + checkcol + windowsItemHMargin;
1352 int xpos = menuitem->rect.x() + xm;
1353 QRect textRect(xpos, y + windowsItemVMargin, w - xm - windowsRightBorder - tab + 1, h - 2 * windowsItemVMargin);
1354 QRect vTextRect = visualRect(option->direction, menuitem->rect, textRect);
1355 QString s = menuitem->text;
1356 if (!s.isEmpty()) { // draw text
1358 int t = s.indexOf(QLatin1Char('\t'));
1359 int text_flags = Qt::AlignVCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine;
1360 if (!proxy()->styleHint(SH_UnderlineShortcut, menuitem, widget))
1361 text_flags |= Qt::TextHideMnemonic;
1362 text_flags |= Qt::AlignLeft;
1364 QRect vShortcutRect = visualRect(option->direction, menuitem->rect,
1365 QRect(textRect.topRight(), QPoint(menuitem->rect.right(), textRect.bottom())));
1366 painter->drawText(vShortcutRect, text_flags, s.mid(t + 1));
1369 QFont font = menuitem->font;
1370 if (menuitem->menuItemType == QStyleOptionMenuItem::DefaultItem)
1372 painter->setFont(font);
1373 painter->setPen(textColor);
1374 painter->drawText(vTextRect, text_flags, s.left(t));
1377 if (menuitem->menuItemType == QStyleOptionMenuItem::SubMenu) {// draw sub menu arrow
1378 int dim = (h - 2 * windowsItemFrame) / 2;
1379 PrimitiveElement arrow;
1380 arrow = (option->direction == Qt::RightToLeft) ? PE_IndicatorArrowLeft : PE_IndicatorArrowRight;
1381 xpos = x + w - windowsArrowHMargin - windowsItemFrame - dim;
1382 QRect vSubMenuRect = visualRect(option->direction, menuitem->rect, QRect(xpos, y + h / 2 - dim / 2, dim, dim));
1383 QStyleOptionMenuItem newMI = *menuitem;
1384 newMI.rect = vSubMenuRect;
1385 newMI.state = dis ? State_None : State_Enabled;
1386 proxy()->drawPrimitive(arrow, &newMI, painter, widget);
1390 #endif // QT_NO_MENU
1391 case CE_HeaderSection:
1392 if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) {
1393 name = QLatin1String("HEADER");
1394 partId = HP_HEADERITEM;
1395 if (flags & State_Sunken)
1396 stateId = HIS_PRESSED;
1397 else if (flags & State_MouseOver)
1400 stateId = HIS_NORMAL;
1402 if (header->sortIndicator != QStyleOptionHeader::None)
1405 XPThemeData theme(widget, painter, name, partId, stateId, option->rect);
1406 d->drawBackground(theme);
1409 case CE_MenuBarEmptyArea:
1411 stateId = MBI_NORMAL;
1412 if (!(state & State_Enabled))
1413 stateId = MBI_DISABLED;
1414 XPThemeData theme(widget, painter, QLatin1String("MENU"), MENU_BARBACKGROUND, stateId, option->rect);
1415 d->drawBackground(theme);
1419 if (const QStyleOptionToolBar *toolbar = qstyleoption_cast<const QStyleOptionToolBar *>(option)) {
1420 QPalette pal = option->palette;
1421 pal.setColor(QPalette::Dark, option->palette.background().color().darker(130));
1422 QStyleOptionToolBar copyOpt = *toolbar;
1423 copyOpt.palette = pal;
1424 QWindowsStyle::drawControl(element, ©Opt, painter, widget);
1427 case CE_DockWidgetTitle:
1428 if (const QDockWidget *dockWidget = qobject_cast<const QDockWidget *>(widget)) {
1429 QRect rect = option->rect;
1430 if (dockWidget->isFloating()) {
1431 QWindowsXPStyle::drawControl(element, option, painter, widget);
1432 break; //otherwise fall through
1435 if (const QStyleOptionDockWidget *dwOpt = qstyleoption_cast<const QStyleOptionDockWidget *>(option)) {
1437 const QStyleOptionDockWidgetV2 *v2
1438 = qstyleoption_cast<const QStyleOptionDockWidgetV2*>(dwOpt);
1439 bool verticalTitleBar = v2 == 0 ? false : v2->verticalTitleBar;
1441 if (verticalTitleBar) {
1442 QSize s = rect.size();
1446 painter->translate(rect.left() - 1, rect.top() + rect.width());
1447 painter->rotate(-90);
1448 painter->translate(-rect.left() + 1, -rect.top());
1451 painter->setBrush(option->palette.background().color().darker(110));
1452 painter->setPen(option->palette.background().color().darker(130));
1453 painter->drawRect(rect.adjusted(0, 1, -1, -3));
1455 int buttonMargin = 4;
1456 int mw = proxy()->pixelMetric(QStyle::PM_DockWidgetTitleMargin, dwOpt, widget);
1457 int fw = proxy()->pixelMetric(PM_DockWidgetFrameWidth, dwOpt, widget);
1458 const QDockWidget *dw = qobject_cast<const QDockWidget *>(widget);
1459 bool isFloating = dw != 0 && dw->isFloating();
1461 QRect r = option->rect.adjusted(0, 2, -1, -3);
1462 QRect titleRect = r;
1464 if (dwOpt->closable) {
1465 QSize sz = standardIcon(QStyle::SP_TitleBarCloseButton, dwOpt, widget).actualSize(QSize(10, 10));
1466 titleRect.adjust(0, 0, -sz.width() - mw - buttonMargin, 0);
1469 if (dwOpt->floatable) {
1470 QSize sz = standardIcon(QStyle::SP_TitleBarMaxButton, dwOpt, widget).actualSize(QSize(10, 10));
1471 titleRect.adjust(0, 0, -sz.width() - mw - buttonMargin, 0);
1475 titleRect.adjust(0, -fw, 0, 0);
1476 if (widget != 0 && widget->windowIcon().cacheKey() != QApplication::windowIcon().cacheKey())
1477 titleRect.adjust(titleRect.height() + mw, 0, 0, 0);
1479 titleRect.adjust(mw, 0, 0, 0);
1480 if (!dwOpt->floatable && !dwOpt->closable)
1481 titleRect.adjust(0, 0, -mw, 0);
1483 if (!verticalTitleBar)
1484 titleRect = visualRect(dwOpt->direction, r, titleRect);
1486 if (!dwOpt->title.isEmpty()) {
1487 QString titleText = painter->fontMetrics().elidedText(dwOpt->title, Qt::ElideRight,
1488 verticalTitleBar ? titleRect.height() : titleRect.width());
1489 const int indent = painter->fontMetrics().descent();
1490 drawItemText(painter, rect.adjusted(indent + 1, 1, -indent - 1, -1),
1491 Qt::AlignLeft | Qt::AlignVCenter, dwOpt->palette,
1492 dwOpt->state & State_Enabled, titleText,
1493 QPalette::WindowText);
1498 #ifndef QT_NO_ITEMVIEWS
1499 case CE_ItemViewItem:
1501 const QStyleOptionViewItemV4 *vopt;
1502 const QAbstractItemView *view = qobject_cast<const QAbstractItemView *>(widget);
1503 bool newStyle = true;
1505 if (qobject_cast<const QTableView*>(widget))
1508 if (newStyle && view && (vopt = qstyleoption_cast<const QStyleOptionViewItemV4 *>(option))) {
1510 // We cannot currently get the correct selection color for "explorer style" views
1512 XPThemeData theme(d->treeViewHelper(), 0, QLatin1String("LISTVIEW"), 0, 0);
1513 unsigned int res = pGetThemeColor(theme.handle(), LVP_LISTITEM, LISS_SELECTED, TMT_TEXTCOLOR, &cref);
1514 QColor textColor(GetRValue(cref), GetGValue(cref), GetBValue(cref));
1516 QPalette palette = vopt->palette;
1517 palette.setColor(QPalette::All, QPalette::HighlightedText, palette.color(QPalette::Active, QPalette::Text));
1518 // Note that setting a saturated color here results in ugly XOR colors in the focus rect
1519 palette.setColor(QPalette::All, QPalette::Highlight, palette.base().color().darker(108));
1520 QStyleOptionViewItemV4 adjustedOption = *vopt;
1521 adjustedOption.palette = palette;
1522 // We hide the focusrect in singleselection as it is not required
1523 if ((view->selectionMode() == QAbstractItemView::SingleSelection)
1524 && !(vopt->state & State_KeyboardFocusChange))
1525 adjustedOption.state &= ~State_HasFocus;
1526 QWindowsXPStyle::drawControl(element, &adjustedOption, painter, widget);
1528 QWindowsXPStyle::drawControl(element, option, painter, widget);
1532 #endif // QT_NO_ITEMVIEWS
1535 QWindowsXPStyle::drawControl(element, option, painter, widget);
1543 see drawPrimitive for comments on the animation support
1546 void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyleOptionComplex *option,
1547 QPainter *painter, const QWidget *widget) const
1549 QWindowsVistaStylePrivate *d = const_cast<QWindowsVistaStylePrivate*>(d_func());
1550 if (!QWindowsVistaStylePrivate::useVista()) {
1551 QWindowsStyle::drawComplexControl(control, option, painter, widget);
1555 State state = option->state;
1556 SubControls sub = option->subControls;
1557 QRect r = option->rect;
1562 State flags = option->state;
1563 if (widget && widget->testAttribute(Qt::WA_UnderMouse) && widget->isActiveWindow())
1564 flags |= State_MouseOver;
1566 if (d->transitionsEnabled() && widget) {
1567 if ((qobject_cast<const QScrollBar *>(widget) && control == CC_ScrollBar)
1568 #ifndef QT_NO_SPINBOX
1569 || (qobject_cast<const QAbstractSpinBox*>(widget) && control == CC_SpinBox)
1570 #endif // QT_NO_SPINBOX
1571 #ifndef QT_NO_COMBOBOX
1572 || (qobject_cast<const QComboBox*>(widget) && control == CC_ComboBox)
1573 #endif // QT_NO_COMBOBOX
1576 QWidget *w = const_cast<QWidget *> (widget);
1578 int oldState = w->property("_q_stylestate").toInt();
1579 int oldActiveControls = w->property("_q_stylecontrols").toInt();
1580 QRect oldRect = w->property("_q_stylerect").toRect();
1581 w->setProperty("_q_stylestate", (int)option->state);
1582 w->setProperty("_q_stylecontrols", (int)option->activeSubControls);
1583 w->setProperty("_q_stylerect", w->rect());
1585 bool doTransition = ((state & State_Sunken) != (oldState & State_Sunken) ||
1586 (state & State_On) != (oldState & State_On) ||
1587 (state & State_MouseOver) != (oldState & State_MouseOver) ||
1588 oldActiveControls != option->activeSubControls);
1591 if (qstyleoption_cast<const QStyleOptionSlider *>(option)) {
1592 QRect oldSliderPos = w->property("_q_stylesliderpos").toRect();
1593 QRect currentPos = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget);
1594 w->setProperty("_q_stylesliderpos", currentPos);
1595 if (oldSliderPos != currentPos) {
1596 doTransition = false;
1597 d->stopAnimation(widget);
1599 } else if (control == CC_SpinBox) {
1600 //spinboxes have a transition when focus changes
1602 doTransition = (state & State_HasFocus) != (oldState & State_HasFocus);
1605 if (oldRect != option->rect) {
1606 doTransition = false;
1607 d->stopAnimation(widget);
1611 QImage startImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
1612 QImage endImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
1613 QWindowsVistaAnimation *anim = d->widgetAnimation(widget);
1614 QWindowsVistaTransition *t = new QWindowsVistaTransition;
1617 if (const QStyleOptionComboBox *combo = qstyleoption_cast<const QStyleOptionComboBox*>(option)) {
1618 //Combo boxes are special cased to avoid cleartype issues
1620 QPainter startPainter(&startImage);
1621 QStyleOptionComboBox startCombo = *combo;
1622 startCombo.state = (QStyle::State)oldState;
1623 startCombo.activeSubControls = (QStyle::SubControl)oldActiveControls;
1624 proxy()->drawComplexControl(control, &startCombo, &startPainter, 0 /* Intentional */);
1625 t->setStartImage(startImage);
1626 } else if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider*>(option)) {
1627 //This is a workaround for the direct3d engine as it currently has some issues with grabWindow
1629 QPainter startPainter(&startImage);
1630 QStyleOptionSlider startSlider = *slider;
1631 startSlider.state = (QStyle::State)oldState;
1632 startSlider.activeSubControls = (QStyle::SubControl)oldActiveControls;
1633 proxy()->drawComplexControl(control, &startSlider, &startPainter, 0 /* Intentional */);
1634 t->setStartImage(startImage);
1636 QPoint offset(0, 0);
1637 if (!widget->internalWinId())
1638 offset = widget->mapTo(widget->nativeParentWidget(), offset);
1639 t->setStartImage(QPixmap::grabWindow(widget->effectiveWinId(), offset.x(), offset.y(),
1640 option->rect.width(), option->rect.height()).toImage());
1644 QPainter startPainter(&startImage);
1645 anim->paint(&startPainter, option);
1646 t->setStartImage(startImage);
1648 d->startAnimation(t);
1650 QPainter endPainter(&endImage);
1651 proxy()->drawComplexControl(control, option, &endPainter, 0 /* Intentional */);
1652 t->setEndImage(endImage);
1653 t->setStartTime(QTime::currentTime());
1655 if (option->state & State_MouseOver || option->state & State_Sunken)
1656 t->setDuration(150);
1658 t->setDuration(500);
1661 if (QWindowsVistaAnimation *anim = d->widgetAnimation(widget)) {
1662 anim->paint(painter, option);
1671 if (const QStyleOptionComboBox *cmb = qstyleoption_cast<const QStyleOptionComboBox *>(option))
1673 if (cmb->editable) {
1674 if (sub & SC_ComboBoxEditField) {
1675 partId = EP_EDITBORDER_NOSCROLL;
1676 if (!(flags & State_Enabled))
1677 stateId = ETS_DISABLED;
1678 else if (flags & State_MouseOver)
1680 else if (flags & State_HasFocus)
1681 stateId = ETS_FOCUSED;
1683 stateId = ETS_NORMAL;
1685 XPThemeData theme(widget, painter, QLatin1String("EDIT"), partId, stateId, r);
1687 d->drawBackground(theme);
1689 if (sub & SC_ComboBoxArrow) {
1690 QRect subRect = proxy()->subControlRect(CC_ComboBox, option, SC_ComboBoxArrow, widget);
1691 XPThemeData theme(widget, painter, QLatin1String("COMBOBOX"));
1692 theme.rect = subRect;
1693 partId = option->direction == Qt::RightToLeft ? CP_DROPDOWNBUTTONLEFT : CP_DROPDOWNBUTTONRIGHT;
1695 if (!(cmb->state & State_Enabled))
1696 stateId = CBXS_DISABLED;
1697 else if (cmb->state & State_Sunken || cmb->state & State_On)
1698 stateId = CBXS_PRESSED;
1699 else if (cmb->state & State_MouseOver && option->activeSubControls & SC_ComboBoxArrow)
1702 stateId = CBXS_NORMAL;
1704 theme.partId = partId;
1705 theme.stateId = stateId;
1706 d->drawBackground(theme);
1710 if (sub & SC_ComboBoxFrame) {
1711 QStyleOptionButton btn;
1712 btn.QStyleOption::operator=(*option);
1713 btn.rect = option->rect.adjusted(-1, -1, 1, 1);
1714 if (sub & SC_ComboBoxArrow)
1715 btn.features = QStyleOptionButton::HasMenu;
1716 proxy()->drawControl(QStyle::CE_PushButton, &btn, painter, widget);
1722 if (const QStyleOptionSlider *scrollbar = qstyleoption_cast<const QStyleOptionSlider *>(option))
1724 XPThemeData theme(widget, painter, QLatin1String("SCROLLBAR"));
1726 bool maxedOut = (scrollbar->maximum == scrollbar->minimum);
1728 flags &= ~State_Enabled;
1730 bool isHorz = flags & State_Horizontal;
1731 bool isRTL = option->direction == Qt::RightToLeft;
1732 if (sub & SC_ScrollBarAddLine) {
1733 theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarAddLine, widget);
1734 partId = SBP_ARROWBTN;
1735 if (!(flags & State_Enabled))
1736 stateId = (isHorz ? (isRTL ? ABS_LEFTDISABLED : ABS_RIGHTDISABLED) : ABS_DOWNDISABLED);
1737 else if (scrollbar->activeSubControls & SC_ScrollBarAddLine && (scrollbar->state & State_Sunken))
1738 stateId = (isHorz ? (isRTL ? ABS_LEFTPRESSED : ABS_RIGHTPRESSED) : ABS_DOWNPRESSED);
1739 else if (scrollbar->activeSubControls & SC_ScrollBarAddLine && (scrollbar->state & State_MouseOver))
1740 stateId = (isHorz ? (isRTL ? ABS_LEFTHOT : ABS_RIGHTHOT) : ABS_DOWNHOT);
1741 else if (scrollbar->state & State_MouseOver)
1742 stateId = (isHorz ? (isRTL ? ABS_LEFTHOVER : ABS_RIGHTHOVER) : ABS_DOWNHOVER);
1744 stateId = (isHorz ? (isRTL ? ABS_LEFTNORMAL : ABS_RIGHTNORMAL) : ABS_DOWNNORMAL);
1745 theme.partId = partId;
1746 theme.stateId = stateId;
1747 d->drawBackground(theme);
1749 if (sub & SC_ScrollBarSubLine) {
1750 theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSubLine, widget);
1751 partId = SBP_ARROWBTN;
1752 if (!(flags & State_Enabled))
1753 stateId = (isHorz ? (isRTL ? ABS_RIGHTDISABLED : ABS_LEFTDISABLED) : ABS_UPDISABLED);
1754 else if (scrollbar->activeSubControls & SC_ScrollBarSubLine && (scrollbar->state & State_Sunken))
1755 stateId = (isHorz ? (isRTL ? ABS_RIGHTPRESSED : ABS_LEFTPRESSED) : ABS_UPPRESSED);
1756 else if (scrollbar->activeSubControls & SC_ScrollBarSubLine && (scrollbar->state & State_MouseOver))
1757 stateId = (isHorz ? (isRTL ? ABS_RIGHTHOT : ABS_LEFTHOT) : ABS_UPHOT);
1758 else if (scrollbar->state & State_MouseOver)
1759 stateId = (isHorz ? (isRTL ? ABS_RIGHTHOVER : ABS_LEFTHOVER) : ABS_UPHOVER);
1761 stateId = (isHorz ? (isRTL ? ABS_RIGHTNORMAL : ABS_LEFTNORMAL) : ABS_UPNORMAL);
1762 theme.partId = partId;
1763 theme.stateId = stateId;
1764 d->drawBackground(theme);
1767 theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget);
1768 theme.rect = theme.rect.united(proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSubPage, widget));
1769 theme.rect = theme.rect.united(proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarAddPage, widget));
1770 partId = flags & State_Horizontal ? SBP_LOWERTRACKHORZ : SBP_LOWERTRACKVERT;
1771 stateId = SCRBS_DISABLED;
1772 theme.partId = partId;
1773 theme.stateId = stateId;
1774 d->drawBackground(theme);
1776 if (sub & SC_ScrollBarSubPage) {
1777 theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSubPage, widget);
1778 partId = flags & State_Horizontal ? SBP_UPPERTRACKHORZ : SBP_UPPERTRACKVERT;
1779 if (!(flags & State_Enabled))
1780 stateId = SCRBS_DISABLED;
1781 else if (scrollbar->activeSubControls & SC_ScrollBarSubPage && (scrollbar->state & State_Sunken))
1782 stateId = SCRBS_PRESSED;
1783 else if (scrollbar->activeSubControls & SC_ScrollBarSubPage && (scrollbar->state & State_MouseOver))
1784 stateId = SCRBS_HOT;
1786 stateId = SCRBS_NORMAL;
1787 theme.partId = partId;
1788 theme.stateId = stateId;
1789 d->drawBackground(theme);
1791 if (sub & SC_ScrollBarAddPage) {
1792 theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarAddPage, widget);
1793 partId = flags & State_Horizontal ? SBP_LOWERTRACKHORZ : SBP_LOWERTRACKVERT;
1794 if (!(flags & State_Enabled))
1795 stateId = SCRBS_DISABLED;
1796 else if (scrollbar->activeSubControls & SC_ScrollBarAddPage && (scrollbar->state & State_Sunken))
1797 stateId = SCRBS_PRESSED;
1798 else if (scrollbar->activeSubControls & SC_ScrollBarAddPage && (scrollbar->state & State_MouseOver))
1799 stateId = SCRBS_HOT;
1801 stateId = SCRBS_NORMAL;
1802 theme.partId = partId;
1803 theme.stateId = stateId;
1804 d->drawBackground(theme);
1806 if (sub & SC_ScrollBarSlider) {
1807 theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget);
1808 if (!(flags & State_Enabled))
1809 stateId = SCRBS_DISABLED;
1810 else if (scrollbar->activeSubControls & SC_ScrollBarSlider && (scrollbar->state & State_Sunken))
1811 stateId = SCRBS_PRESSED;
1812 else if (scrollbar->activeSubControls & SC_ScrollBarSlider && (scrollbar->state & State_MouseOver))
1813 stateId = SCRBS_HOT;
1814 else if (option->state & State_MouseOver)
1815 stateId = SCRBS_HOVER;
1817 stateId = SCRBS_NORMAL;
1820 theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget);
1821 theme.partId = flags & State_Horizontal ? SBP_THUMBBTNHORZ : SBP_THUMBBTNVERT;
1822 theme.stateId = stateId;
1823 d->drawBackground(theme);
1825 // Calculate rect of gripper
1826 const int swidth = theme.rect.width();
1827 const int sheight = theme.rect.height();
1829 MARGINS contentsMargin;
1830 RECT rect = theme.toRECT(theme.rect);
1831 pGetThemeMargins(theme.handle(), 0, theme.partId, theme.stateId, TMT_SIZINGMARGINS, &rect, &contentsMargin);
1834 theme.partId = flags & State_Horizontal ? SBP_GRIPPERHORZ : SBP_GRIPPERVERT;
1835 pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size);
1836 int gw = size.cx, gh = size.cy;
1838 if (QSysInfo::WindowsVersion < QSysInfo::WV_WINDOWS8) {
1839 QRect gripperBounds;
1840 if (flags & State_Horizontal && ((swidth - contentsMargin.cxLeftWidth - contentsMargin.cxRightWidth) > gw)) {
1841 gripperBounds.setLeft(theme.rect.left() + swidth/2 - gw/2);
1842 gripperBounds.setTop(theme.rect.top() + sheight/2 - gh/2);
1843 gripperBounds.setWidth(gw);
1844 gripperBounds.setHeight(gh);
1845 } else if ((sheight - contentsMargin.cyTopHeight - contentsMargin.cyBottomHeight) > gh) {
1846 gripperBounds.setLeft(theme.rect.left() + swidth/2 - gw/2);
1847 gripperBounds.setTop(theme.rect.top() + sheight/2 - gh/2);
1848 gripperBounds.setWidth(gw);
1849 gripperBounds.setHeight(gh);
1852 // Draw gripper if there is enough space
1853 if (!gripperBounds.isEmpty() && flags & State_Enabled) {
1855 XPThemeData grippBackground = theme;
1856 grippBackground.partId = flags & State_Horizontal ? SBP_LOWERTRACKHORZ : SBP_LOWERTRACKVERT;
1857 theme.rect = gripperBounds;
1858 painter->setClipRegion(d->region(theme));// Only change inside the region of the gripper
1859 d->drawBackground(grippBackground);// The gutter is the grippers background
1860 d->drawBackground(theme); // Transparent gripper ontop of background
1868 #ifndef QT_NO_SPINBOX
1870 if (const QStyleOptionSpinBox *sb = qstyleoption_cast<const QStyleOptionSpinBox *>(option))
1872 XPThemeData theme(widget, painter, QLatin1String("SPIN"));
1873 if (sb->frame && (sub & SC_SpinBoxFrame)) {
1874 partId = EP_EDITBORDER_NOSCROLL;
1875 if (!(flags & State_Enabled))
1876 stateId = ETS_DISABLED;
1877 else if (flags & State_MouseOver)
1879 else if (flags & State_HasFocus)
1880 stateId = ETS_SELECTED;
1882 stateId = ETS_NORMAL;
1884 XPThemeData ftheme(widget, painter, QLatin1String("EDIT"), partId, stateId, r);
1885 ftheme.noContent = true;
1886 d->drawBackground(ftheme);
1888 if (sub & SC_SpinBoxUp) {
1889 theme.rect = proxy()->subControlRect(CC_SpinBox, option, SC_SpinBoxUp, widget).adjusted(0, 0, 0, 1);
1891 if (!(sb->stepEnabled & QAbstractSpinBox::StepUpEnabled) || !(flags & State_Enabled))
1892 stateId = UPS_DISABLED;
1893 else if (sb->activeSubControls == SC_SpinBoxUp && (sb->state & State_Sunken))
1894 stateId = UPS_PRESSED;
1895 else if (sb->activeSubControls == SC_SpinBoxUp && (sb->state & State_MouseOver))
1898 stateId = UPS_NORMAL;
1899 theme.partId = partId;
1900 theme.stateId = stateId;
1901 d->drawBackground(theme);
1903 if (sub & SC_SpinBoxDown) {
1904 theme.rect = proxy()->subControlRect(CC_SpinBox, option, SC_SpinBoxDown, widget);
1906 if (!(sb->stepEnabled & QAbstractSpinBox::StepDownEnabled) || !(flags & State_Enabled))
1907 stateId = DNS_DISABLED;
1908 else if (sb->activeSubControls == SC_SpinBoxDown && (sb->state & State_Sunken))
1909 stateId = DNS_PRESSED;
1910 else if (sb->activeSubControls == SC_SpinBoxDown && (sb->state & State_MouseOver))
1913 stateId = DNS_NORMAL;
1914 theme.partId = partId;
1915 theme.stateId = stateId;
1916 d->drawBackground(theme);
1920 #endif // QT_NO_SPINBOX
1922 QWindowsXPStyle::drawComplexControl(control, option, painter, widget);
1930 QSize QWindowsVistaStyle::sizeFromContents(ContentsType type, const QStyleOption *option,
1931 const QSize &size, const QWidget *widget) const
1933 if (!QWindowsVistaStylePrivate::useVista())
1934 return QWindowsStyle::sizeFromContents(type, option, size, widget);
1939 sz = QWindowsXPStyle::sizeFromContents(type, option, size, widget);
1944 XPThemeData theme(widget, 0, QLatin1String("MENU"), MENU_POPUPCHECKBACKGROUND, MBI_HOT);
1945 pGetThemePartSize(theme.handle(), NULL, MENU_POPUPCHECK, 0, NULL,TS_TRUE, &size);
1946 pGetThemeMargins(theme.handle(), NULL, MENU_POPUPCHECK, 0, TMT_CONTENTMARGINS, NULL, &margins);
1947 minimumHeight = qMax<qint32>(size.cy + margins.cyBottomHeight+ margins.cyTopHeight, sz.height());
1948 sz.rwidth() += size.cx + margins.cxLeftWidth + margins.cxRightWidth;
1951 if (const QStyleOptionMenuItem *menuitem = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) {
1952 if (menuitem->menuItemType != QStyleOptionMenuItem::Separator)
1953 sz.setHeight(minimumHeight);
1956 #ifndef QT_NO_MENUBAR
1957 case CT_MenuBarItem:
1959 sz += QSize(windowsItemHMargin * 5 + 1, 5);
1963 case CT_ItemViewItem:
1964 sz = QWindowsXPStyle::sizeFromContents(type, option, size, widget);
1969 //Spinbox adds frame twice
1970 sz = QWindowsStyle::sizeFromContents(type, option, size, widget);
1971 int border = proxy()->pixelMetric(PM_SpinBoxFrameWidth, option, widget);
1972 sz -= QSize(2*border, 2*border);
1978 return QWindowsXPStyle::sizeFromContents(type, option, size, widget);
1984 QRect QWindowsVistaStyle::subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const
1986 if (!QWindowsVistaStylePrivate::useVista())
1987 return QWindowsStyle::subElementRect(element, option, widget);
1989 QRect rect = QWindowsXPStyle::subElementRect(element, option, widget);
1992 case SE_PushButtonContents:
1993 if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) {
1995 HTHEME theme = pOpenThemeData(widget ? QWindowsVistaStylePrivate::winId(widget) : 0, L"Button");
1997 int stateId = PBS_NORMAL;
1998 if (!(option->state & State_Enabled))
1999 stateId = PBS_DISABLED;
2000 else if (option->state & State_Sunken)
2001 stateId = PBS_PRESSED;
2002 else if (option->state & State_MouseOver)
2004 else if (btn->features & QStyleOptionButton::DefaultButton)
2005 stateId = PBS_DEFAULTED;
2007 int border = proxy()->pixelMetric(PM_DefaultFrameWidth, btn, widget);
2008 rect = option->rect.adjusted(border, border, -border, -border);
2010 int result = pGetThemeMargins(theme,
2018 if (result == S_OK) {
2019 rect.adjust(borderSize.cxLeftWidth, borderSize.cyTopHeight,
2020 -borderSize.cxRightWidth, -borderSize.cyBottomHeight);
2021 rect = visualRect(option->direction, option->rect, rect);
2027 case SE_HeaderArrow:
2030 int h = option->rect.height();
2031 int w = option->rect.width();
2032 int x = option->rect.x();
2033 int y = option->rect.y();
2034 int margin = proxy()->pixelMetric(QStyle::PM_HeaderMargin, option, widget);
2036 XPThemeData theme(widget, 0, QLatin1String("HEADER"), HP_HEADERSORTARROW, HSAS_SORTEDDOWN, option->rect);
2038 int arrowWidth = 13;
2039 int arrowHeight = 5;
2040 if (theme.isValid()) {
2042 if (pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size) == S_OK) {
2043 arrowWidth = size.cx;
2044 arrowHeight = size.cy;
2047 if (option->state & State_Horizontal) {
2048 r.setRect(x + w/2 - arrowWidth/2, y , arrowWidth, arrowHeight);
2050 int vert_size = w / 2;
2051 r.setRect(x + 5, y + h - margin * 2 - vert_size,
2052 w - margin * 2 - 5, vert_size);
2054 rect = visualRect(option->direction, option->rect, r);
2058 case SE_HeaderLabel:
2060 int margin = proxy()->pixelMetric(QStyle::PM_HeaderMargin, option, widget);
2061 QRect r = option->rect;
2062 r.setRect(option->rect.x() + margin, option->rect.y() + margin,
2063 option->rect.width() - margin * 2, option->rect.height() - margin * 2);
2064 if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) {
2065 // Subtract width needed for arrow, if there is one
2066 if (header->sortIndicator != QStyleOptionHeader::None) {
2067 if (!(option->state & State_Horizontal)) //horizontal arrows are positioned on top
2068 r.setHeight(r.height() - (option->rect.width() / 2) - (margin * 2));
2071 rect = visualRect(option->direction, option->rect, r);
2074 case SE_ProgressBarContents:
2075 rect = QCommonStyle::subElementRect(SE_ProgressBarGroove, option, widget);
2077 case SE_ItemViewItemDecoration:
2078 if (qstyleoption_cast<const QStyleOptionViewItemV4 *>(option))
2079 rect.adjust(-2, 0, 2, 0);
2081 case SE_ItemViewItemFocusRect:
2082 if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast<const QStyleOptionViewItemV4 *>(option)) {
2083 QRect textRect = subElementRect(QStyle::SE_ItemViewItemText, option, widget);
2084 QRect displayRect = subElementRect(QStyle::SE_ItemViewItemDecoration, option, widget);
2085 if (!vopt->icon.isNull())
2086 rect = textRect.united(displayRect);
2089 rect = rect.adjusted(1, 0, -1, 0);
2100 This function is used by subControlRect to check if a button
2101 should be drawn for the given subControl given a set of window flags.
2103 static bool buttonVisible(const QStyle::SubControl sc, const QStyleOptionTitleBar *tb){
2105 bool isMinimized = tb->titleBarState & Qt::WindowMinimized;
2106 bool isMaximized = tb->titleBarState & Qt::WindowMaximized;
2107 const uint flags = tb->titleBarFlags;
2108 bool retVal = false;
2110 case QStyle::SC_TitleBarContextHelpButton:
2111 if (flags & Qt::WindowContextHelpButtonHint)
2114 case QStyle::SC_TitleBarMinButton:
2115 if (!isMinimized && (flags & Qt::WindowMinimizeButtonHint))
2118 case QStyle::SC_TitleBarNormalButton:
2119 if (isMinimized && (flags & Qt::WindowMinimizeButtonHint))
2121 else if (isMaximized && (flags & Qt::WindowMaximizeButtonHint))
2124 case QStyle::SC_TitleBarMaxButton:
2125 if (!isMaximized && (flags & Qt::WindowMaximizeButtonHint))
2128 case QStyle::SC_TitleBarShadeButton:
2129 if (!isMinimized && flags & Qt::WindowShadeButtonHint)
2132 case QStyle::SC_TitleBarUnshadeButton:
2133 if (isMinimized && flags & Qt::WindowShadeButtonHint)
2136 case QStyle::SC_TitleBarCloseButton:
2137 if (flags & Qt::WindowSystemMenuHint)
2140 case QStyle::SC_TitleBarSysMenu:
2141 if (flags & Qt::WindowSystemMenuHint)
2152 int QWindowsVistaStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget,
2153 QStyleHintReturn *returnData) const
2155 QWindowsVistaStylePrivate *d = const_cast<QWindowsVistaStylePrivate*>(d_func());
2158 case SH_MessageBox_CenterButtons:
2161 case SH_ToolTip_Mask:
2163 if (QStyleHintReturnMask *mask = qstyleoption_cast<QStyleHintReturnMask*>(returnData)) {
2165 XPThemeData themeData(widget, 0, QLatin1String("TOOLTIP"), TTP_STANDARD, TTSS_NORMAL, option->rect);
2166 mask->region = d->region(themeData);
2170 case SH_Table_GridLineColor:
2172 ret = option->palette.color(QPalette::Base).darker(118).rgb();
2177 ret = QWindowsXPStyle::styleHint(hint, option, widget, returnData);
2187 QRect QWindowsVistaStyle::subControlRect(ComplexControl control, const QStyleOptionComplex *option,
2188 SubControl subControl, const QWidget *widget) const
2190 if (!QWindowsVistaStylePrivate::useVista())
2191 return QWindowsStyle::subControlRect(control, option, subControl, widget);
2193 QRect rect = QWindowsXPStyle::subControlRect(control, option, subControl, widget);
2195 #ifndef QT_NO_COMBOBOX
2197 if (const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
2198 int x = cb->rect.x(),
2200 wi = cb->rect.width(),
2201 he = cb->rect.height();
2203 int margin = cb->frame ? 3 : 0;
2204 int bmarg = cb->frame ? 2 : 0;
2205 int arrowButtonWidth = bmarg + 16;
2206 xpos += wi - arrowButtonWidth;
2208 switch (subControl) {
2209 case SC_ComboBoxFrame:
2212 case SC_ComboBoxArrow:
2213 rect.setRect(xpos, y , arrowButtonWidth, he);
2215 case SC_ComboBoxEditField:
2216 rect.setRect(x + margin, y + margin, wi - 2 * margin - 16, he - 2 * margin);
2218 case SC_ComboBoxListBoxPopup:
2224 rect = visualRect(cb->direction, cb->rect, rect);
2227 #endif // QT_NO_COMBOBOX
2229 if (const QStyleOptionTitleBar *tb = qstyleoption_cast<const QStyleOptionTitleBar *>(option)) {
2230 if (!buttonVisible(subControl, tb))
2232 const bool isToolTitle = false;
2233 const int height = tb->rect.height();
2234 const int width = tb->rect.width();
2235 int buttonWidth = GetSystemMetrics(SM_CXSIZE) - 4;
2237 const int frameWidth = proxy()->pixelMetric(PM_MdiSubWindowFrameWidth, option, widget);
2238 const bool sysmenuHint = (tb->titleBarFlags & Qt::WindowSystemMenuHint) != 0;
2239 const bool minimizeHint = (tb->titleBarFlags & Qt::WindowMinimizeButtonHint) != 0;
2240 const bool maximizeHint = (tb->titleBarFlags & Qt::WindowMaximizeButtonHint) != 0;
2241 const bool contextHint = (tb->titleBarFlags & Qt::WindowContextHelpButtonHint) != 0;
2242 const bool shadeHint = (tb->titleBarFlags & Qt::WindowShadeButtonHint) != 0;
2244 switch (subControl) {
2245 case SC_TitleBarLabel:
2246 rect = QRect(frameWidth, 0, width - (buttonWidth + frameWidth + 10), height);
2249 rect.adjust(0, 0, -buttonWidth - 3, 0);
2251 if (minimizeHint || maximizeHint)
2252 rect.adjust(0, 0, -buttonWidth - 2, 0);
2255 const int leftOffset = height - 8;
2256 rect.adjust(leftOffset, 0, 0, 4);
2259 rect.adjust(0, 0, -buttonWidth - 2, 0);
2261 rect.adjust(0, 0, -buttonWidth - 2, 0);
2263 rect.adjust(0, 0, -buttonWidth - 2, 0);
2265 rect.adjust(0, 0, -buttonWidth - 2, 0);
2267 rect.translate(0, 2);
2268 rect = visualRect(option->direction, option->rect, rect);
2270 case SC_TitleBarSysMenu:
2272 const int controlTop = 6;
2273 const int controlHeight = height - controlTop - 3;
2274 int iconExtent = proxy()->pixelMetric(PM_SmallIconSize);
2275 QSize iconSize = tb->icon.actualSize(QSize(iconExtent, iconExtent));
2276 if (tb->icon.isNull())
2277 iconSize = QSize(controlHeight, controlHeight);
2278 int hPad = (controlHeight - iconSize.height())/2;
2279 int vPad = (controlHeight - iconSize.width())/2;
2280 rect = QRect(frameWidth + hPad, controlTop + vPad, iconSize.width(), iconSize.height());
2281 rect.translate(0, 3);
2282 rect = visualRect(option->direction, option->rect, rect);
2299 bool QWindowsVistaStyle::event(QEvent *e)
2301 Q_D(QWindowsVistaStyle);
2302 switch (e->type()) {
2305 QTimerEvent *timerEvent = (QTimerEvent *)e;
2306 if (d->animationTimer.timerId() == timerEvent->timerId()) {
2316 return QWindowsXPStyle::event(e);
2322 QStyle::SubControl QWindowsVistaStyle::hitTestComplexControl(ComplexControl control, const QStyleOptionComplex *option,
2323 const QPoint &pos, const QWidget *widget) const
2325 if (!QWindowsVistaStylePrivate::useVista()) {
2326 return QWindowsStyle::hitTestComplexControl(control, option, pos, widget);
2328 return QWindowsXPStyle::hitTestComplexControl(control, option, pos, widget);
2334 int QWindowsVistaStyle::pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const
2336 if (!QWindowsVistaStylePrivate::useVista()) {
2337 return QWindowsStyle::pixelMetric(metric, option, widget);
2341 case PM_DockWidgetTitleBarButtonMargin:
2342 return int(QStyleHelper::dpiScaled(5.));
2343 case PM_ScrollBarSliderMin:
2344 return int(QStyleHelper::dpiScaled(18.));
2345 case PM_MenuHMargin:
2346 case PM_MenuVMargin:
2348 case PM_MenuPanelWidth:
2353 return QWindowsXPStyle::pixelMetric(metric, option, widget);
2359 QPalette QWindowsVistaStyle::standardPalette() const
2361 return QWindowsXPStyle::standardPalette();
2367 void QWindowsVistaStyle::polish(QApplication *app)
2369 QWindowsXPStyle::polish(app);
2375 void QWindowsVistaStyle::polish(QWidget *widget)
2377 QWindowsXPStyle::polish(widget);
2378 #ifndef QT_NO_LINEEDIT
2379 if (qobject_cast<QLineEdit*>(widget))
2380 widget->setAttribute(Qt::WA_Hover);
2382 #endif // QT_NO_LINEEDIT
2383 if (qobject_cast<QGroupBox*>(widget))
2384 widget->setAttribute(Qt::WA_Hover);
2385 else if (qobject_cast<QCommandLinkButton*>(widget)) {
2386 QFont buttonFont = widget->font();
2387 buttonFont.setFamily(QLatin1String("Segoe UI"));
2388 widget->setFont(buttonFont);
2390 else if (widget->inherits("QTipLabel")){
2391 //note that since tooltips are not reused
2392 //we do not have to care about unpolishing
2393 widget->setContentsMargins(3, 0, 4, 0);
2395 HTHEME theme = pOpenThemeData(widget ? QWindowsVistaStylePrivate::winId(widget) : 0, L"TOOLTIP");
2397 if (pGetThemeColor(theme, TTP_STANDARD, TTSS_NORMAL, TMT_TEXTCOLOR, &bgRef) == S_OK) {
2398 QColor textColor = QColor::fromRgb(bgRef);
2400 pal.setColor(QPalette::All, QPalette::ToolTipText, textColor);
2401 widget->setPalette(pal);
2404 } else if (qobject_cast<QMessageBox *> (widget)) {
2405 widget->setAttribute(Qt::WA_StyledBackground);
2406 QDialogButtonBox *buttonBox = widget->findChild<QDialogButtonBox *>(QLatin1String("qt_msgbox_buttonbox"));
2408 buttonBox->setContentsMargins(0, 9, 0, 0);
2410 #ifndef QT_NO_INPUTDIALOG
2411 else if (qobject_cast<QInputDialog *> (widget)) {
2412 widget->setAttribute(Qt::WA_StyledBackground);
2413 QDialogButtonBox *buttonBox = widget->findChild<QDialogButtonBox *>(QLatin1String("qt_inputdlg_buttonbox"));
2415 buttonBox->setContentsMargins(0, 9, 0, 0);
2417 #endif // QT_NO_INPUTDIALOG
2418 else if (QTreeView *tree = qobject_cast<QTreeView *> (widget)) {
2419 tree->viewport()->setAttribute(Qt::WA_Hover);
2421 else if (QListView *list = qobject_cast<QListView *> (widget)) {
2422 list->viewport()->setAttribute(Qt::WA_Hover);
2429 void QWindowsVistaStyle::unpolish(QWidget *widget)
2431 QWindowsXPStyle::unpolish(widget);
2433 QWindowsVistaStylePrivate *d = const_cast<QWindowsVistaStylePrivate*>(d_func());
2434 d->stopAnimation(widget);
2436 #ifndef QT_NO_LINEEDIT
2437 if (qobject_cast<QLineEdit*>(widget))
2438 widget->setAttribute(Qt::WA_Hover, false);
2440 #endif // QT_NO_LINEEDIT
2441 if (qobject_cast<QGroupBox*>(widget))
2442 widget->setAttribute(Qt::WA_Hover, false);
2443 else if (qobject_cast<QMessageBox *> (widget)) {
2444 widget->setAttribute(Qt::WA_StyledBackground, false);
2445 QDialogButtonBox *buttonBox = widget->findChild<QDialogButtonBox *>(QLatin1String("qt_msgbox_buttonbox"));
2447 buttonBox->setContentsMargins(0, 0, 0, 0);
2449 #ifndef QT_NO_INPUTDIALOG
2450 else if (qobject_cast<QInputDialog *> (widget)) {
2451 widget->setAttribute(Qt::WA_StyledBackground, false);
2452 QDialogButtonBox *buttonBox = widget->findChild<QDialogButtonBox *>(QLatin1String("qt_inputdlg_buttonbox"));
2454 buttonBox->setContentsMargins(0, 0, 0, 0);
2456 #endif // QT_NO_INPUTDIALOG
2457 else if (QTreeView *tree = qobject_cast<QTreeView *> (widget)) {
2458 tree->viewport()->setAttribute(Qt::WA_Hover, false);
2459 } else if (qobject_cast<QCommandLinkButton*>(widget)) {
2460 QFont font = QApplication::font("QCommandLinkButton");
2461 QFont widgetFont = widget->font();
2462 widgetFont.setFamily(font.family()); //Only family set by polish
2463 widget->setFont(widgetFont);
2471 void QWindowsVistaStyle::unpolish(QApplication *app)
2473 QWindowsXPStyle::unpolish(app);
2479 void QWindowsVistaStyle::polish(QPalette &pal)
2481 QWindowsStyle::polish(pal);
2482 pal.setBrush(QPalette::AlternateBase, pal.base().color().darker(104));
2488 QPixmap QWindowsVistaStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *option,
2489 const QWidget *widget) const
2491 if (!QWindowsVistaStylePrivate::useVista()) {
2492 return QWindowsStyle::standardPixmap(standardPixmap, option, widget);
2494 return QWindowsXPStyle::standardPixmap(standardPixmap, option, widget);
2497 QWindowsVistaStylePrivate::QWindowsVistaStylePrivate() :
2498 QWindowsXPStylePrivate(), m_treeViewHelper(0)
2503 QWindowsVistaStylePrivate::~QWindowsVistaStylePrivate()
2505 qDeleteAll(animations);
2506 delete m_treeViewHelper;
2509 void QWindowsVistaStylePrivate::timerEvent()
2511 for (int i = animations.size() - 1 ; i >= 0 ; --i) {
2513 if (animations[i]->widget())
2514 animations[i]->widget()->update();
2516 if (!animations[i]->widget() ||
2517 !animations[i]->widget()->isVisible() ||
2518 animations[i]->widget()->window()->isMinimized() ||
2519 !animations[i]->running() ||
2520 !QWindowsVistaStylePrivate::useVista())
2522 QWindowsVistaAnimation *a = animations.takeAt(i);
2526 if (animations.size() == 0 && animationTimer.isActive()) {
2527 animationTimer.stop();
2531 void QWindowsVistaStylePrivate::stopAnimation(const QWidget *w)
2533 for (int i = animations.size() - 1 ; i >= 0 ; --i) {
2534 if (animations[i]->widget() == w) {
2535 QWindowsVistaAnimation *a = animations.takeAt(i);
2542 void QWindowsVistaStylePrivate::startAnimation(QWindowsVistaAnimation *t)
2544 Q_Q(QWindowsVistaStyle);
2545 stopAnimation(t->widget());
2546 animations.append(t);
2547 if (animations.size() > 0 && !animationTimer.isActive()) {
2548 animationTimer.start(45, q);
2552 bool QWindowsVistaStylePrivate::transitionsEnabled() const
2554 BOOL animEnabled = false;
2555 if (SystemParametersInfo(SPI_GETCLIENTAREAANIMATION, 0, &animEnabled, 0))
2564 QWindowsVistaAnimation * QWindowsVistaStylePrivate::widgetAnimation(const QWidget *widget) const
2568 foreach (QWindowsVistaAnimation *a, animations) {
2569 if (a->widget() == widget)
2577 Returns true if all the necessary theme engine symbols were
2580 bool QWindowsVistaStylePrivate::resolveSymbols()
2582 static bool tried = false;
2584 QSystemLibrary themeLib(QLatin1String("uxtheme"));
2585 pSetWindowTheme = (PtrSetWindowTheme )themeLib.resolve("SetWindowTheme");
2586 pIsThemePartDefined = (PtrIsThemePartDefined )themeLib.resolve("IsThemePartDefined");
2587 pGetThemePartSize = (PtrGetThemePartSize )themeLib.resolve("GetThemePartSize");
2588 pOpenThemeData = (PtrOpenThemeData )themeLib.resolve("OpenThemeData");
2589 pCloseThemeData = (PtrCloseThemeData )themeLib.resolve("CloseThemeData");
2590 pDrawThemeBackground = (PtrDrawThemeBackground )themeLib.resolve("DrawThemeBackground");
2591 pDrawThemeBackgroundEx = (PtrDrawThemeBackgroundEx )themeLib.resolve("DrawThemeBackgroundEx");
2592 pGetCurrentThemeName = (PtrGetCurrentThemeName )themeLib.resolve("GetCurrentThemeName");
2593 pGetThemeBool = (PtrGetThemeBool )themeLib.resolve("GetThemeBool");
2594 pGetThemeColor = (PtrGetThemeColor )themeLib.resolve("GetThemeColor");
2595 pGetThemeEnumValue = (PtrGetThemeEnumValue )themeLib.resolve("GetThemeEnumValue");
2596 pGetThemeFilename = (PtrGetThemeFilename )themeLib.resolve("GetThemeFilename");
2597 pGetThemeFont = (PtrGetThemeFont )themeLib.resolve("GetThemeFont");
2598 pGetThemeInt = (PtrGetThemeInt )themeLib.resolve("GetThemeInt");
2599 pGetThemeIntList = (PtrGetThemeIntList )themeLib.resolve("GetThemeIntList");
2600 pGetThemeMargins = (PtrGetThemeMargins )themeLib.resolve("GetThemeMargins");
2601 pGetThemeMetric = (PtrGetThemeMetric )themeLib.resolve("GetThemeMetric");
2602 pGetThemePartSize = (PtrGetThemePartSize )themeLib.resolve("GetThemePartSize");
2603 pGetThemePosition = (PtrGetThemePosition )themeLib.resolve("GetThemePosition");
2604 pGetThemeRect = (PtrGetThemeRect )themeLib.resolve("GetThemeRect");
2605 pGetThemeString = (PtrGetThemeString )themeLib.resolve("GetThemeString");
2606 pGetThemeTransitionDuration = (PtrGetThemeTransitionDuration)themeLib.resolve("GetThemeTransitionDuration");
2607 pGetThemePropertyOrigin = (PtrGetThemePropertyOrigin)themeLib.resolve("GetThemePropertyOrigin");
2610 return pGetThemeTransitionDuration != 0;
2614 * We need to set the windows explorer theme explicitly on a native widget
2615 * in order to get Vista-style item view themes
2617 QWidget *QWindowsVistaStylePrivate::treeViewHelper()
2619 if (!m_treeViewHelper) {
2620 m_treeViewHelper = new QWidget(0);
2621 pSetWindowTheme(m_treeViewHelper->winId(), L"explorer", NULL);
2623 return m_treeViewHelper;
2630 QIcon QWindowsVistaStyle::standardIconImplementation(StandardPixmap standardIcon,
2631 const QStyleOption *option,
2632 const QWidget *widget) const
2634 if (!QWindowsVistaStylePrivate::useVista()) {
2635 return QWindowsStyle::standardIconImplementation(standardIcon, option, widget);
2638 QWindowsVistaStylePrivate *d = const_cast<QWindowsVistaStylePrivate *>(d_func());
2639 switch(standardIcon) {
2640 case SP_CommandLink:
2642 XPThemeData theme(0, 0, QLatin1String("BUTTON"), BP_COMMANDLINKGLYPH, CMDLGS_NORMAL);
2643 if (theme.isValid()) {
2645 pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size);
2647 QPixmap pm = QPixmap(size.cx, size.cy);
2648 pm.fill(Qt::transparent);
2651 theme.rect = QRect(0, 0, size.cx, size.cy);
2652 d->drawBackground(theme);
2653 linkGlyph.addPixmap(pm, QIcon::Normal, QIcon::Off); // Normal
2654 pm.fill(Qt::transparent);
2656 theme.stateId = CMDLGS_PRESSED;
2657 d->drawBackground(theme);
2658 linkGlyph.addPixmap(pm, QIcon::Normal, QIcon::On); // Pressed
2659 pm.fill(Qt::transparent);
2661 theme.stateId = CMDLGS_HOT;
2662 d->drawBackground(theme);
2663 linkGlyph.addPixmap(pm, QIcon::Active, QIcon::Off); // Hover
2664 pm.fill(Qt::transparent);
2666 theme.stateId = CMDLGS_DISABLED;
2667 d->drawBackground(theme);
2668 linkGlyph.addPixmap(pm, QIcon::Disabled, QIcon::Off); // Disabled
2676 return QWindowsXPStyle::standardIconImplementation(standardIcon, option, widget);
2681 #endif //QT_NO_WINDOWSVISTA