Widgets: No longer use deprecated QPixmap::grabWindow(),grabWidget().
[profile/ivi/qtbase.git] / src / widgets / styles / qwindowsvistastyle.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
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.
16 **
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.
20 **
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.
28 **
29 ** Other Usage
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.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qwindowsvistastyle.h"
43 #include "qwindowsvistastyle_p.h"
44 #include <qscreen.h>
45 #include <qwindow.h>
46 #include <private/qstylehelper_p.h>
47 #include <private/qsystemlibrary_p.h>
48 #include <private/qapplication_p.h>
49 #include <qplatformnativeinterface_qpa.h>
50
51 #if !defined(QT_NO_STYLE_WINDOWSVISTA) || defined(QT_PLUGIN)
52
53 QT_BEGIN_NAMESPACE
54
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
60
61 #ifndef TMT_CONTENTMARGINS
62 #  define TMT_CONTENTMARGINS 3602
63 #endif
64 #ifndef TMT_SIZINGMARGINS
65 #  define TMT_SIZINGMARGINS 3601
66 #endif
67 #ifndef LISS_NORMAL
68 #  define LISS_NORMAL 1
69 #  define LISS_HOT 2
70 #  define LISS_SELECTED 3
71 #  define LISS_DISABLED 4
72 #  define LISS_SELECTEDNOTFOCUS 5
73 #  define LISS_HOTSELECTED 6
74 #endif
75 #ifndef BP_COMMANDLINK
76 #  define BP_COMMANDLINK 6
77 #  define BP_COMMANDLINKGLYPH 7
78 #  define CMDLGS_NORMAL 1
79 #  define CMDLGS_HOT 2
80 #  define CMDLGS_PRESSED 3
81 #  define CMDLGS_DISABLED 4
82 #endif
83
84 // Runtime resolved theme engine function calls
85
86
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);
111
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;
134
135 /* \internal
136     Checks if we should use Vista style , or if we should
137     fall back to Windows style.
138 */
139 bool QWindowsVistaStylePrivate::useVista()
140 {
141     return (QWindowsVistaStylePrivate::useXP() &&
142             (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA &&
143              (QSysInfo::WindowsVersion & QSysInfo::WV_NT_based)));
144 }
145
146 /*!
147   \class QWindowsVistaStyle
148   \brief The QWindowsVistaStyle class provides a look and feel suitable for applications on Microsoft Windows Vista.
149   \since 4.3
150   \ingroup appearance
151   \inmodule QtWidgets
152
153   \warning This style is only available on the Windows Vista platform
154   because it makes use of Windows Vista's style engine.
155
156   \sa QMacStyle, QWindowsXPStyle, QPlastiqueStyle, QCleanlooksStyle, QMotifStyle
157 */
158
159 /*!
160   Constructs a QWindowsVistaStyle object.
161 */
162 QWindowsVistaStyle::QWindowsVistaStyle()
163     : QWindowsXPStyle(*new QWindowsVistaStylePrivate)
164 {
165 }
166
167 //convert Qt state flags to uxtheme button states
168 static int buttonStateId(int flags, int partId)
169 {
170     int stateId = 0;
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;
178         else
179             stateId = RBS_UNCHECKEDNORMAL;
180
181         if (flags & QStyle::State_On)
182             stateId += RBS_CHECKEDNORMAL-1;
183
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)
190             stateId = PBS_HOT;
191         else
192             stateId = PBS_NORMAL;
193     } else {
194         Q_ASSERT(1);
195     }
196     return stateId;
197 }
198
199 void QWindowsVistaAnimation::paint(QPainter *painter, const QStyleOption *option)
200 {
201     Q_UNUSED(option);
202     Q_UNUSED(painter);
203 }
204
205 /*! \internal
206
207   Helperfunction to paint the current transition state between two
208   animation frames.
209
210   The result is a blended image consisting of ((alpha)*_primaryImage)
211   + ((1-alpha)*_secondaryImage)
212
213 */
214 void QWindowsVistaAnimation::drawBlendedImage(QPainter *painter, QRect rect, float alpha) {
215     if (_secondaryImage.isNull() || _primaryImage.isNull())
216         return;
217
218     if (_tempImage.isNull())
219         _tempImage = _secondaryImage;
220
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()) {
227     case 32:
228         {
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);
243                 }
244                 mixed_data += bpl;
245                 back_data += bpl;
246                 front_data += bpl;
247             }
248         }
249     default:
250         break;
251     }
252     painter->drawImage(rect, _tempImage);
253 }
254
255 /*! \internal
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.
259 */
260 void QWindowsVistaTransition::paint(QPainter *painter, const QStyleOption *option)
261 {
262     float alpha = 1.0;
263     if (_duration > 0) {
264         QTime current = QTime::currentTime();
265
266         if (_startTime > current)
267             _startTime = current;
268
269         int timeDiff = _startTime.msecsTo(current);
270         alpha = timeDiff/(float)_duration;
271         if (timeDiff > _duration) {
272             _running = false;
273             alpha = 1.0;
274         }
275     }
276     else {
277         _running = false;
278     }
279     drawBlendedImage(painter, option->rect, alpha);
280 }
281
282 /*! \internal
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.
286 */
287 void QWindowsVistaPulse::paint(QPainter *painter, const QStyleOption *option)
288 {
289     float alpha = 1.0;
290     if (_duration > 0) {
291         QTime current = QTime::currentTime();
292
293         if (_startTime > current)
294             _startTime = current;
295
296         int timeDiff = _startTime.msecsTo(current) % _duration*2;
297         if (timeDiff > _duration)
298             timeDiff = _duration*2 - timeDiff;
299         alpha = timeDiff/(float)_duration;
300     } else {
301         _running = false;
302     }
303     drawBlendedImage(painter, option->rect, alpha);
304 }
305
306
307 /*!
308  \internal
309  
310   Animations are used for some state transitions on specific widgets.
311  
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 *).
317  
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
324   itself.
325  
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
329   function is called.
330  
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.
335  
336  */
337 void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOption *option,
338                                        QPainter *painter, const QWidget *widget) const
339 {
340     QWindowsVistaStylePrivate *d = const_cast<QWindowsVistaStylePrivate*>(d_func());
341
342     int state = option->state;
343     if (!QWindowsVistaStylePrivate::useVista()) {
344         QWindowsStyle::drawPrimitive(element, option, painter, widget);
345         return;
346     }
347
348     QRect oldRect;
349     QRect newRect;
350
351     if (widget && d->transitionsEnabled())
352     {
353         /* all widgets that supports state transitions : */
354         if (
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)
362         )
363         {
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();
369             newRect = w->rect();
370             w->setProperty("_q_stylestate", (int)option->state);
371             w->setProperty("_q_stylerect", w->rect());
372
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));
377
378             if (oldRect != newRect ||
379                 (state & State_Enabled) != (oldState & State_Enabled) ||
380                 (state & State_Active)  != (oldState & State_Active))
381                     d->stopAnimation(widget);
382
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
388
389             if (doTransition) {
390
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;
396
397                 opt.rect.setRect(0, 0, option->rect.width(), option->rect.height());
398                 opt.state = (QStyle::State)oldState;
399                 startImage.fill(0);
400                 QPainter startPainter(&startImage);
401
402                 QWindowsVistaAnimation *anim = d->widgetAnimation(widget);
403                 QWindowsVistaTransition *t = new QWindowsVistaTransition;
404                 t->setWidget(w);
405
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.
409
410                 if (!anim)
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);
414
415                 d->startAnimation(t);
416                 t->setStartImage(startImage);
417
418                 // The end state of the transition is simply the result we would have painted
419                 // if the style was not animated.
420
421                 QPainter endPainter(&endImage);
422                 endImage.fill(0);
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);
428
429                 HTHEME theme;
430                 int partId;
431                 int duration;
432                 int fromState = 0;
433                 int toState = 0;
434
435                 //translate state flags to UXTHEME states :
436                 if (element == PE_FrameLineEdit) {
437                     theme = pOpenThemeData(0, L"Edit");
438                     partId = EP_EDITBORDER_NOSCROLL;
439
440                     if (oldState & State_MouseOver)
441                         fromState = ETS_HOT;
442                     else if (oldState & State_HasFocus)
443                         fromState = ETS_FOCUSED;
444                     else
445                         fromState = ETS_NORMAL;
446
447                     if (state & State_MouseOver)
448                         toState = ETS_HOT;
449                     else if (state & State_HasFocus)
450                         toState = ETS_FOCUSED;
451                     else
452                         toState = ETS_NORMAL;
453
454                 } else {
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;
460                     else
461                         partId = BP_PUSHBUTTON;
462
463                     fromState = buttonStateId(oldState, partId);
464                     toState = buttonStateId(option->state, partId);
465                 }
466
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)
470                 {
471                     t->setDuration(duration);
472                 }
473                 t->setStartTime(QTime::currentTime());
474             }
475         }
476     } // End of animation part
477
478
479     QRect rect = option->rect;
480
481     switch (element) {
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);
491         }
492         break;
493
494     case PE_IndicatorBranch:
495         {
496             XPThemeData theme(0, painter, QWindowsXPStylePrivate::TreeViewTheme);
497             static int decoration_size = 0;
498             if (d->initTreeViewTheming() && theme.isValid() && !decoration_size) {
499                 SIZE size;
500                 pGetThemePartSize(theme.handle(), 0, TVP_HOTGLYPH, GLPS_OPENED, 0, TS_TRUE, &size);
501                 decoration_size = qMax(size.cx, size.cy);
502             }
503             int mid_h = option->rect.x() + option->rect.width() / 2;
504             int mid_v = option->rect.y() + option->rect.height() / 2;
505             int bef_h = mid_h;
506             int bef_v = mid_v;
507             int aft_h = mid_h;
508             int aft_v = mid_v;
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);
517                 bef_h -= delta + 2;
518                 bef_v -= delta + 2;
519                 aft_h += delta - 2;
520                 aft_v += delta - 2;
521             }
522 #if 0
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);
527                 else
528                     painter->fillRect(aft_h, mid_v, option->rect.right() - aft_h + 1, 1, brush);
529             }
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);
534 #endif
535         }
536         break;
537
538     case PE_PanelButtonBevel:
539     case PE_IndicatorCheckBox:
540     case PE_IndicatorRadioButton:
541         {
542             if (QWindowsVistaAnimation *a = d->widgetAnimation(widget)) {
543                 a->paint(painter, option);
544             } else {
545                 QWindowsXPStyle::drawPrimitive(element, option, painter, widget);
546             }
547         }
548         break;
549
550     case PE_FrameMenu:
551         {
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);
557         }
558         break;
559     case PE_Frame:
560 #ifndef QT_NO_TEXTEDIT
561         if (const QTextEdit *edit = qobject_cast<const QTextEdit*>(widget)) {
562             painter->save();
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
576                 int borderSize = 1;
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);
582             }
583             d->drawBackground(theme);
584             painter->restore();
585         } else
586 #endif // QT_NO_TEXTEDIT
587             QWindowsXPStyle::drawPrimitive(element, option, painter, widget);
588         break;
589
590     case PE_PanelLineEdit:
591         if (const QStyleOptionFrame *panel = qstyleoption_cast<const QStyleOptionFrame *>(option)) {
592             QBrush bg;
593             bool usePalette = false;
594             bool isEnabled = option->state & State_Enabled;
595             uint resolve_mask = panel->palette.resolve();
596             if (widget) {
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
604             }
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);
608                 usePalette = true;
609             }
610             if (usePalette) {
611                 painter->fillRect(panel->rect, bg);
612             } else {
613                 int partId = EP_BACKGROUND;
614                 int stateId = EBS_NORMAL;
615                 if (!isEnabled)
616                     stateId = EBS_DISABLED;
617                 else if (state & State_ReadOnly)
618                     stateId = EBS_READONLY;
619                 else if (state & State_MouseOver)
620                     stateId = EBS_HOT;
621
622                 XPThemeData theme(0, painter, QWindowsXPStylePrivate::EditTheme,
623                                   partId, stateId, rect);
624                 if (!theme.isValid()) {
625                     QWindowsStyle::drawPrimitive(element, option, painter, widget);
626                     return;
627                 }
628                 int bgType;
629                 pGetThemeEnumValue( theme.handle(),
630                                     partId,
631                                     stateId,
632                                     TMT_BGTYPE,
633                                     &bgType);
634                 if( bgType == BT_IMAGEFILE ) {
635                     d->drawBackground(theme);
636                 } else {
637                     QBrush fillColor = option->palette.brush(QPalette::Base);
638                     if (!isEnabled) {
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)) {
643                             COLORREF bgRef;
644                             pGetThemeColor(theme.handle(), partId, stateId, TMT_FILLCOLOR, &bgRef);
645                             fillColor = QBrush(qRgb(GetRValue(bgRef), GetGValue(bgRef), GetBValue(bgRef)));
646                         }
647                     }
648                     painter->fillRect(option->rect, fillColor);
649                 }
650             }
651             if (panel->lineWidth > 0)
652                 proxy()->drawPrimitive(PE_FrameLineEdit, panel, painter, widget);
653             return;
654         }
655         break;
656
657     case PE_FrameLineEdit:
658         if (QWindowsVistaAnimation *anim = d->widgetAnimation(widget)) {
659             anim->paint(painter, option);
660         } else {
661             QPainter *p = painter;
662             QWidget *parentWidget = 0;
663             if (widget) {
664                 parentWidget = widget->parentWidget();
665                 if (parentWidget)
666                     parentWidget = parentWidget->parentWidget();
667             }
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));
675                 // Outer dark border
676                 p->setPen(QPen(option->palette.shadow().color(), 1));
677                 p->drawRect(option->rect.adjusted(0, 0, -1, -1));
678                 p->setPen(oldPen);
679                 return;
680             } else {
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)
687                     stateId = ETS_HOT;
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);
693                 painter->save();
694                 QRegion clipRegion = option->rect;
695                 clipRegion -= option->rect.adjusted(2, 2, -2, -2);
696                 painter->setClipRegion(clipRegion);
697                 d->drawBackground(theme);
698                 painter->restore();
699             }
700         }
701         break;
702
703     case PE_IndicatorToolBarHandle:
704         {
705             XPThemeData theme;
706             QRect rect;
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);
712                 rect.setWidth(4);
713             } else {
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);
717                 rect.setHeight(4);
718             }
719             theme.rect = rect;
720             d->drawBackground(theme);
721         }
722         break;
723
724     case PE_IndicatorToolBarSeparator:
725         {
726             QPen pen = painter->pen();
727             int margin = 3;
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));
732             } else {
733                 int y1 = option->rect.center().y();
734                 painter->drawLine(QPoint(option->rect.left() + margin, y1), QPoint(option->rect.right() - margin, y1));
735             }
736             painter->setPen(pen);
737         }
738         break;
739
740     case PE_PanelTipLabel: {
741         XPThemeData theme(widget, painter,
742                           QWindowsXPStylePrivate::ToolTipTheme,
743                           TTP_STANDARD, TTSS_NORMAL, option->rect);
744         d->drawBackground(theme);
745         break;
746     }
747
748     case PE_PanelItemViewItem:
749         {
750             const QStyleOptionViewItemV4 *vopt;
751             const QAbstractItemView *view = qobject_cast<const QAbstractItemView *>(widget);
752             bool newStyle = true;
753
754             if (qobject_cast<const QTableView*>(widget))
755                 newStyle = false;
756
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;
761
762                 if (vopt->features & QStyleOptionViewItemV2::Alternate)
763                     painter->fillRect(vopt->rect, vopt->palette.alternateBase());
764
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;
769
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());
773
774                 QSize sectionSize = itemRect.size();
775                 if (vopt->showDecorationSelected)
776                     sectionSize = vopt->rect.size();
777
778                 if (view->selectionBehavior() == QAbstractItemView::SelectRows)
779                     sectionSize.setWidth(vopt->rect.width());
780                 if (view->selectionMode() == QAbstractItemView::NoSelection)
781                     hover = false;
782                 QPixmap pixmap;
783
784                 if (vopt->backgroundBrush.style() != Qt::NoBrush) {
785                     painter->setBrushOrigin(vopt->rect.topLeft());
786                     painter->fillRect(vopt->rect, vopt->backgroundBrush);
787                 }
788
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);
795
796                         int state;
797                         if (selected && hover)
798                             state = LISS_HOTSELECTED;
799                         else if (selected && !active)
800                             state = LISS_SELECTEDNOTFOCUS;
801                         else if (selected)
802                             state = LISS_SELECTED;
803                         else
804                             state = LISS_HOT;
805
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);
812                         } else {
813                             QWindowsXPStyle::drawPrimitive(PE_PanelItemViewItem, option, painter, widget);
814                             break;;
815                         }
816                         QPixmapCache::insert(key, pixmap);
817                     }
818
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));
845                     } else {
846                         if (vopt->text.isEmpty() && vopt->icon.isNull())
847                             break;
848                         painter->drawPixmap(itemRect.topLeft(), pixmap);
849                     }
850                 }
851             } else {
852                 QWindowsXPStyle::drawPrimitive(element, option, painter, widget);
853             }
854             break;
855         }
856     case PE_Widget:
857         {
858             const QDialogButtonBox *buttonBox = 0;
859
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
866
867             if (buttonBox) {
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);
876
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);
883             }
884         }
885         break;
886     default:
887         QWindowsXPStyle::drawPrimitive(element, option, painter, widget);
888         break;
889     }
890 }
891
892
893 /*!
894  \internal
895
896  see drawPrimitive for comments on the animation support
897  */
898 void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption *option,
899                                   QPainter *painter, const QWidget *widget) const
900 {
901     QWindowsVistaStylePrivate *d = const_cast<QWindowsVistaStylePrivate*>(d_func());
902
903     if (!QWindowsVistaStylePrivate::useVista()) {
904         QWindowsStyle::drawControl(element, option, painter, widget);
905         return;
906     }
907
908     bool selected = option->state & State_Selected;
909     bool pressed = option->state & State_Sunken;
910     bool disabled = !(option->state & State_Enabled);
911
912     int state = option->state;
913     int themeNumber  = -1;
914
915     QRect rect(option->rect);
916     State flags = option->state;
917     int partId = 0;
918     int stateId = 0;
919
920     QRect oldRect;
921     QRect newRect;
922
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))
926             {
927                 QWidget *w = const_cast<QWidget *> (widget);
928                 int oldState = w->property("_q_stylestate").toInt();
929                 oldRect = w->property("_q_stylerect").toRect();
930                 newRect = w->rect();
931                 w->setProperty("_q_stylestate", (int)option->state);
932                 w->setProperty("_q_stylerect", w->rect());
933
934                 bool wasDefault = w->property("_q_isdefault").toBool();
935                 bool isDefault = button->features & QStyleOptionButton::DefaultButton;
936                 w->setProperty("_q_isdefault", isDefault);
937
938                 bool doTransition = ((state & State_Sunken)     != (oldState & State_Sunken) ||
939                                      (state & State_On)         != (oldState & State_On)     ||
940                                      (state & State_MouseOver)  != (oldState & State_MouseOver));
941
942                 if (oldRect != newRect || (wasDefault && !isDefault))
943                 {
944                     doTransition = false;
945                     d->stopAnimation(widget);
946                 }
947
948                 if (doTransition) {
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);
952
953                     QStyleOptionButton opt = *button;
954                     opt.state = (QStyle::State)oldState;
955
956                     startImage.fill(0);
957                     QWindowsVistaTransition *t = new QWindowsVistaTransition;
958                     t->setWidget(w);
959                     QPainter startPainter(&startImage);
960
961                     if (!anim) {
962                         proxy()->drawControl(element, &opt, &startPainter, 0 /* Intentional */);
963                     } else {
964                         anim->paint(&startPainter, &opt);
965                         d->stopAnimation(widget);
966                     }
967
968                     t->setStartImage(startImage);
969                     d->startAnimation(t);
970
971                     endImage.fill(0);
972                     QPainter endPainter(&endImage);
973                     proxy()->drawControl(element, option, &endPainter, 0 /* Intentional */);
974                     t->setEndImage(endImage);
975                     int duration = 0;
976                     HTHEME theme = pOpenThemeData(0, L"Button");
977
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);
982                     else
983                         t->setDuration(0);
984                     t->setStartTime(QTime::currentTime());
985                 }
986             }
987         }
988     }
989     switch (element) {
990     case CE_PushButtonBevel:
991         if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option))
992         {
993             QWindowsVistaAnimation *anim = d->widgetAnimation(widget);
994             if (anim && (btn->state & State_Enabled)) {
995                 anim->paint(painter, option);
996             } else {
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;
1004                 else if (justFlat)
1005                     ;
1006                 else if (flags & (State_Sunken | State_On))
1007                     stateId = PBS_PRESSED;
1008                 else if (flags & State_MouseOver)
1009                     stateId = PBS_HOT;
1010                 else if (btn->features & QStyleOptionButton::DefaultButton && (state & State_Active))
1011                     stateId = PBS_DEFAULTED;
1012                 else
1013                     stateId = PBS_NORMAL;
1014
1015                 if (!justFlat) {
1016
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))
1020                         {
1021                         if (!anim && widget) {
1022                             QImage startImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
1023                             startImage.fill(0);
1024                             QImage alternateImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
1025                             alternateImage.fill(0);
1026
1027                             QWindowsVistaPulse *pulse = new QWindowsVistaPulse;
1028                             pulse->setWidget(const_cast<QWidget*>(widget));
1029
1030                             QPainter startPainter(&startImage);
1031                             stateId = PBS_DEFAULTED;
1032                             XPThemeData theme(widget, &startPainter, themeNumber, partId, stateId, rect);
1033                             d->drawBackground(theme);
1034
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);
1044                             anim = pulse;
1045                         }
1046
1047                         if (anim)
1048                             anim->paint(painter, option);
1049                         else {
1050                             XPThemeData theme(widget, painter, themeNumber, partId, stateId, rect);
1051                             d->drawBackground(theme);
1052                         }
1053                     }
1054                     else {
1055                         d->stopAnimation(widget);
1056                         XPThemeData theme(widget, painter, themeNumber, partId, stateId, rect);
1057                         d->drawBackground(theme);
1058                     }
1059                 }
1060             }
1061             if (btn->features & QStyleOptionButton::HasMenu) {
1062                 int mbiw = 0, mbih = 0;
1063                 XPThemeData theme(widget, 0, QWindowsXPStylePrivate::ToolBarTheme,
1064                                   TP_DROPDOWNBUTTON);
1065                 if (theme.isValid()) {
1066                     SIZE size;
1067                     if (pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size) == S_OK) {
1068                         mbiw = size.cx;
1069                         mbih = size.cy;
1070                     }
1071                 }
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);
1079             }
1080             return;
1081         }
1082         break;
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;
1093             }
1094
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);
1102                     }
1103                 } else {
1104                     d->stopAnimation(progressbar);
1105                 }
1106             }
1107
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();
1114
1115             if (isIndeterminate) {
1116                 if (QWindowsVistaAnimation *a = d->widgetAnimation(widget)) {
1117                     int glowSize = 120;
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());
1122                     painter->save();
1123                     painter->setClipRect(theme.rect);
1124                     QRect animRect;
1125                     QSize pixmapSize(14, 14);
1126                     if (vertical) {
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());
1132                     } else {
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());
1138                     }
1139                     QString name = QString::fromLatin1("qiprogress-%1-%2").arg(pixmapSize.width()).arg(pixmapSize.height());
1140                     QPixmap pixmap;
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);
1156                         imagePainter.end();
1157                         pixmap = QPixmap::fromImage(image);
1158                         QPixmapCache::insert(name, pixmap);
1159                     }
1160                     painter->drawPixmap(animRect, pixmap);
1161                     painter->restore();
1162                 }
1163             }
1164             else {
1165                 qint64 progress = qMax<qint64>(bar->progress, bar->minimum); // workaround for bug in QProgressBar
1166
1167                 if (vertical) {
1168                     int maxHeight = option->rect.height();
1169                     int minHeight = 0;
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);
1173                     if (!inverted)
1174                         theme.rect.moveTop(rect.height() - theme.rect.height());
1175                 } else {
1176                     int maxWidth = option->rect.width();
1177                     int minWidth = 0;
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);
1183                 }
1184                 d->drawBackground(theme);
1185
1186                 if (QWindowsVistaAnimation *a = d->widgetAnimation(widget)) {
1187                     int glowSize = 140;
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());
1194                         else
1195                             d->stopAnimation(widget); //we stop the glow motion only after it has
1196                                                       //moved out of view
1197                     }
1198                     painter->save();
1199                     painter->setClipRect(theme.rect);
1200                     if (vertical) {
1201                         theme.rect = QRect(theme.rect.left(),
1202                                            inverted ? rect.top() - glowSize + animOffset :
1203                                                       rect.bottom() + glowSize - animOffset,
1204                                            rect.width(), glowSize);
1205                     } else {
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);
1208                     }
1209                     d->drawBackground(theme);
1210                     painter->restore();
1211                 }
1212             }
1213         }
1214         break;
1215 #endif // QT_NO_PROGRESSBAR
1216     case CE_MenuBarItem:
1217         {
1218
1219         if (const QStyleOptionMenuItem *mbi = qstyleoption_cast<const QStyleOptionMenuItem *>(option))
1220         {
1221             if (mbi->menuItemType == QStyleOptionMenuItem::DefaultItem)
1222                 break;
1223
1224             QPalette::ColorRole textRole = disabled ? QPalette::Text : QPalette::ButtonText;
1225             QPixmap pix = mbi->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize, option, widget), QIcon::Normal);
1226
1227             uint alignment = Qt::AlignCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine;
1228             if (!proxy()->styleHint(SH_UnderlineShortcut, mbi, widget))
1229                 alignment |= Qt::TextHideMnemonic;
1230
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);
1236
1237             int stateId = MBI_NORMAL;
1238             if (disabled)
1239                 stateId = MBI_DISABLED;
1240             else if (pressed)
1241                 stateId = MBI_PUSHED;
1242             else if (selected)
1243                 stateId = MBI_HOT;
1244
1245             XPThemeData theme2(widget, painter,
1246                                QWindowsXPStylePrivate::MenuTheme,
1247                                MENU_BARITEM, stateId, option->rect);
1248             d->drawBackground(theme2);
1249
1250             if (!pix.isNull())
1251                 drawItemPixmap(painter, mbi->rect, alignment, pix);
1252             else
1253                 drawItemText(painter, mbi->rect, alignment, mbi->palette, mbi->state & State_Enabled, mbi->text, textRole);
1254         }
1255     }
1256     break;
1257 #ifndef QT_NO_MENU
1258     case CE_MenuItem:
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
1261             int checkcol = 28;
1262             {
1263                 SIZE    size;
1264                 MARGINS margins;
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));
1270             }
1271             QRect rect = option->rect;
1272
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);
1280
1281             int x, y, w, h;
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;
1288
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);
1293                 stateId = MBI_HOT;
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);
1300                 return;
1301             }
1302
1303             QRect vCheckRect = visualRect(option->direction, menuitem->rect, QRect(menuitem->rect.x(),
1304                                           menuitem->rect.y(), checkcol - 6, menuitem->rect.height()));
1305
1306             if (act) {
1307                 stateId = MBI_HOT;
1308                 XPThemeData theme2(widget, painter,
1309                                    QWindowsXPStylePrivate::MenuTheme,
1310                                    MENU_POPUPITEM, stateId, option->rect);
1311                 d->drawBackground(theme2);
1312             }
1313
1314             if (checked) {
1315                 XPThemeData theme(widget, painter,
1316                                   QWindowsXPStylePrivate::MenuTheme,
1317                                   MENU_POPUPCHECKBACKGROUND,
1318                                   menuitem->icon.isNull() ? MBI_HOT : MBI_PUSHED, vCheckRect);
1319                 SIZE    size;
1320                 MARGINS margins;
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;
1328
1329                 d->drawBackground(theme);
1330
1331                 if (menuitem->icon.isNull()) {
1332                     checkRect = QRect(0, 0, size.cx, size.cy);
1333                     checkRect.moveCenter(theme.rect.center());
1334                     theme.rect = checkRect;
1335
1336                     theme.partId = MENU_POPUPCHECK;
1337                     bool bullet = menuitem->checkType & QStyleOptionMenuItem::Exclusive;
1338                     if (dis)
1339                         theme.stateId = bullet ? MC_BULLETDISABLED: MC_CHECKMARKDISABLED;
1340                     else
1341                         theme.stateId = bullet ? MC_BULLETNORMAL: MC_CHECKMARKNORMAL;
1342                     d->drawBackground(theme);
1343                 }
1344             }
1345
1346             if (!menuitem->icon.isNull()) {
1347                 QIcon::Mode mode = dis ? QIcon::Disabled : QIcon::Normal;
1348                 if (act && !dis)
1349                     mode = QIcon::Active;
1350                 QPixmap pixmap;
1351                 if (checked)
1352                     pixmap = menuitem->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize, option, widget), mode, QIcon::On);
1353                 else
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);
1361             }
1362
1363             painter->setPen(menuitem->palette.buttonText().color());
1364
1365             QColor discol;
1366             if (dis) {
1367                 discol = menuitem->palette.text().color();
1368                 painter->setPen(discol);
1369             }
1370
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
1377                 painter->save();
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;
1383                 if (t >= 0) {
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));
1387                     s = s.left(t);
1388                 }
1389                 QFont font = menuitem->font;
1390                 if (menuitem->menuItemType == QStyleOptionMenuItem::DefaultItem)
1391                     font.setBold(true);
1392                 painter->setFont(font);
1393                 painter->setPen(discol);
1394                 painter->drawText(vTextRect, text_flags, s.left(t));
1395                 painter->restore();
1396             }
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);
1407             }
1408         }
1409         break;
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)
1417                 stateId = HIS_HOT;
1418             else
1419                 stateId = HIS_NORMAL;
1420
1421             if (header->sortIndicator != QStyleOptionHeader::None)
1422                 stateId += 3;
1423
1424             XPThemeData theme(widget, painter,
1425                               QWindowsXPStylePrivate::HeaderTheme,
1426                               partId, stateId, option->rect);
1427             d->drawBackground(theme);
1428         }
1429         break;
1430     case CE_MenuBarEmptyArea:
1431         {
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);
1439         }
1440         break;
1441     case CE_ToolBar:
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, &copyOpt, painter, widget);
1448         }
1449         break;
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
1456             }
1457
1458             if (const QStyleOptionDockWidget *dwOpt = qstyleoption_cast<const QStyleOptionDockWidget *>(option)) {
1459
1460             const QStyleOptionDockWidgetV2 *v2
1461                 = qstyleoption_cast<const QStyleOptionDockWidgetV2*>(dwOpt);
1462             bool verticalTitleBar = v2 == 0 ? false : v2->verticalTitleBar;
1463
1464             if (verticalTitleBar) {
1465                 QSize s = rect.size();
1466                 s.transpose();
1467                 rect.setSize(s);
1468
1469                 painter->translate(rect.left() - 1, rect.top() + rect.width());
1470                 painter->rotate(-90);
1471                 painter->translate(-rect.left() + 1, -rect.top());
1472             }
1473
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));
1477
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();
1483
1484             QRect r = option->rect.adjusted(0, 2, -1, -3);
1485             QRect titleRect = r;
1486
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);
1490             }
1491
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);
1495             }
1496
1497             if (isFloating) {
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);
1501             } else {
1502                 titleRect.adjust(mw, 0, 0, 0);
1503                 if (!dwOpt->floatable && !dwOpt->closable)
1504                     titleRect.adjust(0, 0, -mw, 0);
1505             }
1506             if (!verticalTitleBar)
1507                 titleRect = visualRect(dwOpt->direction, r, titleRect);
1508
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);
1517                 }
1518             }
1519             break;
1520         }
1521 #ifndef QT_NO_ITEMVIEWS
1522     case CE_ItemViewItem:
1523         {
1524             const QStyleOptionViewItemV4 *vopt;
1525             const QAbstractItemView *view = qobject_cast<const QAbstractItemView *>(widget);
1526             bool newStyle = true;
1527
1528             if (qobject_cast<const QTableView*>(widget))
1529                 newStyle = false;
1530
1531             if (newStyle && view && (vopt = qstyleoption_cast<const QStyleOptionViewItemV4 *>(option))) {
1532                 /*
1533                 // We cannot currently get the correct selection color for "explorer style" views
1534                 COLORREF cref = 0;
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));
1538                 */
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);
1550             } else {
1551                 QWindowsXPStyle::drawControl(element, option, painter, widget);
1552             }
1553             break;
1554         }
1555 #endif // QT_NO_ITEMVIEWS
1556
1557     default:
1558         QWindowsXPStyle::drawControl(element, option, painter, widget);
1559         break;
1560     }
1561 }
1562
1563 /*!
1564   \internal
1565
1566   see drawPrimitive for comments on the animation support
1567
1568  */
1569 void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyleOptionComplex *option,
1570                                          QPainter *painter, const QWidget *widget) const
1571 {
1572     QWindowsVistaStylePrivate *d = const_cast<QWindowsVistaStylePrivate*>(d_func());
1573     if (!QWindowsVistaStylePrivate::useVista()) {
1574         QWindowsStyle::drawComplexControl(control, option, painter, widget);
1575         return;
1576     }
1577
1578     State state = option->state;
1579     SubControls sub = option->subControls;
1580     QRect r = option->rect;
1581
1582     int partId = 0;
1583     int stateId = 0;
1584
1585     State flags = option->state;
1586     if (widget && widget->testAttribute(Qt::WA_UnderMouse) && widget->isActiveWindow())
1587         flags |= State_MouseOver;
1588
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
1597             )
1598         {
1599             QWidget *w = const_cast<QWidget *> (widget);
1600
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());
1607
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);
1612
1613
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);
1621                 }
1622             } else if (control == CC_SpinBox) {
1623                 //spinboxes have a transition when focus changes
1624                 if (!doTransition)
1625                     doTransition = (state & State_HasFocus) != (oldState & State_HasFocus);
1626             }
1627
1628             if (oldRect != option->rect) {
1629                 doTransition = false;
1630                 d->stopAnimation(widget);
1631             }
1632
1633             if (doTransition) {
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;
1638                 t->setWidget(w);
1639                 if (!anim) {
1640                     if (const QStyleOptionComboBox *combo = qstyleoption_cast<const QStyleOptionComboBox*>(option)) {
1641                         //Combo boxes are special cased to avoid cleartype issues
1642                         startImage.fill(0);
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
1651                         startImage.fill(0);
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);
1658                     } else {
1659                         QPoint offset(0, 0);
1660                         QWindow *window = widget->windowHandle();
1661                         if (!window) {
1662                             if (const QWidget *nativeParent = widget->nativeParentWidget()) {
1663                                 offset = widget->mapTo(nativeParent, offset);
1664                                 window = nativeParent->windowHandle();
1665                             }
1666                         }
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());
1671                         }
1672                     }
1673                 } else {
1674                     startImage.fill(0);
1675                     QPainter startPainter(&startImage);
1676                     anim->paint(&startPainter, option);
1677                     t->setStartImage(startImage);
1678                 }
1679                 d->startAnimation(t);
1680                 endImage.fill(0);
1681                 QPainter endPainter(&endImage);
1682                 proxy()->drawComplexControl(control, option, &endPainter, 0 /* Intentional */);
1683                 t->setEndImage(endImage);
1684                 t->setStartTime(QTime::currentTime());
1685
1686                 if (option->state & State_MouseOver || option->state & State_Sunken)
1687                     t->setDuration(150);
1688                 else
1689                     t->setDuration(500);
1690             }
1691
1692             if (QWindowsVistaAnimation *anim = d->widgetAnimation(widget)) {
1693                 anim->paint(painter, option);
1694                 return;
1695             }
1696
1697         }
1698     }
1699
1700     switch (control) {
1701     case CC_ComboBox:
1702         if (const QStyleOptionComboBox *cmb = qstyleoption_cast<const QStyleOptionComboBox *>(option))
1703         {
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)
1710                         stateId = ETS_HOT;
1711                     else if (flags & State_HasFocus)
1712                         stateId = ETS_FOCUSED;
1713                     else
1714                         stateId = ETS_NORMAL;
1715
1716                     XPThemeData theme(widget, painter,
1717                                       QWindowsXPStylePrivate::EditTheme,
1718                                       partId, stateId, r);
1719
1720                     d->drawBackground(theme);
1721                 }
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;
1727
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)
1733                         stateId = CBXS_HOT;
1734                     else
1735                         stateId = CBXS_NORMAL;
1736
1737                     theme.partId = partId;
1738                     theme.stateId = stateId;
1739                     d->drawBackground(theme);
1740                 }
1741
1742             } else {
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);
1750                 }
1751             }
1752        }
1753        break;
1754     case CC_ScrollBar:
1755         if (const QStyleOptionSlider *scrollbar = qstyleoption_cast<const QStyleOptionSlider *>(option))
1756         {
1757             XPThemeData theme(widget, painter, QWindowsXPStylePrivate::ScrollBarTheme);
1758             bool maxedOut = (scrollbar->maximum == scrollbar->minimum);
1759             if (maxedOut)
1760                 flags &= ~State_Enabled;
1761
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);
1775                 else
1776                     stateId = (isHorz ? (isRTL ? ABS_LEFTNORMAL : ABS_RIGHTNORMAL) : ABS_DOWNNORMAL);
1777                 theme.partId = partId;
1778                 theme.stateId = stateId;
1779                 d->drawBackground(theme);
1780             }
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);
1792                 else
1793                     stateId = (isHorz ? (isRTL ? ABS_RIGHTNORMAL : ABS_LEFTNORMAL) : ABS_UPNORMAL);
1794                 theme.partId = partId;
1795                 theme.stateId = stateId;
1796                 d->drawBackground(theme);
1797             }
1798             if (maxedOut) {
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);
1807             } else {
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;
1817                     else
1818                         stateId = SCRBS_NORMAL;
1819                     theme.partId = partId;
1820                     theme.stateId = stateId;
1821                     d->drawBackground(theme);
1822                 }
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;
1832                     else
1833                         stateId = SCRBS_NORMAL;
1834                     theme.partId = partId;
1835                     theme.stateId = stateId;
1836                     d->drawBackground(theme);
1837                 }
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;
1848                     else
1849                         stateId = SCRBS_NORMAL;
1850
1851                     // Draw handle
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);
1856
1857                     // Calculate rect of gripper
1858                     const int swidth = theme.rect.width();
1859                     const int sheight = theme.rect.height();
1860
1861                     MARGINS contentsMargin;
1862                     RECT rect = theme.toRECT(theme.rect);
1863                     pGetThemeMargins(theme.handle(), 0, theme.partId, theme.stateId, TMT_SIZINGMARGINS, &rect, &contentsMargin);
1864
1865                     SIZE size;
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;
1869
1870
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);
1882                     }
1883
1884                     // Draw gripper if there is enough space
1885                     if (!gripperBounds.isEmpty() && flags & State_Enabled) {
1886                         painter->save();
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
1893                         painter->restore();
1894                     }
1895                 }
1896             }
1897         }
1898         break;
1899 #ifndef QT_NO_SPINBOX
1900     case CC_SpinBox:
1901         if (const QStyleOptionSpinBox *sb = qstyleoption_cast<const QStyleOptionSpinBox *>(option))
1902         {
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)
1909                     stateId = ETS_HOT;
1910                 else if (flags & State_HasFocus)
1911                     stateId = ETS_SELECTED;
1912                 else
1913                     stateId = ETS_NORMAL;
1914
1915                 XPThemeData ftheme(widget, painter,
1916                                    QWindowsXPStylePrivate::EditTheme,
1917                                    partId, stateId, r);
1918                 ftheme.noContent = true;
1919                 d->drawBackground(ftheme);
1920             }
1921             if (sub & SC_SpinBoxUp) {
1922                 theme.rect = proxy()->subControlRect(CC_SpinBox, option, SC_SpinBoxUp, widget).adjusted(0, 0, 0, 1);
1923                 partId = SPNP_UP;
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))
1929                     stateId = UPS_HOT;
1930                 else
1931                     stateId = UPS_NORMAL;
1932                 theme.partId = partId;
1933                 theme.stateId = stateId;
1934                 d->drawBackground(theme);
1935             }
1936             if (sub & SC_SpinBoxDown) {
1937                 theme.rect = proxy()->subControlRect(CC_SpinBox, option, SC_SpinBoxDown, widget);
1938                 partId = SPNP_DOWN;
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))
1944                     stateId = DNS_HOT;
1945                 else
1946                     stateId = DNS_NORMAL;
1947                 theme.partId = partId;
1948                 theme.stateId = stateId;
1949                 d->drawBackground(theme);
1950             }
1951         }
1952         break;
1953 #endif // QT_NO_SPINBOX
1954     default:
1955         QWindowsXPStyle::drawComplexControl(control, option, painter, widget);
1956         break;
1957     }
1958 }
1959
1960 /*!
1961  \internal
1962  */
1963 QSize QWindowsVistaStyle::sizeFromContents(ContentsType type, const QStyleOption *option,
1964                                         const QSize &size, const QWidget *widget) const
1965 {
1966     if (!QWindowsVistaStylePrivate::useVista())
1967         return QWindowsStyle::sizeFromContents(type, option, size, widget);
1968
1969     QSize sz(size);
1970     switch (type) {
1971     case CT_MenuItem:
1972         sz = QWindowsXPStyle::sizeFromContents(type, option, size, widget);
1973         int minimumHeight;
1974         {
1975             SIZE    size;
1976             MARGINS margins;
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;
1984         }
1985         
1986         if (const QStyleOptionMenuItem *menuitem = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) {
1987             if (menuitem->menuItemType != QStyleOptionMenuItem::Separator)
1988                 sz.setHeight(minimumHeight);
1989         }
1990         return sz;
1991 #ifndef QT_NO_MENUBAR
1992     case CT_MenuBarItem:
1993         if (!sz.isEmpty())
1994             sz += QSize(windowsItemHMargin * 5 + 1, 5);
1995             return sz;
1996         break;
1997 #endif
1998     case CT_ItemViewItem:
1999         sz = QWindowsXPStyle::sizeFromContents(type, option, size, widget);
2000         sz.rheight() += 2;
2001         return sz;
2002     case CT_SpinBox:
2003         {
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);
2008         }
2009         return sz;
2010     default:
2011         break;
2012     }
2013     return QWindowsXPStyle::sizeFromContents(type, option, size, widget);
2014 }
2015
2016 /*!
2017  \internal
2018  */
2019 QRect QWindowsVistaStyle::subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const
2020 {
2021    if (!QWindowsVistaStylePrivate::useVista())
2022         return QWindowsStyle::subElementRect(element, option, widget);
2023
2024    QRect rect = QWindowsXPStyle::subElementRect(element, option, widget);
2025     switch (element) {
2026
2027     case SE_PushButtonContents:
2028         if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) {
2029             MARGINS borderSize;
2030             HTHEME theme = pOpenThemeData(widget ? QWindowsVistaStylePrivate::winId(widget) : 0, L"Button");
2031             if (theme) {
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)
2038                     stateId = PBS_HOT;
2039                 else if (btn->features & QStyleOptionButton::DefaultButton)
2040                     stateId = PBS_DEFAULTED;
2041
2042                 int border = proxy()->pixelMetric(PM_DefaultFrameWidth, btn, widget);
2043                 rect = option->rect.adjusted(border, border, -border, -border);
2044
2045                 int result = pGetThemeMargins(theme,
2046                                               NULL,
2047                                               BP_PUSHBUTTON,
2048                                               stateId,
2049                                               TMT_CONTENTMARGINS,
2050                                               NULL,
2051                                               &borderSize);
2052
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);
2057                 }
2058             }
2059         }
2060         break;
2061
2062     case SE_HeaderArrow:
2063         {
2064             QRect r = rect;
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);
2070
2071             XPThemeData theme(widget, 0,
2072                               QWindowsXPStylePrivate::HeaderTheme,
2073                               HP_HEADERSORTARROW, HSAS_SORTEDDOWN, option->rect);
2074
2075             int arrowWidth = 13;
2076             int arrowHeight = 5;
2077             if (theme.isValid()) {
2078                 SIZE size;
2079                 if (pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size) == S_OK) {
2080                     arrowWidth = size.cx;
2081                     arrowHeight = size.cy;
2082                 }
2083             }
2084             if (option->state & State_Horizontal) {
2085                 r.setRect(x + w/2 - arrowWidth/2, y , arrowWidth, arrowHeight);
2086             } else {
2087                 int vert_size = w / 2;
2088                 r.setRect(x + 5, y + h - margin * 2 - vert_size,
2089                           w - margin * 2 - 5, vert_size);
2090             }
2091             rect = visualRect(option->direction, option->rect, r);
2092         }
2093         break;
2094
2095     case SE_HeaderLabel:
2096         {
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));
2106                 }
2107             }
2108             rect = visualRect(option->direction, option->rect, r);
2109         }
2110         break;
2111     case SE_ProgressBarContents:
2112         rect = QCommonStyle::subElementRect(SE_ProgressBarGroove, option, widget);
2113         break;
2114     case SE_ItemViewItemDecoration:
2115         if (qstyleoption_cast<const QStyleOptionViewItemV4 *>(option))
2116             rect.adjust(-2, 0, 2, 0);
2117         break;
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);
2124             else
2125                 rect = textRect;
2126             rect = rect.adjusted(1, 0, -1, 0);
2127         }
2128         break;
2129     default:
2130         break;
2131     }
2132     return rect;
2133 }
2134
2135
2136 /*
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.
2139 */
2140 static bool buttonVisible(const QStyle::SubControl sc, const QStyleOptionTitleBar *tb){
2141
2142     bool isMinimized = tb->titleBarState & Qt::WindowMinimized;
2143     bool isMaximized = tb->titleBarState & Qt::WindowMaximized;
2144     const uint flags = tb->titleBarFlags;
2145     bool retVal = false;
2146     switch (sc) {
2147     case QStyle::SC_TitleBarContextHelpButton:
2148         if (flags & Qt::WindowContextHelpButtonHint)
2149             retVal = true;
2150         break;
2151     case QStyle::SC_TitleBarMinButton:
2152         if (!isMinimized && (flags & Qt::WindowMinimizeButtonHint))
2153             retVal = true;
2154         break;
2155     case QStyle::SC_TitleBarNormalButton:
2156         if (isMinimized && (flags & Qt::WindowMinimizeButtonHint))
2157             retVal = true;
2158         else if (isMaximized && (flags & Qt::WindowMaximizeButtonHint))
2159             retVal = true;
2160         break;
2161     case QStyle::SC_TitleBarMaxButton:
2162         if (!isMaximized && (flags & Qt::WindowMaximizeButtonHint))
2163             retVal = true;
2164         break;
2165     case QStyle::SC_TitleBarShadeButton:
2166         if (!isMinimized &&  flags & Qt::WindowShadeButtonHint)
2167             retVal = true;
2168         break;
2169     case QStyle::SC_TitleBarUnshadeButton:
2170         if (isMinimized && flags & Qt::WindowShadeButtonHint)
2171             retVal = true;
2172         break;
2173     case QStyle::SC_TitleBarCloseButton:
2174         if (flags & Qt::WindowSystemMenuHint)
2175             retVal = true;
2176         break;
2177     case QStyle::SC_TitleBarSysMenu:
2178         if (flags & Qt::WindowSystemMenuHint)
2179             retVal = true;
2180         break;
2181     default :
2182         retVal = true;
2183     }
2184     return retVal;
2185 }
2186
2187
2188 /*! \internal */
2189 int QWindowsVistaStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget,
2190                              QStyleHintReturn *returnData) const
2191 {
2192     QWindowsVistaStylePrivate *d = const_cast<QWindowsVistaStylePrivate*>(d_func());
2193     int ret = 0;
2194     switch (hint) {
2195     case SH_MessageBox_CenterButtons:
2196         ret = false;
2197         break;
2198     case SH_ToolTip_Mask:
2199         if (option) {
2200             if (QStyleHintReturnMask *mask = qstyleoption_cast<QStyleHintReturnMask*>(returnData)) {
2201                 ret = true;
2202                 XPThemeData themeData(widget, 0,
2203                                       QWindowsXPStylePrivate::ToolTipTheme,
2204                                       TTP_STANDARD, TTSS_NORMAL, option->rect);
2205                 mask->region = d->region(themeData);
2206             }
2207         }
2208         break;
2209      case SH_Table_GridLineColor:
2210         if (option)
2211             ret = option->palette.color(QPalette::Base).darker(118).rgb();
2212         else
2213             ret = -1;
2214         break;
2215     default:
2216         ret = QWindowsXPStyle::styleHint(hint, option, widget, returnData);
2217         break;
2218     }
2219     return ret;
2220 }
2221
2222
2223 /*!
2224  \internal
2225  */
2226 QRect QWindowsVistaStyle::subControlRect(ComplexControl control, const QStyleOptionComplex *option,
2227                                   SubControl subControl, const QWidget *widget) const
2228 {
2229    if (!QWindowsVistaStylePrivate::useVista())
2230         return QWindowsStyle::subControlRect(control, option, subControl, widget);
2231
2232     QRect rect = QWindowsXPStyle::subControlRect(control, option, subControl, widget);
2233     switch (control) {
2234 #ifndef QT_NO_COMBOBOX
2235     case CC_ComboBox:
2236         if (const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
2237             int x = cb->rect.x(),
2238                 y = cb->rect.y(),
2239                 wi = cb->rect.width(),
2240                 he = cb->rect.height();
2241             int xpos = x;
2242             int margin = cb->frame ? 3 : 0;
2243             int bmarg = cb->frame ? 2 : 0;
2244             int arrowButtonWidth = bmarg + 16;
2245             xpos += wi - arrowButtonWidth;
2246
2247             switch (subControl) {
2248             case SC_ComboBoxFrame:
2249                 rect = cb->rect;
2250                 break;
2251             case SC_ComboBoxArrow:
2252                 rect.setRect(xpos, y , arrowButtonWidth, he);
2253                 break;
2254             case SC_ComboBoxEditField:
2255                 rect.setRect(x + margin, y + margin, wi - 2 * margin - 16, he - 2 * margin);
2256                 break;
2257             case SC_ComboBoxListBoxPopup:
2258                 rect = cb->rect;
2259                 break;
2260             default:
2261                 break;
2262             }
2263             rect = visualRect(cb->direction, cb->rect, rect);
2264             return rect;
2265         }
2266 #endif // QT_NO_COMBOBOX
2267     case CC_TitleBar:
2268         if (const QStyleOptionTitleBar *tb = qstyleoption_cast<const QStyleOptionTitleBar *>(option)) {
2269             if (!buttonVisible(subControl, tb))
2270                 return rect;
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;
2275
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;
2282
2283             switch (subControl) {
2284             case SC_TitleBarLabel:
2285                 rect = QRect(frameWidth, 0, width - (buttonWidth + frameWidth + 10), height);
2286                 if (isToolTitle) {
2287                     if (sysmenuHint) {
2288                         rect.adjust(0, 0, -buttonWidth - 3, 0);
2289                     }
2290                     if (minimizeHint || maximizeHint)
2291                         rect.adjust(0, 0, -buttonWidth - 2, 0);
2292                 } else {
2293                     if (sysmenuHint) {
2294                         const int leftOffset = height - 8;
2295                         rect.adjust(leftOffset, 0, 0, 4);
2296                     }
2297                     if (minimizeHint)
2298                         rect.adjust(0, 0, -buttonWidth - 2, 0);
2299                     if (maximizeHint)
2300                         rect.adjust(0, 0, -buttonWidth - 2, 0);
2301                     if (contextHint)
2302                         rect.adjust(0, 0, -buttonWidth - 2, 0);
2303                     if (shadeHint)
2304                         rect.adjust(0, 0, -buttonWidth - 2, 0);
2305                 }
2306                 rect.translate(0, 2);
2307                 rect = visualRect(option->direction, option->rect, rect);
2308                 break;
2309             case SC_TitleBarSysMenu:
2310                 {
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);
2322                 }
2323                 break;
2324             default:
2325                 break;
2326             }
2327         }
2328         break;
2329     default:
2330         break;
2331     }
2332     return rect;
2333 }
2334
2335 /*!
2336  \internal
2337  */
2338 bool QWindowsVistaStyle::event(QEvent *e)
2339 {
2340     Q_D(QWindowsVistaStyle);
2341     switch (e->type()) {
2342     case QEvent::Timer:
2343         {
2344             QTimerEvent *timerEvent = (QTimerEvent *)e;
2345             if (d->animationTimer.timerId() == timerEvent->timerId()) {
2346                 d->timerEvent();
2347                 e->accept();
2348                 return true;
2349             }
2350         }
2351         break;
2352     default:
2353         break;
2354     }
2355     return QWindowsXPStyle::event(e);
2356 }
2357
2358 /*!
2359  \internal
2360  */
2361 QStyle::SubControl QWindowsVistaStyle::hitTestComplexControl(ComplexControl control, const QStyleOptionComplex *option,
2362                                                           const QPoint &pos, const QWidget *widget) const
2363 {
2364     if (!QWindowsVistaStylePrivate::useVista()) {
2365         return QWindowsStyle::hitTestComplexControl(control, option, pos, widget);
2366     }
2367     return QWindowsXPStyle::hitTestComplexControl(control, option, pos, widget);
2368 }
2369
2370 /*!
2371  \internal
2372  */
2373 int QWindowsVistaStyle::pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const
2374 {
2375     if (!QWindowsVistaStylePrivate::useVista()) {
2376         return QWindowsStyle::pixelMetric(metric, option, widget);
2377     }
2378     switch (metric) {
2379
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:
2386         return 0;
2387     case PM_MenuPanelWidth:
2388         return 3;
2389     default:
2390         break;
2391     }
2392     return QWindowsXPStyle::pixelMetric(metric, option, widget);
2393 }
2394
2395 /*!
2396  \internal
2397  */
2398 QPalette QWindowsVistaStyle::standardPalette() const
2399 {
2400     return QWindowsXPStyle::standardPalette();
2401 }
2402
2403 /*!
2404  \internal
2405  */
2406 void QWindowsVistaStyle::polish(QApplication *app)
2407 {
2408     QWindowsXPStyle::polish(app);
2409 }
2410
2411 /*!
2412  \internal
2413  */
2414 void QWindowsVistaStyle::polish(QWidget *widget)
2415 {
2416     QWindowsXPStyle::polish(widget);
2417 #ifndef QT_NO_LINEEDIT
2418     if (qobject_cast<QLineEdit*>(widget))
2419         widget->setAttribute(Qt::WA_Hover);
2420     else
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);
2428     }
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);
2433         COLORREF bgRef;
2434         HTHEME theme = pOpenThemeData(widget ? QWindowsVistaStylePrivate::winId(widget) : 0, L"TOOLTIP");
2435         if (theme) {
2436             if (pGetThemeColor(theme, TTP_STANDARD, TTSS_NORMAL, TMT_TEXTCOLOR, &bgRef) == S_OK) {
2437                 QColor textColor = QColor::fromRgb(bgRef);
2438                 QPalette pal;
2439                 pal.setColor(QPalette::All, QPalette::ToolTipText, textColor);
2440                 widget->setPalette(pal);
2441             }
2442         }
2443     } else if (qobject_cast<QMessageBox *> (widget)) {
2444         widget->setAttribute(Qt::WA_StyledBackground);
2445         QDialogButtonBox *buttonBox = widget->findChild<QDialogButtonBox *>(QLatin1String("qt_msgbox_buttonbox"));
2446         if (buttonBox)
2447             buttonBox->setContentsMargins(0, 9, 0, 0);
2448     }
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"));
2453         if (buttonBox)
2454             buttonBox->setContentsMargins(0, 9, 0, 0);
2455     }
2456 #endif // QT_NO_INPUTDIALOG
2457     else if (QTreeView *tree = qobject_cast<QTreeView *> (widget)) {
2458         tree->viewport()->setAttribute(Qt::WA_Hover);
2459     }
2460     else if (QListView *list = qobject_cast<QListView *> (widget)) {
2461         list->viewport()->setAttribute(Qt::WA_Hover);
2462     }
2463 }
2464
2465 /*!
2466  \internal
2467  */
2468 void QWindowsVistaStyle::unpolish(QWidget *widget)
2469 {
2470     QWindowsXPStyle::unpolish(widget);
2471
2472     QWindowsVistaStylePrivate *d = const_cast<QWindowsVistaStylePrivate*>(d_func());
2473     d->stopAnimation(widget);
2474
2475 #ifndef QT_NO_LINEEDIT
2476     if (qobject_cast<QLineEdit*>(widget))
2477         widget->setAttribute(Qt::WA_Hover, false);
2478     else
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"));
2485         if (buttonBox)
2486             buttonBox->setContentsMargins(0, 0, 0, 0);
2487     }
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"));
2492         if (buttonBox)
2493             buttonBox->setContentsMargins(0, 0, 0, 0);
2494     }
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);
2503     }
2504 }
2505
2506
2507 /*!
2508  \internal
2509  */
2510 void QWindowsVistaStyle::unpolish(QApplication *app)
2511 {
2512     QWindowsXPStyle::unpolish(app);
2513 }
2514
2515 /*!
2516  \internal
2517  */
2518 void QWindowsVistaStyle::polish(QPalette &pal)
2519 {
2520     QWindowsStyle::polish(pal);
2521     pal.setBrush(QPalette::AlternateBase, pal.base().color().darker(104));
2522 }
2523
2524 /*!
2525  \internal
2526  */
2527 QPixmap QWindowsVistaStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *option,
2528                                       const QWidget *widget) const
2529 {
2530     if (!QWindowsVistaStylePrivate::useVista()) {
2531         return QWindowsStyle::standardPixmap(standardPixmap, option, widget);
2532     }
2533     return QWindowsXPStyle::standardPixmap(standardPixmap, option, widget);
2534 }
2535
2536 QWindowsVistaStylePrivate::QWindowsVistaStylePrivate() :
2537     QWindowsXPStylePrivate(), m_treeViewHelper(0)
2538 {
2539     resolveSymbols();
2540 }
2541
2542 QWindowsVistaStylePrivate::~QWindowsVistaStylePrivate()
2543 {
2544     qDeleteAll(animations);
2545     if (m_treeViewHelper)
2546         DestroyWindow(m_treeViewHelper);
2547 }
2548
2549 void QWindowsVistaStylePrivate::timerEvent()
2550 {
2551     for (int i = animations.size() - 1 ; i >= 0 ; --i) {
2552
2553         if (animations[i]->widget())
2554             animations[i]->widget()->update();
2555
2556         if (!animations[i]->widget() ||
2557             !animations[i]->widget()->isVisible() ||
2558             animations[i]->widget()->window()->isMinimized() ||
2559             !animations[i]->running() ||
2560             !QWindowsVistaStylePrivate::useVista())
2561         {
2562             QWindowsVistaAnimation *a = animations.takeAt(i);
2563             delete a;
2564         }
2565     }
2566     if (animations.size() == 0 && animationTimer.isActive()) {
2567         animationTimer.stop();
2568     }
2569 }
2570
2571 void QWindowsVistaStylePrivate::stopAnimation(const QWidget *w)
2572 {
2573     for (int i = animations.size() - 1 ; i >= 0 ; --i) {
2574         if (animations[i]->widget() == w) {
2575             QWindowsVistaAnimation *a = animations.takeAt(i);
2576             delete a;
2577             break;
2578         }
2579     }
2580 }
2581
2582 void QWindowsVistaStylePrivate::startAnimation(QWindowsVistaAnimation *t)
2583 {
2584     Q_Q(QWindowsVistaStyle);
2585     stopAnimation(t->widget());
2586     animations.append(t);
2587     if (animations.size() > 0 && !animationTimer.isActive()) {
2588         animationTimer.start(45, q);
2589     }
2590 }
2591
2592 bool QWindowsVistaStylePrivate::transitionsEnabled() const
2593 {
2594     BOOL animEnabled = false;
2595     if (SystemParametersInfo(SPI_GETCLIENTAREAANIMATION, 0, &animEnabled, 0))
2596     {
2597         if (animEnabled)
2598             return true;
2599     }
2600     return false;
2601 }
2602
2603
2604 QWindowsVistaAnimation * QWindowsVistaStylePrivate::widgetAnimation(const QWidget *widget) const
2605 {
2606     if (!widget)
2607         return 0;
2608     foreach (QWindowsVistaAnimation *a, animations) {
2609         if (a->widget() == widget)
2610             return a;
2611     }
2612     return 0;
2613 }
2614
2615
2616 /*! \internal
2617     Returns true if all the necessary theme engine symbols were
2618     resolved.
2619 */
2620 bool QWindowsVistaStylePrivate::resolveSymbols()
2621 {
2622     static bool tried = false;
2623     if (!tried) {
2624         tried = true;
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");
2649     }
2650     return pGetThemeTransitionDuration != 0;
2651 }
2652
2653 /*
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.
2661  */
2662
2663 static inline HWND createTreeViewHelperWindow()
2664 {
2665     if (QPlatformNativeInterface *ni = QGuiApplication::platformNativeInterface()) {
2666         void *hwnd = 0;
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);
2674         }
2675     }
2676     return 0;
2677 }
2678
2679 bool QWindowsVistaStylePrivate::initTreeViewTheming()
2680 {
2681     if (m_treeViewHelper)
2682         return true;
2683
2684     m_treeViewHelper = createTreeViewHelperWindow();
2685     if (!m_treeViewHelper) {
2686         qWarning("%s: Unable to create the treeview helper window.", Q_FUNC_INFO);
2687         return false;
2688     }
2689     const HRESULT hr = pSetWindowTheme(m_treeViewHelper, L"explorer", NULL);
2690     if (hr != S_OK) {
2691         qErrnoWarning("%s: SetWindowTheme() failed.", Q_FUNC_INFO);
2692         return false;
2693     }
2694     return QWindowsXPStylePrivate::createTheme(QWindowsXPStylePrivate::TreeViewTheme, m_treeViewHelper);
2695 }
2696
2697 /*!
2698 \internal
2699 */
2700 QIcon QWindowsVistaStyle::standardIconImplementation(StandardPixmap standardIcon,
2701                                                   const QStyleOption *option,
2702                                                   const QWidget *widget) const
2703 {
2704     if (!QWindowsVistaStylePrivate::useVista()) {
2705         return QWindowsStyle::standardIconImplementation(standardIcon, option, widget);
2706     }
2707
2708     QWindowsVistaStylePrivate *d = const_cast<QWindowsVistaStylePrivate *>(d_func());
2709     switch(standardIcon) {
2710     case SP_CommandLink:
2711         {
2712             XPThemeData theme(0, 0,
2713                               QWindowsXPStylePrivate::ButtonTheme,
2714                               BP_COMMANDLINKGLYPH, CMDLGS_NORMAL);
2715             if (theme.isValid()) {
2716                 SIZE size;
2717                 pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size);
2718                 QIcon linkGlyph;
2719                 QPixmap pm = QPixmap(size.cx, size.cy);
2720                 pm.fill(Qt::transparent);
2721                 QPainter p(&pm);
2722                 theme.painter = &p;
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);
2727
2728                 theme.stateId = CMDLGS_PRESSED;
2729                 d->drawBackground(theme);
2730                 linkGlyph.addPixmap(pm, QIcon::Normal, QIcon::On);     // Pressed
2731                 pm.fill(Qt::transparent);
2732
2733                 theme.stateId = CMDLGS_HOT;
2734                 d->drawBackground(theme);
2735                 linkGlyph.addPixmap(pm, QIcon::Active, QIcon::Off);    // Hover
2736                 pm.fill(Qt::transparent);
2737
2738                 theme.stateId = CMDLGS_DISABLED;
2739                 d->drawBackground(theme);
2740                 linkGlyph.addPixmap(pm, QIcon::Disabled, QIcon::Off);  // Disabled
2741                 return linkGlyph;
2742             }
2743         }
2744         break;
2745     default:
2746         break;
2747     }
2748     return QWindowsXPStyle::standardIconImplementation(standardIcon, option, widget);
2749 }
2750
2751 QT_END_NAMESPACE
2752
2753 #endif //QT_NO_WINDOWSVISTA