source: trunk/src/gui/styles/qwindowsvistastyle.cpp@ 1147

Last change on this file since 1147 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 117.7 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
6**
7** This file is part of the QtGui module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at qt-info@nokia.com.
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qwindowsvistastyle.h"
43#include "qwindowsvistastyle_p.h"
44#include <private/qstylehelper_p.h>
45#include <private/qsystemlibrary_p.h>
46
47#if !defined(QT_NO_STYLE_WINDOWSVISTA) || defined(QT_PLUGIN)
48
49QT_BEGIN_NAMESPACE
50
51static const int windowsItemFrame = 2; // menu item frame width
52static const int windowsItemHMargin = 3; // menu item hor text margin
53static const int windowsItemVMargin = 4; // menu item ver text margin
54static const int windowsArrowHMargin = 6; // arrow horizontal margin
55static const int windowsRightBorder = 15; // right border on windows
56
57#ifndef TMT_CONTENTMARGINS
58# define TMT_CONTENTMARGINS 3602
59#endif
60#ifndef TMT_SIZINGMARGINS
61# define TMT_SIZINGMARGINS 3601
62#endif
63#ifndef LISS_NORMAL
64# define LISS_NORMAL 1
65# define LISS_HOT 2
66# define LISS_SELECTED 3
67# define LISS_DISABLED 4
68# define LISS_SELECTEDNOTFOCUS 5
69# define LISS_HOTSELECTED 6
70#endif
71#ifndef BP_COMMANDLINK
72# define BP_COMMANDLINK 6
73# define BP_COMMANDLINKGLYPH 7
74# define CMDLGS_NORMAL 1
75# define CMDLGS_HOT 2
76# define CMDLGS_PRESSED 3
77# define CMDLGS_DISABLED 4
78#endif
79
80// Runtime resolved theme engine function calls
81
82
83typedef HRESULT (WINAPI *PtrGetThemePartSize)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, OPTIONAL RECT *prc, enum THEMESIZE eSize, OUT SIZE *psz);
84typedef HTHEME (WINAPI *PtrOpenThemeData)(HWND hwnd, LPCWSTR pszClassList);
85typedef HTHEME (WINAPI *PtrOpenThemeData)(HWND hwnd, LPCWSTR pszClassList);
86typedef HRESULT (WINAPI *PtrCloseThemeData)(HTHEME hTheme);
87typedef HRESULT (WINAPI *PtrDrawThemeBackground)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, OPTIONAL const RECT *pClipRect);
88typedef HRESULT (WINAPI *PtrDrawThemeBackgroundEx)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, OPTIONAL const DTBGOPTS *pOptions);
89typedef HRESULT (WINAPI *PtrGetCurrentThemeName)(OUT LPWSTR pszThemeFileName, int cchMaxNameChars, OUT OPTIONAL LPWSTR pszColorBuff, int cchMaxColorChars, OUT OPTIONAL LPWSTR pszSizeBuff, int cchMaxSizeChars);
90typedef HRESULT (WINAPI *PtrGetThemeBool)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT BOOL *pfVal);
91typedef HRESULT (WINAPI *PtrGetThemeColor)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT COLORREF *pColor);
92typedef HRESULT (WINAPI *PtrGetThemeEnumValue)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT int *piVal);
93typedef HRESULT (WINAPI *PtrGetThemeFilename)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT LPWSTR pszThemeFileName, int cchMaxBuffChars);
94typedef HRESULT (WINAPI *PtrGetThemeFont)(HTHEME hTheme, OPTIONAL HDC hdc, int iPartId, int iStateId, int iPropId, OUT LOGFONT *pFont);
95typedef HRESULT (WINAPI *PtrGetThemeInt)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT int *piVal);
96typedef HRESULT (WINAPI *PtrGetThemeIntList)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT INTLIST *pIntList);
97typedef HRESULT (WINAPI *PtrGetThemeMargins)(HTHEME hTheme, OPTIONAL HDC hdc, int iPartId, int iStateId, int iPropId, OPTIONAL RECT *prc, OUT MARGINS *pMargins);
98typedef HRESULT (WINAPI *PtrGetThemeMetric)(HTHEME hTheme, OPTIONAL HDC hdc, int iPartId, int iStateId, int iPropId, OUT int *piVal);
99typedef HRESULT (WINAPI *PtrGetThemePartSize)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, OPTIONAL RECT *prc, enum THEMESIZE eSize, OUT SIZE *psz);
100typedef HRESULT (WINAPI *PtrGetThemePosition)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT POINT *pPoint);
101typedef HRESULT (WINAPI *PtrGetThemeRect)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT RECT *pRect);
102typedef HRESULT (WINAPI *PtrGetThemeString)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT LPWSTR pszBuff, int cchMaxBuffChars);
103typedef HRESULT (WINAPI *PtrGetThemeTransitionDuration)(HTHEME hTheme, int iPartId, int iStateFromId, int iStateToId, int iPropId, int *pDuration);
104typedef HRESULT (WINAPI *PtrIsThemePartDefined)(HTHEME hTheme, int iPartId, int iStateId);
105typedef HRESULT (WINAPI *PtrSetWindowTheme)(HWND hwnd, LPCWSTR pszSubAppName, LPCWSTR pszSubIdList);
106typedef HRESULT (WINAPI *PtrGetThemePropertyOrigin)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT enum PROPERTYORIGIN *pOrigin);
107
108static PtrIsThemePartDefined pIsThemePartDefined = 0;
109static PtrOpenThemeData pOpenThemeData = 0;
110static PtrCloseThemeData pCloseThemeData = 0;
111static PtrDrawThemeBackground pDrawThemeBackground = 0;
112static PtrDrawThemeBackgroundEx pDrawThemeBackgroundEx = 0;
113static PtrGetCurrentThemeName pGetCurrentThemeName = 0;
114static PtrGetThemeBool pGetThemeBool = 0;
115static PtrGetThemeColor pGetThemeColor = 0;
116static PtrGetThemeEnumValue pGetThemeEnumValue = 0;
117static PtrGetThemeFilename pGetThemeFilename = 0;
118static PtrGetThemeFont pGetThemeFont = 0;
119static PtrGetThemeInt pGetThemeInt = 0;
120static PtrGetThemeIntList pGetThemeIntList = 0;
121static PtrGetThemeMargins pGetThemeMargins = 0;
122static PtrGetThemeMetric pGetThemeMetric = 0;
123static PtrGetThemePartSize pGetThemePartSize = 0;
124static PtrGetThemePosition pGetThemePosition = 0;
125static PtrGetThemeRect pGetThemeRect = 0;
126static PtrGetThemeString pGetThemeString = 0;
127static PtrGetThemeTransitionDuration pGetThemeTransitionDuration= 0;
128static PtrSetWindowTheme pSetWindowTheme = 0;
129static PtrGetThemePropertyOrigin pGetThemePropertyOrigin = 0;
130
131/* \internal
132 Checks if we should use Vista style , or if we should
133 fall back to Windows style.
134*/
135bool QWindowsVistaStylePrivate::useVista()
136{
137 return (QWindowsVistaStylePrivate::useXP() &&
138 (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA &&
139 QSysInfo::WindowsVersion < QSysInfo::WV_NT_based));
140}
141
142/*!
143 \class QWindowsVistaStyle
144 \brief The QWindowsVistaStyle class provides a look and feel suitable for applications on Microsoft Windows Vista.
145 \since 4.3
146 \ingroup appearance
147
148 \warning This style is only available on the Windows Vista platform
149 because it makes use of Windows Vista's style engine.
150
151 \sa QMacStyle, QWindowsXPStyle, QPlastiqueStyle, QCleanlooksStyle, QMotifStyle
152*/
153
154/*!
155 Constructs a QWindowsVistaStyle object.
156*/
157QWindowsVistaStyle::QWindowsVistaStyle()
158 : QWindowsXPStyle(*new QWindowsVistaStylePrivate)
159{
160}
161
162//convert Qt state flags to uxtheme button states
163static int buttonStateId(int flags, int partId)
164{
165 int stateId = 0;
166 if (partId == BP_RADIOBUTTON || partId == BP_CHECKBOX) {
167 if (!(flags & QStyle::State_Enabled))
168 stateId = RBS_UNCHECKEDDISABLED;
169 else if (flags & QStyle::State_Sunken)
170 stateId = RBS_UNCHECKEDPRESSED;
171 else if (flags & QStyle::State_MouseOver)
172 stateId = RBS_UNCHECKEDHOT;
173 else
174 stateId = RBS_UNCHECKEDNORMAL;
175
176 if (flags & QStyle::State_On)
177 stateId += RBS_CHECKEDNORMAL-1;
178
179 } else if (partId == BP_PUSHBUTTON) {
180 if (!(flags & QStyle::State_Enabled))
181 stateId = PBS_DISABLED;
182 else if (flags & (QStyle::State_Sunken | QStyle::State_On))
183 stateId = PBS_PRESSED;
184 else if (flags & QStyle::State_MouseOver)
185 stateId = PBS_HOT;
186 else
187 stateId = PBS_NORMAL;
188 } else {
189 Q_ASSERT(1);
190 }
191 return stateId;
192}
193
194void QWindowsVistaAnimation::paint(QPainter *painter, const QStyleOption *option)
195{
196 Q_UNUSED(option);
197 Q_UNUSED(painter);
198}
199
200/*! \internal
201
202 Helperfunction to paint the current transition state between two
203 animation frames.
204
205 The result is a blended image consisting of ((alpha)*_primaryImage)
206 + ((1-alpha)*_secondaryImage)
207
208*/
209void QWindowsVistaAnimation::drawBlendedImage(QPainter *painter, QRect rect, float alpha) {
210 if (_secondaryImage.isNull() || _primaryImage.isNull())
211 return;
212
213 if (_tempImage.isNull())
214 _tempImage = _secondaryImage;
215
216 const int a = qRound(alpha*256);
217 const int ia = 256 - a;
218 const int sw = _primaryImage.width();
219 const int sh = _primaryImage.height();
220 const int bpl = _primaryImage.bytesPerLine();
221 switch(_primaryImage.depth()) {
222 case 32:
223 {
224 uchar *mixed_data = _tempImage.bits();
225 const uchar *back_data = _primaryImage.bits();
226 const uchar *front_data = _secondaryImage.bits();
227 for (int sy = 0; sy < sh; sy++) {
228 quint32* mixed = (quint32*)mixed_data;
229 const quint32* back = (const quint32*)back_data;
230 const quint32* front = (const quint32*)front_data;
231 for (int sx = 0; sx < sw; sx++) {
232 quint32 bp = back[sx];
233 quint32 fp = front[sx];
234 mixed[sx] = qRgba ((qRed(bp)*ia + qRed(fp)*a)>>8,
235 (qGreen(bp)*ia + qGreen(fp)*a)>>8,
236 (qBlue(bp)*ia + qBlue(fp)*a)>>8,
237 (qAlpha(bp)*ia + qAlpha(fp)*a)>>8);
238 }
239 mixed_data += bpl;
240 back_data += bpl;
241 front_data += bpl;
242 }
243 }
244 default:
245 break;
246 }
247 painter->drawImage(rect, _tempImage);
248}
249
250/*! \internal
251 Paints a transition state. The result will be a mix between the
252 initial and final state of the transition, depending on the time
253 difference between _startTime and current time.
254*/
255void QWindowsVistaTransition::paint(QPainter *painter, const QStyleOption *option)
256{
257 float alpha = 1.0;
258 if (_duration > 0) {
259 QTime current = QTime::currentTime();
260
261 if (_startTime > current)
262 _startTime = current;
263
264 int timeDiff = _startTime.msecsTo(current);
265 alpha = timeDiff/(float)_duration;
266 if (timeDiff > _duration) {
267 _running = false;
268 alpha = 1.0;
269 }
270 }
271 else {
272 _running = false;
273 }
274 drawBlendedImage(painter, option->rect, alpha);
275}
276
277/*! \internal
278 Paints a pulse. The result will be a mix between the primary and
279 secondary pulse images depending on the time difference between
280 _startTime and current time.
281*/
282void QWindowsVistaPulse::paint(QPainter *painter, const QStyleOption *option)
283{
284 float alpha = 1.0;
285 if (_duration > 0) {
286 QTime current = QTime::currentTime();
287
288 if (_startTime > current)
289 _startTime = current;
290
291 int timeDiff = _startTime.msecsTo(current) % _duration*2;
292 if (timeDiff > _duration)
293 timeDiff = _duration*2 - timeDiff;
294 alpha = timeDiff/(float)_duration;
295 } else {
296 _running = false;
297 }
298 drawBlendedImage(painter, option->rect, alpha);
299}
300
301
302/*!
303 \internal
304
305 Animations are used for some state transitions on specific widgets.
306
307 Only one running animation can exist for a widget at any specific
308 time. Animations can be added through
309 QWindowsVistaStylePrivate::startAnimation(Animation *) and any
310 existing animation on a widget can be retrieved with
311 QWindowsVistaStylePrivate::widgetAnimation(Widget *).
312
313 Once an animation has been started,
314 QWindowsVistaStylePrivate::timerEvent(QTimerEvent *) will
315 continuously call update() on the widget until it is stopped,
316 meaning that drawPrimitive will be called many times until the
317 transition has completed. During this time, the result will be
318 retrieved by the Animation::paint(...) function and not by the style
319 itself.
320
321 To determine if a transition should occur, the style needs to know
322 the previous state of the widget as well as the current one. This is
323 solved by updating dynamic properties on the widget every time the
324 function is called.
325
326 Transitions interrupting existing transitions should always be
327 smooth, so whenever a hover-transition is started on a pulsating
328 button, it uses the current frame of the pulse-animation as the
329 starting image for the hover transition.
330
331 */
332void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOption *option,
333 QPainter *painter, const QWidget *widget) const
334{
335 QWindowsVistaStylePrivate *d = const_cast<QWindowsVistaStylePrivate*>(d_func());
336
337 int state = option->state;
338 if (!QWindowsVistaStylePrivate::useVista()) {
339 QWindowsStyle::drawPrimitive(element, option, painter, widget);
340 return;
341 }
342
343 QRect oldRect;
344 QRect newRect;
345
346 if (widget && d->transitionsEnabled())
347 {
348 /* all widgets that supports state transitions : */
349 if (
350#ifndef QT_NO_LINEEDIT
351 (qobject_cast<const QLineEdit*>(widget) && element == PE_FrameLineEdit) ||
352#endif // QT_NO_LINEEDIT
353 (qobject_cast<const QRadioButton*>(widget)&& element == PE_IndicatorRadioButton) ||
354 (qobject_cast<const QCheckBox*>(widget) && element == PE_IndicatorCheckBox) ||
355 (qobject_cast<const QGroupBox *>(widget)&& element == PE_IndicatorCheckBox) ||
356 (qobject_cast<const QToolButton*>(widget) && element == PE_PanelButtonBevel)
357 )
358 {
359 // Retrieve and update the dynamic properties tracking
360 // the previous state of the widget:
361 QWidget *w = const_cast<QWidget *> (widget);
362 int oldState = w->property("_q_stylestate").toInt();
363 oldRect = w->property("_q_stylerect").toRect();
364 newRect = w->rect();
365 w->setProperty("_q_stylestate", (int)option->state);
366 w->setProperty("_q_stylerect", w->rect());
367
368 bool doTransition = oldState &&
369 ((state & State_Sunken) != (oldState & State_Sunken) ||
370 (state & State_On) != (oldState & State_On) ||
371 (state & State_MouseOver) != (oldState & State_MouseOver));
372
373 if (oldRect != newRect ||
374 (state & State_Enabled) != (oldState & State_Enabled) ||
375 (state & State_Active) != (oldState & State_Active))
376 d->stopAnimation(widget);
377
378#ifndef QT_NO_LINEEDIT
379 if (const QLineEdit *edit = qobject_cast<const QLineEdit *>(widget))
380 if (edit->isReadOnly() && element == PE_FrameLineEdit) // Do not animate read only line edits
381 doTransition = false;
382#endif // QT_NO_LINEEDIT
383
384 if (doTransition) {
385
386 // We create separate images for the initial and final transition states and store them in the
387 // Transition object.
388 QImage startImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
389 QImage endImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
390 QStyleOption opt = *option;
391
392 opt.rect.setRect(0, 0, option->rect.width(), option->rect.height());
393 opt.state = (QStyle::State)oldState;
394 startImage.fill(0);
395 QPainter startPainter(&startImage);
396
397 QWindowsVistaAnimation *anim = d->widgetAnimation(widget);
398 QWindowsVistaTransition *t = new QWindowsVistaTransition;
399 t->setWidget(w);
400
401 // If we have a running animation on the widget already, we will use that to paint the initial
402 // state of the new transition, this ensures a smooth transition from a current animation such as a
403 // pulsating default button into the intended target state.
404
405 if (!anim)
406 proxy()->drawPrimitive(element, &opt, &startPainter, 0); // Note that the widget pointer is intentionally 0
407 else // this ensures that we do not recurse in the animation logic above
408 anim->paint(&startPainter, &opt);
409
410 d->startAnimation(t);
411 t->setStartImage(startImage);
412
413 // The end state of the transition is simply the result we would have painted
414 // if the style was not animated.
415
416 QPainter endPainter(&endImage);
417 endImage.fill(0);
418 QStyleOption opt2 = opt;
419 opt2.state = option->state;
420 proxy()->drawPrimitive(element, &opt2, &endPainter, 0); // Note that the widget pointer is intentionally 0
421 // this ensures that we do not recurse in the animation logic above
422 t->setEndImage(endImage);
423
424 HTHEME theme;
425 int partId;
426 int duration;
427 int fromState = 0;
428 int toState = 0;
429
430 //translate state flags to UXTHEME states :
431 if (element == PE_FrameLineEdit) {
432 theme = pOpenThemeData(0, L"Edit");
433 partId = EP_EDITBORDER_NOSCROLL;
434
435 if (oldState & State_MouseOver)
436 fromState = ETS_HOT;
437 else if (oldState & State_HasFocus)
438 fromState = ETS_FOCUSED;
439 else
440 fromState = ETS_NORMAL;
441
442 if (state & State_MouseOver)
443 toState = ETS_HOT;
444 else if (state & State_HasFocus)
445 toState = ETS_FOCUSED;
446 else
447 toState = ETS_NORMAL;
448
449 } else {
450 theme = pOpenThemeData(0, L"Button");
451 if (element == PE_IndicatorRadioButton)
452 partId = BP_RADIOBUTTON;
453 else if (element == PE_IndicatorCheckBox)
454 partId = BP_CHECKBOX;
455 else
456 partId = BP_PUSHBUTTON;
457
458 fromState = buttonStateId(oldState, partId);
459 toState = buttonStateId(option->state, partId);
460 }
461
462 // Retrieve the transition time between the states from the system.
463 if (theme && pGetThemeTransitionDuration(theme, partId, fromState, toState,
464 TMT_TRANSITIONDURATIONS, &duration) == S_OK)
465 {
466 t->setDuration(duration);
467 }
468 t->setStartTime(QTime::currentTime());
469 }
470 }
471 } // End of animation part
472
473
474 QRect rect = option->rect;
475
476 switch (element) {
477 case PE_IndicatorHeaderArrow:
478 if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) {
479 int stateId = HSAS_SORTEDDOWN;
480 if (header->sortIndicator & QStyleOptionHeader::SortDown)
481 stateId = HSAS_SORTEDUP; //note that the uxtheme sort down indicator is the inverse of ours
482 XPThemeData theme(widget, painter, QLatin1String("HEADER"), HP_HEADERSORTARROW, stateId, option->rect);
483 d->drawBackground(theme);
484 }
485 break;
486
487 case PE_IndicatorBranch:
488 {
489 XPThemeData theme(d->treeViewHelper(), painter, QLatin1String("TREEVIEW"));
490 static int decoration_size = 0;
491 if (theme.isValid() && !decoration_size) {
492 SIZE size;
493 pGetThemePartSize(theme.handle(), 0, TVP_HOTGLYPH, GLPS_OPENED, 0, TS_TRUE, &size);
494 decoration_size = qMax(size.cx, size.cy);
495 }
496 int mid_h = option->rect.x() + option->rect.width() / 2;
497 int mid_v = option->rect.y() + option->rect.height() / 2;
498 int bef_h = mid_h;
499 int bef_v = mid_v;
500 int aft_h = mid_h;
501 int aft_v = mid_v;
502 if (option->state & State_Children) {
503 int delta = decoration_size / 2;
504 theme.rect = QRect(bef_h - delta, bef_v - delta, decoration_size, decoration_size);
505 theme.partId = option->state & State_MouseOver ? TVP_HOTGLYPH : TVP_GLYPH;
506 theme.stateId = option->state & QStyle::State_Open ? GLPS_OPENED : GLPS_CLOSED;
507 if (option->direction == Qt::RightToLeft)
508 theme.mirrorHorizontally = true;
509 d->drawBackground(theme);
510 bef_h -= delta + 2;
511 bef_v -= delta + 2;
512 aft_h += delta - 2;
513 aft_v += delta - 2;
514 }
515#if 0
516 QBrush brush(option->palette.dark().color(), Qt::Dense4Pattern);
517 if (option->state & State_Item) {
518 if (option->direction == Qt::RightToLeft)
519 painter->fillRect(option->rect.left(), mid_v, bef_h - option->rect.left(), 1, brush);
520 else
521 painter->fillRect(aft_h, mid_v, option->rect.right() - aft_h + 1, 1, brush);
522 }
523 if (option->state & State_Sibling && option->rect.bottom() > aft_v)
524 painter->fillRect(mid_h, aft_v, 1, option->rect.bottom() - aft_v + 1, brush);
525 if (option->state & (State_Open | State_Children | State_Item | State_Sibling) && (bef_v > option->rect.y()))
526 painter->fillRect(mid_h, option->rect.y(), 1, bef_v - option->rect.y(), brush);
527#endif
528 }
529 break;
530
531 case PE_PanelButtonBevel:
532 case PE_IndicatorCheckBox:
533 case PE_IndicatorRadioButton:
534 {
535 if (QWindowsVistaAnimation *a = d->widgetAnimation(widget)) {
536 a->paint(painter, option);
537 } else {
538 QWindowsXPStyle::drawPrimitive(element, option, painter, widget);
539 }
540 }
541 break;
542
543 case PE_FrameMenu:
544 {
545 int stateId = option->state & State_Active ? MB_ACTIVE : MB_INACTIVE;
546 XPThemeData theme(widget, painter, QLatin1String("MENU"), MENU_POPUPBORDERS, stateId, option->rect);
547 d->drawBackground(theme);
548 }
549 break;
550 case PE_Frame:
551#ifndef QT_NO_TEXTEDIT
552 if (const QTextEdit *edit = qobject_cast<const QTextEdit*>(widget)) {
553 painter->save();
554 int stateId = ETS_NORMAL;
555 if (!(state & State_Enabled))
556 stateId = ETS_DISABLED;
557 else if (edit->isReadOnly())
558 stateId = ETS_READONLY;
559 else if (state & State_HasFocus)
560 stateId = ETS_SELECTED;
561 XPThemeData theme(widget, painter, QLatin1String("EDIT"), EP_EDITBORDER_HVSCROLL, stateId, option->rect);
562 uint resolve_mask = option->palette.resolve();
563 if (resolve_mask & (1 << QPalette::Base)) {
564 // Since EP_EDITBORDER_HVSCROLL does not us borderfill, theme.noContent cannot be used for clipping
565 int borderSize = 1;
566 pGetThemeInt(theme.handle(), theme.partId, theme.stateId, TMT_BORDERSIZE, &borderSize);
567 QRegion clipRegion = option->rect;
568 QRegion content = option->rect.adjusted(borderSize, borderSize, -borderSize, -borderSize);
569 clipRegion ^= content;
570 painter->setClipRegion(clipRegion);
571 }
572 d->drawBackground(theme);
573 painter->restore();
574 } else
575#endif // QT_NO_TEXTEDIT
576 QWindowsXPStyle::drawPrimitive(element, option, painter, widget);
577 break;
578
579 case PE_PanelLineEdit:
580 if (const QStyleOptionFrame *panel = qstyleoption_cast<const QStyleOptionFrame *>(option)) {
581 QBrush bg;
582 bool usePalette = false;
583 bool isEnabled = option->state & State_Enabled;
584 uint resolve_mask = panel->palette.resolve();
585 if (widget) {
586 //Since spin box and combo box includes a line edit we need to resolve the palette on the parent instead
587#ifndef QT_NO_SPINBOX
588 if (QAbstractSpinBox *spinbox = qobject_cast<QAbstractSpinBox*>(widget->parentWidget()))
589 resolve_mask = spinbox->palette().resolve();
590#endif // QT_NO_SPINBOX
591#ifndef QT_NO_COMBOBOX
592 if (QComboBox *combobox = qobject_cast<QComboBox*>(widget->parentWidget()))
593 resolve_mask = combobox->palette().resolve();
594#endif // QT_NO_COMBOBOX
595 }
596 if (resolve_mask & (1 << QPalette::Base)) {
597 // Base color is set for this widget, so use it
598 bg = panel->palette.brush(QPalette::Base);
599 usePalette = true;
600 }
601 if (usePalette) {
602 painter->fillRect(panel->rect, bg);
603 } else {
604 int partId = EP_BACKGROUND;
605 int stateId = EBS_NORMAL;
606 if (!isEnabled)
607 stateId = EBS_DISABLED;
608 else if (state & State_ReadOnly)
609 stateId = EBS_READONLY;
610 else if (state & State_MouseOver)
611 stateId = EBS_HOT;
612
613 XPThemeData theme(0, painter, QLatin1String("EDIT"), partId, stateId, rect);
614 if (!theme.isValid()) {
615 QWindowsStyle::drawPrimitive(element, option, painter, widget);
616 return;
617 }
618 int bgType;
619 pGetThemeEnumValue( theme.handle(),
620 partId,
621 stateId,
622 TMT_BGTYPE,
623 &bgType);
624 if( bgType == BT_IMAGEFILE ) {
625 d->drawBackground(theme);
626 } else {
627 QBrush fillColor = option->palette.brush(QPalette::Base);
628 if (!isEnabled) {
629 PROPERTYORIGIN origin = PO_NOTFOUND;
630 pGetThemePropertyOrigin(theme.handle(), theme.partId, theme.stateId, TMT_FILLCOLOR, &origin);
631 // Use only if the fill property comes from our part
632 if ((origin == PO_PART || origin == PO_STATE)) {
633 COLORREF bgRef;
634 pGetThemeColor(theme.handle(), partId, stateId, TMT_FILLCOLOR, &bgRef);
635 fillColor = QBrush(qRgb(GetRValue(bgRef), GetGValue(bgRef), GetBValue(bgRef)));
636 }
637 }
638 painter->fillRect(option->rect, fillColor);
639 }
640 }
641 if (panel->lineWidth > 0)
642 proxy()->drawPrimitive(PE_FrameLineEdit, panel, painter, widget);
643 return;
644 }
645 break;
646
647 case PE_FrameLineEdit:
648 if (QWindowsVistaAnimation *anim = d->widgetAnimation(widget)) {
649 anim->paint(painter, option);
650 } else {
651 QPainter *p = painter;
652 QWidget *parentWidget = 0;
653 if (widget) {
654 parentWidget = widget->parentWidget();
655 if (parentWidget)
656 parentWidget = parentWidget->parentWidget();
657 }
658 if (widget && widget->inherits("QLineEdit")
659 && parentWidget && parentWidget->inherits("QAbstractItemView")) {
660 // we try to check if this lineedit is a delegate on a QAbstractItemView-derived class.
661 QPen oldPen = p->pen();
662 // Inner white border
663 p->setPen(QPen(option->palette.base().color(), 1));
664 p->drawRect(option->rect.adjusted(1, 1, -2, -2));
665 // Outer dark border
666 p->setPen(QPen(option->palette.shadow().color(), 1));
667 p->drawRect(option->rect.adjusted(0, 0, -1, -1));
668 p->setPen(oldPen);
669 return;
670 } else {
671 int stateId = ETS_NORMAL;
672 if (!(state & State_Enabled))
673 stateId = ETS_DISABLED;
674 else if (state & State_ReadOnly)
675 stateId = ETS_READONLY;
676 else if (state & State_MouseOver)
677 stateId = ETS_HOT;
678 else if (state & State_HasFocus)
679 stateId = ETS_SELECTED;
680 XPThemeData theme(widget, painter, QLatin1String("EDIT"), EP_EDITBORDER_NOSCROLL, stateId, option->rect);
681 painter->save();
682 QRegion clipRegion = option->rect;
683 clipRegion -= option->rect.adjusted(2, 2, -2, -2);
684 painter->setClipRegion(clipRegion);
685 d->drawBackground(theme);
686 painter->restore();
687 }
688 }
689 break;
690
691 case PE_IndicatorToolBarHandle:
692 {
693 XPThemeData theme;
694 QRect rect;
695 if (option->state & State_Horizontal) {
696 theme = XPThemeData(widget, painter, QLatin1String("REBAR"), RP_GRIPPER, ETS_NORMAL, option->rect.adjusted(0, 1, -2, -2));
697 rect = option->rect.adjusted(0, 1, 0, -2);
698 rect.setWidth(4);
699 } else {
700 theme = XPThemeData(widget, painter, QLatin1String("REBAR"), RP_GRIPPERVERT, ETS_NORMAL, option->rect.adjusted(0, 1, -2, -2));
701 rect = option->rect.adjusted(1, 0, -1, 0);
702 rect.setHeight(4);
703 }
704 theme.rect = rect;
705 d->drawBackground(theme);
706 }
707 break;
708
709 case PE_IndicatorToolBarSeparator:
710 {
711 QPen pen = painter->pen();
712 int margin = 3;
713 painter->setPen(option->palette.background().color().darker(114));
714 if (option->state & State_Horizontal) {
715 int x1 = option->rect.center().x();
716 painter->drawLine(QPoint(x1, option->rect.top() + margin), QPoint(x1, option->rect.bottom() - margin));
717 } else {
718 int y1 = option->rect.center().y();
719 painter->drawLine(QPoint(option->rect.left() + margin, y1), QPoint(option->rect.right() - margin, y1));
720 }
721 painter->setPen(pen);
722 }
723 break;
724
725 case PE_PanelTipLabel: {
726 XPThemeData theme(widget, painter, QLatin1String("TOOLTIP"), TTP_STANDARD, TTSS_NORMAL, option->rect);
727 d->drawBackground(theme);
728 break;
729 }
730
731 case PE_PanelItemViewItem:
732 {
733 const QStyleOptionViewItemV4 *vopt;
734 const QAbstractItemView *view = qobject_cast<const QAbstractItemView *>(widget);
735 bool newStyle = true;
736
737 if (qobject_cast<const QTableView*>(widget))
738 newStyle = false;
739
740 if (newStyle && view && (vopt = qstyleoption_cast<const QStyleOptionViewItemV4 *>(option))) {
741 bool selected = vopt->state & QStyle::State_Selected;
742 bool hover = vopt->state & QStyle::State_MouseOver;
743 bool active = vopt->state & QStyle::State_Active;
744
745 if (vopt->features & QStyleOptionViewItemV2::Alternate)
746 painter->fillRect(vopt->rect, vopt->palette.alternateBase());
747
748 QPalette::ColorGroup cg = vopt->state & QStyle::State_Enabled
749 ? QPalette::Normal : QPalette::Disabled;
750 if (cg == QPalette::Normal && !(vopt->state & QStyle::State_Active))
751 cg = QPalette::Inactive;
752
753 QRect textRect = subElementRect(QStyle::SE_ItemViewItemText, option, widget);
754 QRect itemRect = subElementRect(QStyle::SE_ItemViewItemFocusRect, option, widget).adjusted(-1, 0, 1, 0);
755 itemRect.setTop(vopt->rect.top());
756 itemRect.setBottom(vopt->rect.bottom());
757
758 QSize sectionSize = itemRect.size();
759 if (vopt->showDecorationSelected)
760 sectionSize = vopt->rect.size();
761
762 if (view->selectionBehavior() == QAbstractItemView::SelectRows)
763 sectionSize.setWidth(vopt->rect.width());
764 if (view->selectionMode() == QAbstractItemView::NoSelection)
765 hover = false;
766 QPixmap pixmap;
767
768 if (vopt->backgroundBrush.style() != Qt::NoBrush) {
769 QPointF oldBO = painter->brushOrigin();
770 painter->setBrushOrigin(vopt->rect.topLeft());
771 painter->fillRect(vopt->rect, vopt->backgroundBrush);
772 }
773
774 if (hover || selected) {
775 QString key = QString::fromLatin1("qvdelegate-%1-%2-%3-%4-%5").arg(sectionSize.width())
776 .arg(sectionSize.height()).arg(selected).arg(active).arg(hover);
777 if (!QPixmapCache::find(key, pixmap)) {
778 pixmap = QPixmap(sectionSize);
779 pixmap.fill(Qt::transparent);
780
781 int state;
782 if (selected && hover)
783 state = LISS_HOTSELECTED;
784 else if (selected && !active)
785 state = LISS_SELECTEDNOTFOCUS;
786 else if (selected)
787 state = LISS_SELECTED;
788 else
789 state = LISS_HOT;
790
791 QPainter pixmapPainter(&pixmap);
792 XPThemeData theme(d->treeViewHelper(), &pixmapPainter, QLatin1String("TREEVIEW"),
793 LVP_LISTITEM, state, QRect(0, 0, sectionSize.width(), sectionSize.height()));
794 if (theme.isValid()) {
795 d->drawBackground(theme);
796 } else {
797 QWindowsXPStyle::drawPrimitive(PE_PanelItemViewItem, option, painter, widget);
798 break;;
799 }
800 QPixmapCache::insert(key, pixmap);
801 }
802
803 if (vopt->showDecorationSelected) {
804 const int frame = 2; //Assumes a 2 pixel pixmap border
805 QRect srcRect = QRect(0, 0, sectionSize.width(), sectionSize.height());
806 QRect pixmapRect = vopt->rect;
807 bool reverse = vopt->direction == Qt::RightToLeft;
808 bool leftSection = vopt->viewItemPosition == QStyleOptionViewItemV4::Beginning;
809 bool rightSection = vopt->viewItemPosition == QStyleOptionViewItemV4::End;
810 if (vopt->viewItemPosition == QStyleOptionViewItemV4::OnlyOne
811 || vopt->viewItemPosition == QStyleOptionViewItemV4::Invalid)
812 painter->drawPixmap(pixmapRect.topLeft(), pixmap);
813 else if (reverse ? rightSection : leftSection){
814 painter->drawPixmap(QRect(pixmapRect.topLeft(),
815 QSize(frame, pixmapRect.height())), pixmap,
816 QRect(QPoint(0, 0), QSize(frame, pixmapRect.height())));
817 painter->drawPixmap(pixmapRect.adjusted(frame, 0, 0, 0),
818 pixmap, srcRect.adjusted(frame, 0, -frame, 0));
819 } else if (reverse ? leftSection : rightSection) {
820 painter->drawPixmap(QRect(pixmapRect.topRight() - QPoint(frame - 1, 0),
821 QSize(frame, pixmapRect.height())), pixmap,
822 QRect(QPoint(pixmapRect.width() - frame, 0),
823 QSize(frame, pixmapRect.height())));
824 painter->drawPixmap(pixmapRect.adjusted(0, 0, -frame, 0),
825 pixmap, srcRect.adjusted(frame, 0, -frame, 0));
826 } else if (vopt->viewItemPosition == QStyleOptionViewItemV4::Middle)
827 painter->drawPixmap(pixmapRect, pixmap,
828 srcRect.adjusted(frame, 0, -frame, 0));
829 } else {
830 if (vopt->text.isEmpty() && vopt->icon.isNull())
831 break;
832 painter->drawPixmap(itemRect.topLeft(), pixmap);
833 }
834 }
835 } else {
836 QWindowsXPStyle::drawPrimitive(element, option, painter, widget);
837 }
838 break;
839 }
840 case PE_Widget:
841 {
842 const QDialogButtonBox *buttonBox = 0;
843
844 if (qobject_cast<const QMessageBox *> (widget))
845 buttonBox = qFindChild<const QDialogButtonBox *>(widget,QLatin1String("qt_msgbox_buttonbox"));
846#ifndef QT_NO_INPUTDIALOG
847 else if (qobject_cast<const QInputDialog *> (widget))
848 buttonBox = qFindChild<const QDialogButtonBox *>(widget,QLatin1String("qt_inputdlg_buttonbox"));
849#endif // QT_NO_INPUTDIALOG
850
851 if (buttonBox) {
852 //draw white panel part
853 XPThemeData theme(widget, painter, QLatin1String("TASKDIALOG"), TDLG_PRIMARYPANEL, 0, option->rect);
854 QRect toprect = option->rect;
855 toprect.setBottom(buttonBox->geometry().top());
856 theme.rect = toprect;
857 d->drawBackground(theme);
858
859 //draw bottom panel part
860 QRect buttonRect = option->rect;
861 buttonRect.setTop(buttonBox->geometry().top());
862 theme.rect = buttonRect;
863 theme.partId = TDLG_SECONDARYPANEL;
864 d->drawBackground(theme);
865 }
866 }
867 break;
868 default:
869 QWindowsXPStyle::drawPrimitive(element, option, painter, widget);
870 break;
871 }
872}
873
874
875/*!
876 \internal
877
878 see drawPrimitive for comments on the animation support
879 */
880void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption *option,
881 QPainter *painter, const QWidget *widget) const
882{
883 QWindowsVistaStylePrivate *d = const_cast<QWindowsVistaStylePrivate*>(d_func());
884
885 if (!QWindowsVistaStylePrivate::useVista()) {
886 QWindowsStyle::drawControl(element, option, painter, widget);
887 return;
888 }
889
890 bool selected = option->state & State_Selected;
891 bool pressed = option->state & State_Sunken;
892 bool disabled = !(option->state & State_Enabled);
893
894 int state = option->state;
895 QString name;
896
897 QRect rect(option->rect);
898 State flags = option->state;
899 int partId = 0;
900 int stateId = 0;
901
902 QRect oldRect;
903 QRect newRect;
904
905 if (d->transitionsEnabled() && widget) {
906 if (const QStyleOptionButton *button = qstyleoption_cast<const QStyleOptionButton *>(option)) {
907 if ((qobject_cast<const QPushButton*>(widget) && element == CE_PushButtonBevel))
908 {
909 QWidget *w = const_cast<QWidget *> (widget);
910 int oldState = w->property("_q_stylestate").toInt();
911 oldRect = w->property("_q_stylerect").toRect();
912 newRect = w->rect();
913 w->setProperty("_q_stylestate", (int)option->state);
914 w->setProperty("_q_stylerect", w->rect());
915
916 bool wasDefault = w->property("_q_isdefault").toBool();
917 bool isDefault = button->features & QStyleOptionButton::DefaultButton;
918 w->setProperty("_q_isdefault", isDefault);
919
920 bool doTransition = ((state & State_Sunken) != (oldState & State_Sunken) ||
921 (state & State_On) != (oldState & State_On) ||
922 (state & State_MouseOver) != (oldState & State_MouseOver));
923
924 if (oldRect != newRect || (wasDefault && !isDefault))
925 {
926 doTransition = false;
927 d->stopAnimation(widget);
928 }
929
930 if (doTransition) {
931 QImage startImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
932 QImage endImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
933 QWindowsVistaAnimation *anim = d->widgetAnimation(widget);
934
935 QStyleOptionButton opt = *button;
936 opt.state = (QStyle::State)oldState;
937
938 startImage.fill(0);
939 QWindowsVistaTransition *t = new QWindowsVistaTransition;
940 t->setWidget(w);
941 QPainter startPainter(&startImage);
942
943 if (!anim) {
944 proxy()->drawControl(element, &opt, &startPainter, 0 /* Intentional */);
945 } else {
946 anim->paint(&startPainter, &opt);
947 d->stopAnimation(widget);
948 }
949
950 t->setStartImage(startImage);
951 d->startAnimation(t);
952
953 endImage.fill(0);
954 QPainter endPainter(&endImage);
955 proxy()->drawControl(element, option, &endPainter, 0 /* Intentional */);
956 t->setEndImage(endImage);
957 int duration = 0;
958 HTHEME theme = pOpenThemeData(0, L"Button");
959
960 int fromState = buttonStateId(oldState, BP_PUSHBUTTON);
961 int toState = buttonStateId(option->state, BP_PUSHBUTTON);
962 if (pGetThemeTransitionDuration(theme, BP_PUSHBUTTON, fromState, toState, TMT_TRANSITIONDURATIONS, &duration) == S_OK)
963 t->setDuration(duration);
964 else
965 t->setDuration(0);
966 t->setStartTime(QTime::currentTime());
967 }
968 }
969 }
970 }
971 switch (element) {
972 case CE_PushButtonBevel:
973 if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option))
974 {
975
976 if (QWindowsVistaAnimation *anim = d->widgetAnimation(widget)) {
977 anim->paint(painter, option);
978 } else {
979 name = QLatin1String("BUTTON");
980 partId = BP_PUSHBUTTON;
981 if (btn->features & QStyleOptionButton::CommandLinkButton)
982 partId = BP_COMMANDLINK;
983 bool justFlat = (btn->features & QStyleOptionButton::Flat) && !(flags & (State_On|State_Sunken));
984 if (!(flags & State_Enabled) && !(btn->features & QStyleOptionButton::Flat))
985 stateId = PBS_DISABLED;
986 else if (justFlat)
987 ;
988 else if (flags & (State_Sunken | State_On))
989 stateId = PBS_PRESSED;
990 else if (flags & State_MouseOver)
991 stateId = PBS_HOT;
992 else if (btn->features & QStyleOptionButton::DefaultButton && (state & State_Active))
993 stateId = PBS_DEFAULTED;
994 else
995 stateId = PBS_NORMAL;
996
997 if (!justFlat) {
998
999 if (widget && d->transitionsEnabled() && (btn->features & QStyleOptionButton::DefaultButton) &&
1000 !(state & (State_Sunken | State_On)) && !(state & State_MouseOver) &&
1001 (state & State_Enabled) && (state & State_Active))
1002 {
1003 QWindowsVistaAnimation *anim = d->widgetAnimation(widget);
1004 if (!anim && widget) {
1005 QImage startImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
1006 startImage.fill(0);
1007 QImage alternateImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
1008 alternateImage.fill(0);
1009
1010 QWindowsVistaPulse *pulse = new QWindowsVistaPulse;
1011 pulse->setWidget(const_cast<QWidget*>(widget));
1012
1013 QPainter startPainter(&startImage);
1014 stateId = PBS_DEFAULTED;
1015 XPThemeData theme(widget, &startPainter, name, partId, stateId, rect);
1016 d->drawBackground(theme);
1017
1018 QPainter alternatePainter(&alternateImage);
1019 theme.stateId = PBS_DEFAULTED_ANIMATING;
1020 theme.painter = &alternatePainter;
1021 d->drawBackground(theme);
1022 pulse->setPrimaryImage(startImage);
1023 pulse->setAlternateImage(alternateImage);
1024 pulse->setStartTime(QTime::currentTime());
1025 pulse->setDuration(2000);
1026 d->startAnimation(pulse);
1027 anim = pulse;
1028 }
1029
1030 if (anim)
1031 anim->paint(painter, option);
1032 else {
1033 XPThemeData theme(widget, painter, name, partId, stateId, rect);
1034 d->drawBackground(theme);
1035 }
1036 }
1037 else {
1038 d->stopAnimation(widget);
1039 XPThemeData theme(widget, painter, name, partId, stateId, rect);
1040 d->drawBackground(theme);
1041 }
1042 }
1043 }
1044 if (btn->features & QStyleOptionButton::HasMenu) {
1045 int mbiw = 0, mbih = 0;
1046 XPThemeData theme(widget, 0, QLatin1String("TOOLBAR"), TP_DROPDOWNBUTTON);
1047 if (theme.isValid()) {
1048 SIZE size;
1049 if (pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size) == S_OK) {
1050 mbiw = size.cx;
1051 mbih = size.cy;
1052 }
1053 }
1054 QRect ir = subElementRect(SE_PushButtonContents, option, 0);
1055 QStyleOptionButton newBtn = *btn;
1056 newBtn.rect = QStyle::visualRect(option->direction, option->rect,
1057 QRect(ir.right() - mbiw - 2,
1058 option->rect.top() + (option->rect.height()/2) - (mbih/2),
1059 mbiw + 1, mbih + 1));
1060 proxy()->drawPrimitive(PE_IndicatorArrowDown, &newBtn, painter, widget);
1061 }
1062 return;
1063 }
1064 break;
1065#ifndef QT_NO_PROGRESSBAR
1066 case CE_ProgressBarContents:
1067 if (const QStyleOptionProgressBar *bar
1068 = qstyleoption_cast<const QStyleOptionProgressBar *>(option)) {
1069 int stateId = MBI_NORMAL;
1070 if (disabled)
1071 stateId = MBI_DISABLED;
1072 bool isIndeterminate = (bar->minimum == 0 && bar->maximum == 0);
1073 bool vertical = false;
1074 bool inverted = false;
1075 if (const QStyleOptionProgressBarV2 *pb2 = qstyleoption_cast<const QStyleOptionProgressBarV2 *>(option)) {
1076 vertical = (pb2->orientation == Qt::Vertical);
1077 inverted = pb2->invertedAppearance;
1078 }
1079
1080 if (const QProgressBar *progressbar = qobject_cast<const QProgressBar *>(widget)) {
1081 if (((progressbar->value() > 0 && d->transitionsEnabled()) || isIndeterminate)) {
1082 if (!d->widgetAnimation(progressbar) && progressbar->value() < progressbar->maximum()) {
1083 QWindowsVistaAnimation *a = new QWindowsVistaAnimation;
1084 a->setWidget(const_cast<QWidget*>(widget));
1085 a->setStartTime(QTime::currentTime());
1086 d->startAnimation(a);
1087 }
1088 } else {
1089 d->stopAnimation(progressbar);
1090 }
1091 }
1092
1093 XPThemeData theme(widget, painter, QLatin1String("PROGRESS"), vertical ? PP_FILLVERT : PP_FILL);
1094 theme.rect = option->rect;
1095 bool reverse = (bar->direction == Qt::LeftToRight && inverted) || (bar->direction == Qt::RightToLeft && !inverted);
1096 QTime current = QTime::currentTime();
1097
1098 if (isIndeterminate) {
1099 if (QWindowsVistaAnimation *a = d->widgetAnimation(widget)) {
1100 int glowSize = 120;
1101 int animationWidth = glowSize * 2 + (vertical ? theme.rect.height() : theme.rect.width());
1102 int animOffset = a->startTime().msecsTo(current) / 4;
1103 if (animOffset > animationWidth)
1104 a->setStartTime(QTime::currentTime());
1105 painter->save();
1106 painter->setClipRect(theme.rect);
1107 QRect animRect;
1108 QSize pixmapSize(14, 14);
1109 if (vertical) {
1110 animRect = QRect(theme.rect.left(),
1111 inverted ? rect.top() - glowSize + animOffset :
1112 rect.bottom() + glowSize - animOffset,
1113 rect.width(), glowSize);
1114 pixmapSize.setHeight(animRect.height());
1115 } else {
1116 animRect = QRect(rect.left() - glowSize + animOffset,
1117 rect.top(), glowSize, rect.height());
1118 animRect = QStyle::visualRect(reverse ? Qt::RightToLeft : Qt::LeftToRight,
1119 option->rect, animRect);
1120 pixmapSize.setWidth(animRect.width());
1121 }
1122 QString name = QString::fromLatin1("qiprogress-%1-%2").arg(pixmapSize.width()).arg(pixmapSize.height());
1123 QPixmap pixmap;
1124 if (!QPixmapCache::find(name, pixmap)) {
1125 QImage image(pixmapSize, QImage::Format_ARGB32);
1126 image.fill(Qt::transparent);
1127 QPainter imagePainter(&image);
1128 theme.painter = &imagePainter;
1129 theme.partId = vertical ? PP_FILLVERT : PP_FILL;
1130 theme.rect = QRect(QPoint(0,0), theme.rect.size());
1131 QLinearGradient alphaGradient(0, 0, vertical ? 0 : image.width(),
1132 vertical ? image.height() : 0);
1133 alphaGradient.setColorAt(0, QColor(0, 0, 0, 0));
1134 alphaGradient.setColorAt(0.5, QColor(0, 0, 0, 220));
1135 alphaGradient.setColorAt(1, QColor(0, 0, 0, 0));
1136 imagePainter.fillRect(image.rect(), alphaGradient);
1137 imagePainter.setCompositionMode(QPainter::CompositionMode_SourceIn);
1138 d->drawBackground(theme);
1139 imagePainter.end();
1140 pixmap = QPixmap::fromImage(image);
1141 QPixmapCache::insert(name, pixmap);
1142 }
1143 painter->drawPixmap(animRect, pixmap);
1144 painter->restore();
1145 }
1146 }
1147 else {
1148 qint64 progress = qMax<qint64>(bar->progress, bar->minimum); // workaround for bug in QProgressBar
1149
1150 if (vertical) {
1151 int maxHeight = option->rect.height();
1152 int minHeight = 0;
1153 double vc6_workaround = ((progress - qint64(bar->minimum)) / qMax(double(1.0), double(qint64(bar->maximum) - qint64(bar->minimum))) * maxHeight);
1154 int height = isIndeterminate ? maxHeight: qMax(int(vc6_workaround), minHeight);
1155 theme.rect.setHeight(height);
1156 if (!inverted)
1157 theme.rect.moveTop(rect.height() - theme.rect.height());
1158 } else {
1159 int maxWidth = option->rect.width();
1160 int minWidth = 0;
1161 double vc6_workaround = ((progress - qint64(bar->minimum)) / qMax(double(1.0), double(qint64(bar->maximum) - qint64(bar->minimum))) * maxWidth);
1162 int width = isIndeterminate ? maxWidth : qMax(int(vc6_workaround), minWidth);
1163 theme.rect.setWidth(width);
1164 theme.rect = QStyle::visualRect(reverse ? Qt::RightToLeft : Qt::LeftToRight,
1165 option->rect, theme.rect);
1166 }
1167 d->drawBackground(theme);
1168
1169 if (QWindowsVistaAnimation *a = d->widgetAnimation(widget)) {
1170 int glowSize = 140;
1171 int animationWidth = glowSize * 2 + (vertical ? theme.rect.height() : theme.rect.width());
1172 int animOffset = a->startTime().msecsTo(current) / 4;
1173 theme.partId = vertical ? PP_MOVEOVERLAYVERT : PP_MOVEOVERLAY;
1174 if (animOffset > animationWidth) {
1175 if (bar->progress < bar->maximum)
1176 a->setStartTime(QTime::currentTime());
1177 else
1178 d->stopAnimation(widget); //we stop the glow motion only after it has
1179 //moved out of view
1180 }
1181 painter->save();
1182 painter->setClipRect(theme.rect);
1183 if (vertical) {
1184 theme.rect = QRect(theme.rect.left(),
1185 inverted ? rect.top() - glowSize + animOffset :
1186 rect.bottom() + glowSize - animOffset,
1187 rect.width(), glowSize);
1188 } else {
1189 theme.rect = QRect(rect.left() - glowSize + animOffset,rect.top(), glowSize, rect.height());
1190 theme.rect = QStyle::visualRect(reverse ? Qt::RightToLeft : Qt::LeftToRight, option->rect, theme.rect);
1191 }
1192 d->drawBackground(theme);
1193 painter->restore();
1194 }
1195 }
1196 }
1197 break;
1198#endif // QT_NO_PROGRESSBAR
1199 case CE_MenuBarItem:
1200 {
1201
1202 if (const QStyleOptionMenuItem *mbi = qstyleoption_cast<const QStyleOptionMenuItem *>(option))
1203 {
1204 if (mbi->menuItemType == QStyleOptionMenuItem::DefaultItem)
1205 break;
1206
1207 QPalette::ColorRole textRole = disabled ? QPalette::Text : QPalette::ButtonText;
1208 QPixmap pix = mbi->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize, option, widget), QIcon::Normal);
1209
1210 uint alignment = Qt::AlignCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine;
1211 if (!proxy()->styleHint(SH_UnderlineShortcut, mbi, widget))
1212 alignment |= Qt::TextHideMnemonic;
1213
1214 //The rect adjustment is a workaround for the menu not really filling its background.
1215 XPThemeData theme(widget, painter, QLatin1String("MENU"), MENU_BARBACKGROUND, 0, option->rect.adjusted(-1, 0, 2, 1));
1216 d->drawBackground(theme);
1217
1218 int stateId = MBI_NORMAL;
1219 if (disabled)
1220 stateId = MBI_DISABLED;
1221 else if (pressed)
1222 stateId = MBI_PUSHED;
1223 else if (selected)
1224 stateId = MBI_HOT;
1225
1226 XPThemeData theme2(widget, painter, QLatin1String("MENU"), MENU_BARITEM, stateId, option->rect);
1227 d->drawBackground(theme2);
1228
1229 if (!pix.isNull())
1230 drawItemPixmap(painter, mbi->rect, alignment, pix);
1231 else
1232 drawItemText(painter, mbi->rect, alignment, mbi->palette, mbi->state & State_Enabled, mbi->text, textRole);
1233 }
1234 }
1235 break;
1236#ifndef QT_NO_MENU
1237 case CE_MenuItem:
1238 if (const QStyleOptionMenuItem *menuitem = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) {
1239 // windows always has a check column, regardless whether we have an icon or not
1240 int checkcol = 28;
1241 {
1242 SIZE size;
1243 MARGINS margins;
1244 XPThemeData theme(widget, 0, QLatin1String("MENU"), MENU_POPUPCHECKBACKGROUND, MBI_HOT);
1245 pGetThemePartSize(theme.handle(), NULL, MENU_POPUPCHECK, 0, NULL,TS_TRUE, &size);
1246 pGetThemeMargins(theme.handle(), NULL, MENU_POPUPCHECK, 0, TMT_CONTENTMARGINS, NULL, &margins);
1247 checkcol = qMax(menuitem->maxIconWidth, int(6 + size.cx + margins.cxLeftWidth + margins.cxRightWidth));
1248 }
1249 QColor darkLine = option->palette.background().color().darker(108);
1250 QColor lightLine = option->palette.background().color().lighter(107);
1251 QRect rect = option->rect;
1252 QStyleOptionMenuItem mbiCopy = *menuitem;
1253
1254 //draw vertical menu line
1255 QPoint p1 = QStyle::visualPos(option->direction, menuitem->rect, QPoint(checkcol, rect.top()));
1256 QPoint p2 = QStyle::visualPos(option->direction, menuitem->rect, QPoint(checkcol, rect.bottom()));
1257 QRect gutterRect(p1.x(), p1.y(), 3, p2.y() - p1.y() + 1);
1258 XPThemeData theme2(widget, painter, QLatin1String("MENU"), MENU_POPUPGUTTER, stateId, gutterRect);
1259 d->drawBackground(theme2);
1260
1261 int x, y, w, h;
1262 menuitem->rect.getRect(&x, &y, &w, &h);
1263 int tab = menuitem->tabWidth;
1264 bool dis = !(menuitem->state & State_Enabled);
1265 bool checked = menuitem->checkType != QStyleOptionMenuItem::NotCheckable
1266 ? menuitem->checked : false;
1267 bool act = menuitem->state & State_Selected;
1268
1269 if (menuitem->menuItemType == QStyleOptionMenuItem::Separator) {
1270 int yoff = y-2 + h / 2;
1271 QPoint p1 = QPoint(x + checkcol, yoff);
1272 QPoint p2 = QPoint(x + w + 6 , yoff);
1273 stateId = MBI_HOT;
1274 QRect subRect(p1.x(), p1.y(), p2.x() - p1.x(), 6);
1275 subRect = QStyle::visualRect(option->direction, option->rect, subRect );
1276 XPThemeData theme2(widget, painter, QLatin1String("MENU"), MENU_POPUPSEPARATOR, stateId, subRect);
1277 d->drawBackground(theme2);
1278 return;
1279 }
1280
1281 QRect vCheckRect = visualRect(option->direction, menuitem->rect, QRect(menuitem->rect.x(),
1282 menuitem->rect.y(), checkcol - 6, menuitem->rect.height()));
1283
1284 if (act) {
1285 stateId = MBI_HOT;
1286 XPThemeData theme2(widget, painter, QLatin1String("MENU"), MENU_POPUPITEM, stateId, option->rect);
1287 d->drawBackground(theme2);
1288 }
1289
1290 if (checked) {
1291 XPThemeData theme(widget, painter, QLatin1String("MENU"), MENU_POPUPCHECKBACKGROUND,
1292 menuitem->icon.isNull() ? MBI_HOT : MBI_PUSHED, vCheckRect);
1293 SIZE size;
1294 MARGINS margins;
1295 pGetThemePartSize(theme.handle(), NULL, MENU_POPUPCHECK, 0, NULL,TS_TRUE, &size);
1296 pGetThemeMargins(theme.handle(), NULL, MENU_POPUPCHECK, 0,
1297 TMT_CONTENTMARGINS, NULL, &margins);
1298 QRect checkRect(0, 0, size.cx + margins.cxLeftWidth + margins.cxRightWidth ,
1299 size.cy + margins.cyBottomHeight + margins.cyTopHeight);
1300 checkRect.moveCenter(vCheckRect.center());
1301 theme.rect = checkRect;
1302
1303 d->drawBackground(theme);
1304
1305 if (menuitem->icon.isNull()) {
1306 checkRect = QRect(0, 0, size.cx, size.cy);
1307 checkRect.moveCenter(theme.rect.center());
1308 theme.rect = checkRect;
1309
1310 theme.partId = MENU_POPUPCHECK;
1311 bool bullet = menuitem->checkType & QStyleOptionMenuItem::Exclusive;
1312 if (dis)
1313 theme.stateId = bullet ? MC_BULLETDISABLED: MC_CHECKMARKDISABLED;
1314 else
1315 theme.stateId = bullet ? MC_BULLETNORMAL: MC_CHECKMARKNORMAL;
1316 d->drawBackground(theme);
1317 }
1318 }
1319
1320 if (!menuitem->icon.isNull()) {
1321 QIcon::Mode mode = dis ? QIcon::Disabled : QIcon::Normal;
1322 if (act && !dis)
1323 mode = QIcon::Active;
1324 QPixmap pixmap;
1325 if (checked)
1326 pixmap = menuitem->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize, option, widget), mode, QIcon::On);
1327 else
1328 pixmap = menuitem->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize, option, widget), mode);
1329 int pixw = pixmap.width();
1330 int pixh = pixmap.height();
1331 QRect pmr(0, 0, pixw, pixh);
1332 pmr.moveCenter(vCheckRect.center());
1333 painter->setPen(menuitem->palette.text().color());
1334 painter->drawPixmap(pmr.topLeft(), pixmap);
1335 }
1336
1337 painter->setPen(menuitem->palette.buttonText().color());
1338
1339 QColor discol;
1340 if (dis) {
1341 discol = menuitem->palette.text().color();
1342 painter->setPen(discol);
1343 }
1344
1345 int xm = windowsItemFrame + checkcol + windowsItemHMargin;
1346 int xpos = menuitem->rect.x() + xm;
1347 QRect textRect(xpos, y + windowsItemVMargin, w - xm - windowsRightBorder - tab + 1, h - 2 * windowsItemVMargin);
1348 QRect vTextRect = visualRect(option->direction, menuitem->rect, textRect);
1349 QString s = menuitem->text;
1350 if (!s.isEmpty()) { // draw text
1351 painter->save();
1352 int t = s.indexOf(QLatin1Char('\t'));
1353 int text_flags = Qt::AlignVCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine;
1354 if (!proxy()->styleHint(SH_UnderlineShortcut, menuitem, widget))
1355 text_flags |= Qt::TextHideMnemonic;
1356 text_flags |= Qt::AlignLeft;
1357 if (t >= 0) {
1358 QRect vShortcutRect = visualRect(option->direction, menuitem->rect,
1359 QRect(textRect.topRight(), QPoint(menuitem->rect.right(), textRect.bottom())));
1360 painter->drawText(vShortcutRect, text_flags, s.mid(t + 1));
1361 s = s.left(t);
1362 }
1363 QFont font = menuitem->font;
1364 if (menuitem->menuItemType == QStyleOptionMenuItem::DefaultItem)
1365 font.setBold(true);
1366 painter->setFont(font);
1367 painter->setPen(discol);
1368 painter->drawText(vTextRect, text_flags, s.left(t));
1369 painter->restore();
1370 }
1371 if (menuitem->menuItemType == QStyleOptionMenuItem::SubMenu) {// draw sub menu arrow
1372 int dim = (h - 2 * windowsItemFrame) / 2;
1373 PrimitiveElement arrow;
1374 arrow = (option->direction == Qt::RightToLeft) ? PE_IndicatorArrowLeft : PE_IndicatorArrowRight;
1375 xpos = x + w - windowsArrowHMargin - windowsItemFrame - dim;
1376 QRect vSubMenuRect = visualRect(option->direction, menuitem->rect, QRect(xpos, y + h / 2 - dim / 2, dim, dim));
1377 QStyleOptionMenuItem newMI = *menuitem;
1378 newMI.rect = vSubMenuRect;
1379 newMI.state = dis ? State_None : State_Enabled;
1380 proxy()->drawPrimitive(arrow, &newMI, painter, widget);
1381 }
1382 }
1383 break;
1384#endif // QT_NO_MENU
1385 case CE_HeaderSection:
1386 if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) {
1387 name = QLatin1String("HEADER");
1388 partId = HP_HEADERITEM;
1389 if (flags & State_Sunken)
1390 stateId = HIS_PRESSED;
1391 else if (flags & State_MouseOver)
1392 stateId = HIS_HOT;
1393 else
1394 stateId = HIS_NORMAL;
1395
1396 if (header->sortIndicator != QStyleOptionHeader::None)
1397 stateId += 3;
1398
1399 XPThemeData theme(widget, painter, name, partId, stateId, option->rect);
1400 d->drawBackground(theme);
1401 }
1402 break;
1403 case CE_MenuBarEmptyArea:
1404 {
1405 stateId = MBI_NORMAL;
1406 if (!(state & State_Enabled))
1407 stateId = MBI_DISABLED;
1408 XPThemeData theme(widget, painter, QLatin1String("MENU"), MENU_BARBACKGROUND, stateId, option->rect);
1409 d->drawBackground(theme);
1410 }
1411 break;
1412 case CE_ToolBar:
1413 if (const QStyleOptionToolBar *toolbar = qstyleoption_cast<const QStyleOptionToolBar *>(option)) {
1414 QPalette pal = option->palette;
1415 pal.setColor(QPalette::Dark, option->palette.background().color().darker(130));
1416 QStyleOptionToolBar copyOpt = *toolbar;
1417 copyOpt.palette = pal;
1418 QWindowsStyle::drawControl(element, &copyOpt, painter, widget);
1419 }
1420 break;
1421 case CE_DockWidgetTitle:
1422 if (const QDockWidget *dockWidget = qobject_cast<const QDockWidget *>(widget)) {
1423 QRect rect = option->rect;
1424 if (dockWidget->isFloating()) {
1425 QWindowsXPStyle::drawControl(element, option, painter, widget);
1426 break; //otherwise fall through
1427 }
1428
1429 if (const QStyleOptionDockWidget *dwOpt = qstyleoption_cast<const QStyleOptionDockWidget *>(option)) {
1430
1431 const QStyleOptionDockWidgetV2 *v2
1432 = qstyleoption_cast<const QStyleOptionDockWidgetV2*>(dwOpt);
1433 bool verticalTitleBar = v2 == 0 ? false : v2->verticalTitleBar;
1434
1435 if (verticalTitleBar) {
1436 QSize s = rect.size();
1437 s.transpose();
1438 rect.setSize(s);
1439
1440 painter->translate(rect.left() - 1, rect.top() + rect.width());
1441 painter->rotate(-90);
1442 painter->translate(-rect.left() + 1, -rect.top());
1443 }
1444
1445 painter->setBrush(option->palette.background().color().darker(110));
1446 painter->setPen(option->palette.background().color().darker(130));
1447 painter->drawRect(rect.adjusted(0, 1, -1, -3));
1448
1449 int buttonMargin = 4;
1450 int mw = proxy()->pixelMetric(QStyle::PM_DockWidgetTitleMargin, dwOpt, widget);
1451 int fw = proxy()->pixelMetric(PM_DockWidgetFrameWidth, dwOpt, widget);
1452 const QDockWidget *dw = qobject_cast<const QDockWidget *>(widget);
1453 bool isFloating = dw != 0 && dw->isFloating();
1454
1455 QRect r = option->rect.adjusted(0, 2, -1, -3);
1456 QRect titleRect = r;
1457
1458 if (dwOpt->closable) {
1459 QSize sz = standardIcon(QStyle::SP_TitleBarCloseButton, dwOpt, widget).actualSize(QSize(10, 10));
1460 titleRect.adjust(0, 0, -sz.width() - mw - buttonMargin, 0);
1461 }
1462
1463 if (dwOpt->floatable) {
1464 QSize sz = standardIcon(QStyle::SP_TitleBarMaxButton, dwOpt, widget).actualSize(QSize(10, 10));
1465 titleRect.adjust(0, 0, -sz.width() - mw - buttonMargin, 0);
1466 }
1467
1468 if (isFloating) {
1469 titleRect.adjust(0, -fw, 0, 0);
1470 if (widget != 0 && widget->windowIcon().cacheKey() != QApplication::windowIcon().cacheKey())
1471 titleRect.adjust(titleRect.height() + mw, 0, 0, 0);
1472 } else {
1473 titleRect.adjust(mw, 0, 0, 0);
1474 if (!dwOpt->floatable && !dwOpt->closable)
1475 titleRect.adjust(0, 0, -mw, 0);
1476 }
1477 if (!verticalTitleBar)
1478 titleRect = visualRect(dwOpt->direction, r, titleRect);
1479
1480 if (!dwOpt->title.isEmpty()) {
1481 QString titleText = painter->fontMetrics().elidedText(dwOpt->title, Qt::ElideRight,
1482 verticalTitleBar ? titleRect.height() : titleRect.width());
1483 const int indent = painter->fontMetrics().descent();
1484 drawItemText(painter, rect.adjusted(indent + 1, 1, -indent - 1, -1),
1485 Qt::AlignLeft | Qt::AlignVCenter, dwOpt->palette,
1486 dwOpt->state & State_Enabled, titleText,
1487 QPalette::WindowText);
1488 }
1489 }
1490 break;
1491 }
1492#ifndef QT_NO_ITEMVIEWS
1493 case CE_ItemViewItem:
1494 {
1495 const QStyleOptionViewItemV4 *vopt;
1496 const QAbstractItemView *view = qobject_cast<const QAbstractItemView *>(widget);
1497 bool newStyle = true;
1498
1499 if (qobject_cast<const QTableView*>(widget))
1500 newStyle = false;
1501
1502 if (newStyle && view && (vopt = qstyleoption_cast<const QStyleOptionViewItemV4 *>(option))) {
1503 /*
1504 // We cannot currently get the correct selection color for "explorer style" views
1505 COLORREF cref = 0;
1506 XPThemeData theme(d->treeViewHelper(), 0, QLatin1String("LISTVIEW"), 0, 0);
1507 unsigned int res = pGetThemeColor(theme.handle(), LVP_LISTITEM, LISS_SELECTED, TMT_TEXTCOLOR, &cref);
1508 QColor textColor(GetRValue(cref), GetGValue(cref), GetBValue(cref));
1509 */
1510 QPalette palette = vopt->palette;
1511 palette.setColor(QPalette::All, QPalette::HighlightedText, palette.color(QPalette::Active, QPalette::Text));
1512 // Note that setting a saturated color here results in ugly XOR colors in the focus rect
1513 palette.setColor(QPalette::All, QPalette::Highlight, palette.base().color().darker(108));
1514 QStyleOptionViewItemV4 adjustedOption = *vopt;
1515 adjustedOption.palette = palette;
1516 // We hide the focusrect in singleselection as it is not required
1517 if ((view->selectionMode() == QAbstractItemView::SingleSelection)
1518 && !(vopt->state & State_KeyboardFocusChange))
1519 adjustedOption.state &= ~State_HasFocus;
1520 QWindowsXPStyle::drawControl(element, &adjustedOption, painter, widget);
1521 } else {
1522 QWindowsXPStyle::drawControl(element, option, painter, widget);
1523 }
1524 break;
1525 }
1526#endif // QT_NO_ITEMVIEWS
1527
1528 default:
1529 QWindowsXPStyle::drawControl(element, option, painter, widget);
1530 break;
1531 }
1532}
1533
1534/*!
1535 \internal
1536
1537 see drawPrimitive for comments on the animation support
1538
1539 */
1540void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyleOptionComplex *option,
1541 QPainter *painter, const QWidget *widget) const
1542{
1543 QWindowsVistaStylePrivate *d = const_cast<QWindowsVistaStylePrivate*>(d_func());
1544 if (!QWindowsVistaStylePrivate::useVista()) {
1545 QWindowsStyle::drawComplexControl(control, option, painter, widget);
1546 return;
1547 }
1548
1549 State state = option->state;
1550 SubControls sub = option->subControls;
1551 QRect r = option->rect;
1552
1553 int partId = 0;
1554 int stateId = 0;
1555
1556 State flags = option->state;
1557 if (widget && widget->testAttribute(Qt::WA_UnderMouse) && widget->isActiveWindow())
1558 flags |= State_MouseOver;
1559
1560 if (d->transitionsEnabled() && widget) {
1561 if ((qobject_cast<const QScrollBar *>(widget) && control == CC_ScrollBar)
1562#ifndef QT_NO_SPINBOX
1563 || (qobject_cast<const QAbstractSpinBox*>(widget) && control == CC_SpinBox)
1564#endif // QT_NO_SPINBOX
1565#ifndef QT_NO_COMBOBOX
1566 || (qobject_cast<const QComboBox*>(widget) && control == CC_ComboBox)
1567#endif // QT_NO_COMBOBOX
1568 )
1569 {
1570 QWidget *w = const_cast<QWidget *> (widget);
1571
1572 int oldState = w->property("_q_stylestate").toInt();
1573 int oldActiveControls = w->property("_q_stylecontrols").toInt();
1574 QRect oldRect = w->property("_q_stylerect").toRect();
1575 w->setProperty("_q_stylestate", (int)option->state);
1576 w->setProperty("_q_stylecontrols", (int)option->activeSubControls);
1577 w->setProperty("_q_stylerect", w->rect());
1578
1579 bool doTransition = ((state & State_Sunken) != (oldState & State_Sunken) ||
1580 (state & State_On) != (oldState & State_On) ||
1581 (state & State_MouseOver) != (oldState & State_MouseOver) ||
1582 oldActiveControls != option->activeSubControls);
1583
1584
1585 if (qstyleoption_cast<const QStyleOptionSlider *>(option)) {
1586 QRect oldSliderPos = w->property("_q_stylesliderpos").toRect();
1587 QRect currentPos = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget);
1588 w->setProperty("_q_stylesliderpos", currentPos);
1589 if (oldSliderPos != currentPos) {
1590 doTransition = false;
1591 d->stopAnimation(widget);
1592 }
1593 } else if (control == CC_SpinBox) {
1594 //spinboxes have a transition when focus changes
1595 if (!doTransition)
1596 doTransition = (state & State_HasFocus) != (oldState & State_HasFocus);
1597 }
1598
1599 if (oldRect != option->rect) {
1600 doTransition = false;
1601 d->stopAnimation(widget);
1602 }
1603
1604 if (doTransition) {
1605 QImage startImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
1606 QImage endImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
1607 QWindowsVistaAnimation *anim = d->widgetAnimation(widget);
1608 QWindowsVistaTransition *t = new QWindowsVistaTransition;
1609 t->setWidget(w);
1610 if (!anim) {
1611 if (const QStyleOptionComboBox *combo = qstyleoption_cast<const QStyleOptionComboBox*>(option)) {
1612 //Combo boxes are special cased to avoid cleartype issues
1613 startImage.fill(0);
1614 QPainter startPainter(&startImage);
1615 QStyleOptionComboBox startCombo = *combo;
1616 startCombo.state = (QStyle::State)oldState;
1617 startCombo.activeSubControls = (QStyle::SubControl)oldActiveControls;
1618 proxy()->drawComplexControl(control, &startCombo, &startPainter, 0 /* Intentional */);
1619 t->setStartImage(startImage);
1620 } else if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider*>(option)) {
1621 //This is a workaround for the direct3d engine as it currently has some issues with grabWindow
1622 startImage.fill(0);
1623 QPainter startPainter(&startImage);
1624 QStyleOptionSlider startSlider = *slider;
1625 startSlider.state = (QStyle::State)oldState;
1626 startSlider.activeSubControls = (QStyle::SubControl)oldActiveControls;
1627 proxy()->drawComplexControl(control, &startSlider, &startPainter, 0 /* Intentional */);
1628 t->setStartImage(startImage);
1629 } else {
1630 QPoint offset(0, 0);
1631 if (!widget->internalWinId())
1632 offset = widget->mapTo(widget->nativeParentWidget(), offset);
1633 t->setStartImage(QPixmap::grabWindow(widget->effectiveWinId(), offset.x(), offset.y(),
1634 option->rect.width(), option->rect.height()).toImage());
1635 }
1636 } else {
1637 startImage.fill(0);
1638 QPainter startPainter(&startImage);
1639 anim->paint(&startPainter, option);
1640 t->setStartImage(startImage);
1641 }
1642 d->startAnimation(t);
1643 endImage.fill(0);
1644 QPainter endPainter(&endImage);
1645 proxy()->drawComplexControl(control, option, &endPainter, 0 /* Intentional */);
1646 t->setEndImage(endImage);
1647 t->setStartTime(QTime::currentTime());
1648
1649 if (option->state & State_MouseOver || option->state & State_Sunken)
1650 t->setDuration(150);
1651 else
1652 t->setDuration(500);
1653 }
1654
1655 if (QWindowsVistaAnimation *anim = d->widgetAnimation(widget)) {
1656 anim->paint(painter, option);
1657 return;
1658 }
1659
1660 }
1661 }
1662
1663 switch (control) {
1664 case CC_ComboBox:
1665 if (const QStyleOptionComboBox *cmb = qstyleoption_cast<const QStyleOptionComboBox *>(option))
1666 {
1667 if (cmb->editable) {
1668 if (sub & SC_ComboBoxEditField) {
1669 partId = EP_EDITBORDER_NOSCROLL;
1670 if (!(flags & State_Enabled))
1671 stateId = ETS_DISABLED;
1672 else if (flags & State_MouseOver)
1673 stateId = ETS_HOT;
1674 else if (flags & State_HasFocus)
1675 stateId = ETS_FOCUSED;
1676 else
1677 stateId = ETS_NORMAL;
1678
1679 XPThemeData theme(widget, painter, QLatin1String("EDIT"), partId, stateId, r);
1680
1681 d->drawBackground(theme);
1682 }
1683 if (sub & SC_ComboBoxArrow) {
1684 QRect subRect = proxy()->subControlRect(CC_ComboBox, option, SC_ComboBoxArrow, widget);
1685 XPThemeData theme(widget, painter, QLatin1String("COMBOBOX"));
1686 theme.rect = subRect;
1687 partId = option->direction == Qt::RightToLeft ? CP_DROPDOWNBUTTONLEFT : CP_DROPDOWNBUTTONRIGHT;
1688
1689 if (!(cmb->state & State_Enabled))
1690 stateId = CBXS_DISABLED;
1691 else if (cmb->state & State_Sunken || cmb->state & State_On)
1692 stateId = CBXS_PRESSED;
1693 else if (cmb->state & State_MouseOver && option->activeSubControls & SC_ComboBoxArrow)
1694 stateId = CBXS_HOT;
1695 else
1696 stateId = CBXS_NORMAL;
1697
1698 theme.partId = partId;
1699 theme.stateId = stateId;
1700 d->drawBackground(theme);
1701 }
1702
1703 } else {
1704 if (sub & SC_ComboBoxFrame) {
1705 QStyleOptionButton btn;
1706 btn.QStyleOption::operator=(*option);
1707 btn.rect = option->rect.adjusted(-1, -1, 1, 1);
1708 if (sub & SC_ComboBoxArrow)
1709 btn.features = QStyleOptionButton::HasMenu;
1710 proxy()->drawControl(QStyle::CE_PushButton, &btn, painter, widget);
1711 }
1712 }
1713 }
1714 break;
1715 case CC_ScrollBar:
1716 if (const QStyleOptionSlider *scrollbar = qstyleoption_cast<const QStyleOptionSlider *>(option))
1717 {
1718 XPThemeData theme(widget, painter, QLatin1String("SCROLLBAR"));
1719
1720 bool maxedOut = (scrollbar->maximum == scrollbar->minimum);
1721 if (maxedOut)
1722 flags &= ~State_Enabled;
1723
1724 bool isHorz = flags & State_Horizontal;
1725 bool isRTL = option->direction == Qt::RightToLeft;
1726 if (sub & SC_ScrollBarAddLine) {
1727 theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarAddLine, widget);
1728 partId = SBP_ARROWBTN;
1729 if (!(flags & State_Enabled))
1730 stateId = (isHorz ? (isRTL ? ABS_LEFTDISABLED : ABS_RIGHTDISABLED) : ABS_DOWNDISABLED);
1731 else if (scrollbar->activeSubControls & SC_ScrollBarAddLine && (scrollbar->state & State_Sunken))
1732 stateId = (isHorz ? (isRTL ? ABS_LEFTPRESSED : ABS_RIGHTPRESSED) : ABS_DOWNPRESSED);
1733 else if (scrollbar->activeSubControls & SC_ScrollBarAddLine && (scrollbar->state & State_MouseOver))
1734 stateId = (isHorz ? (isRTL ? ABS_LEFTHOT : ABS_RIGHTHOT) : ABS_DOWNHOT);
1735 else if (scrollbar->state & State_MouseOver)
1736 stateId = (isHorz ? (isRTL ? ABS_LEFTHOVER : ABS_RIGHTHOVER) : ABS_DOWNHOVER);
1737 else
1738 stateId = (isHorz ? (isRTL ? ABS_LEFTNORMAL : ABS_RIGHTNORMAL) : ABS_DOWNNORMAL);
1739 theme.partId = partId;
1740 theme.stateId = stateId;
1741 d->drawBackground(theme);
1742 }
1743 if (sub & SC_ScrollBarSubLine) {
1744 theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSubLine, widget);
1745 partId = SBP_ARROWBTN;
1746 if (!(flags & State_Enabled))
1747 stateId = (isHorz ? (isRTL ? ABS_RIGHTDISABLED : ABS_LEFTDISABLED) : ABS_UPDISABLED);
1748 else if (scrollbar->activeSubControls & SC_ScrollBarSubLine && (scrollbar->state & State_Sunken))
1749 stateId = (isHorz ? (isRTL ? ABS_RIGHTPRESSED : ABS_LEFTPRESSED) : ABS_UPPRESSED);
1750 else if (scrollbar->activeSubControls & SC_ScrollBarSubLine && (scrollbar->state & State_MouseOver))
1751 stateId = (isHorz ? (isRTL ? ABS_RIGHTHOT : ABS_LEFTHOT) : ABS_UPHOT);
1752 else if (scrollbar->state & State_MouseOver)
1753 stateId = (isHorz ? (isRTL ? ABS_RIGHTHOVER : ABS_LEFTHOVER) : ABS_UPHOVER);
1754 else
1755 stateId = (isHorz ? (isRTL ? ABS_RIGHTNORMAL : ABS_LEFTNORMAL) : ABS_UPNORMAL);
1756 theme.partId = partId;
1757 theme.stateId = stateId;
1758 d->drawBackground(theme);
1759 }
1760 if (maxedOut) {
1761 theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget);
1762 theme.rect = theme.rect.united(proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSubPage, widget));
1763 theme.rect = theme.rect.united(proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarAddPage, widget));
1764 partId = flags & State_Horizontal ? SBP_LOWERTRACKHORZ : SBP_LOWERTRACKVERT;
1765 stateId = SCRBS_DISABLED;
1766 theme.partId = partId;
1767 theme.stateId = stateId;
1768 d->drawBackground(theme);
1769 } else {
1770 if (sub & SC_ScrollBarSubPage) {
1771 theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSubPage, widget);
1772 partId = flags & State_Horizontal ? SBP_UPPERTRACKHORZ : SBP_UPPERTRACKVERT;
1773 if (!(flags & State_Enabled))
1774 stateId = SCRBS_DISABLED;
1775 else if (scrollbar->activeSubControls & SC_ScrollBarSubPage && (scrollbar->state & State_Sunken))
1776 stateId = SCRBS_PRESSED;
1777 else if (scrollbar->activeSubControls & SC_ScrollBarSubPage && (scrollbar->state & State_MouseOver))
1778 stateId = SCRBS_HOT;
1779 else
1780 stateId = SCRBS_NORMAL;
1781 theme.partId = partId;
1782 theme.stateId = stateId;
1783 d->drawBackground(theme);
1784 }
1785 if (sub & SC_ScrollBarAddPage) {
1786 theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarAddPage, widget);
1787 partId = flags & State_Horizontal ? SBP_LOWERTRACKHORZ : SBP_LOWERTRACKVERT;
1788 if (!(flags & State_Enabled))
1789 stateId = SCRBS_DISABLED;
1790 else if (scrollbar->activeSubControls & SC_ScrollBarAddPage && (scrollbar->state & State_Sunken))
1791 stateId = SCRBS_PRESSED;
1792 else if (scrollbar->activeSubControls & SC_ScrollBarAddPage && (scrollbar->state & State_MouseOver))
1793 stateId = SCRBS_HOT;
1794 else
1795 stateId = SCRBS_NORMAL;
1796 theme.partId = partId;
1797 theme.stateId = stateId;
1798 d->drawBackground(theme);
1799 }
1800 if (sub & SC_ScrollBarSlider) {
1801 theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget);
1802 if (!(flags & State_Enabled))
1803 stateId = SCRBS_DISABLED;
1804 else if (scrollbar->activeSubControls & SC_ScrollBarSlider && (scrollbar->state & State_Sunken))
1805 stateId = SCRBS_PRESSED;
1806 else if (scrollbar->activeSubControls & SC_ScrollBarSlider && (scrollbar->state & State_MouseOver))
1807 stateId = SCRBS_HOT;
1808 else if (option->state & State_MouseOver)
1809 stateId = SCRBS_HOVER;
1810 else
1811 stateId = SCRBS_NORMAL;
1812
1813 // Draw handle
1814 theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget);
1815 theme.partId = flags & State_Horizontal ? SBP_THUMBBTNHORZ : SBP_THUMBBTNVERT;
1816 theme.stateId = stateId;
1817 d->drawBackground(theme);
1818
1819 // Calculate rect of gripper
1820 const int swidth = theme.rect.width();
1821 const int sheight = theme.rect.height();
1822
1823 MARGINS contentsMargin;
1824 RECT rect = theme.toRECT(theme.rect);
1825 pGetThemeMargins(theme.handle(), 0, theme.partId, theme.stateId, TMT_SIZINGMARGINS, &rect, &contentsMargin);
1826
1827 SIZE size;
1828 theme.partId = flags & State_Horizontal ? SBP_GRIPPERHORZ : SBP_GRIPPERVERT;
1829 pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size);
1830 int gw = size.cx, gh = size.cy;
1831
1832
1833 QRect gripperBounds;
1834 if (flags & State_Horizontal && ((swidth - contentsMargin.cxLeftWidth - contentsMargin.cxRightWidth) > gw)) {
1835 gripperBounds.setLeft(theme.rect.left() + swidth/2 - gw/2);
1836 gripperBounds.setTop(theme.rect.top() + sheight/2 - gh/2);
1837 gripperBounds.setWidth(gw);
1838 gripperBounds.setHeight(gh);
1839 } else if ((sheight - contentsMargin.cyTopHeight - contentsMargin.cyBottomHeight) > gh) {
1840 gripperBounds.setLeft(theme.rect.left() + swidth/2 - gw/2);
1841 gripperBounds.setTop(theme.rect.top() + sheight/2 - gh/2);
1842 gripperBounds.setWidth(gw);
1843 gripperBounds.setHeight(gh);
1844 }
1845
1846 // Draw gripper if there is enough space
1847 if (!gripperBounds.isEmpty() && flags & State_Enabled) {
1848 painter->save();
1849 XPThemeData grippBackground = theme;
1850 grippBackground.partId = flags & State_Horizontal ? SBP_LOWERTRACKHORZ : SBP_LOWERTRACKVERT;
1851 theme.rect = gripperBounds;
1852 painter->setClipRegion(d->region(theme));// Only change inside the region of the gripper
1853 d->drawBackground(grippBackground);// The gutter is the grippers background
1854 d->drawBackground(theme); // Transparent gripper ontop of background
1855 painter->restore();
1856 }
1857 }
1858 }
1859 }
1860 break;
1861#ifndef QT_NO_SPINBOX
1862 case CC_SpinBox:
1863 if (const QStyleOptionSpinBox *sb = qstyleoption_cast<const QStyleOptionSpinBox *>(option))
1864 {
1865 XPThemeData theme(widget, painter, QLatin1String("SPIN"));
1866 if (sb->frame && (sub & SC_SpinBoxFrame)) {
1867 partId = EP_EDITBORDER_NOSCROLL;
1868 if (!(flags & State_Enabled))
1869 stateId = ETS_DISABLED;
1870 else if (flags & State_MouseOver)
1871 stateId = ETS_HOT;
1872 else if (flags & State_HasFocus)
1873 stateId = ETS_SELECTED;
1874 else
1875 stateId = ETS_NORMAL;
1876
1877 XPThemeData ftheme(widget, painter, QLatin1String("EDIT"), partId, stateId, r);
1878 ftheme.noContent = true;
1879 d->drawBackground(ftheme);
1880 }
1881 if (sub & SC_SpinBoxUp) {
1882 theme.rect = proxy()->subControlRect(CC_SpinBox, option, SC_SpinBoxUp, widget).adjusted(0, 0, 0, 1);
1883 partId = SPNP_UP;
1884 if (!(sb->stepEnabled & QAbstractSpinBox::StepUpEnabled) || !(flags & State_Enabled))
1885 stateId = UPS_DISABLED;
1886 else if (sb->activeSubControls == SC_SpinBoxUp && (sb->state & State_Sunken))
1887 stateId = UPS_PRESSED;
1888 else if (sb->activeSubControls == SC_SpinBoxUp && (sb->state & State_MouseOver))
1889 stateId = UPS_HOT;
1890 else
1891 stateId = UPS_NORMAL;
1892 theme.partId = partId;
1893 theme.stateId = stateId;
1894 d->drawBackground(theme);
1895 }
1896 if (sub & SC_SpinBoxDown) {
1897 theme.rect = proxy()->subControlRect(CC_SpinBox, option, SC_SpinBoxDown, widget);
1898 partId = SPNP_DOWN;
1899 if (!(sb->stepEnabled & QAbstractSpinBox::StepDownEnabled) || !(flags & State_Enabled))
1900 stateId = DNS_DISABLED;
1901 else if (sb->activeSubControls == SC_SpinBoxDown && (sb->state & State_Sunken))
1902 stateId = DNS_PRESSED;
1903 else if (sb->activeSubControls == SC_SpinBoxDown && (sb->state & State_MouseOver))
1904 stateId = DNS_HOT;
1905 else
1906 stateId = DNS_NORMAL;
1907 theme.partId = partId;
1908 theme.stateId = stateId;
1909 d->drawBackground(theme);
1910 }
1911 }
1912 break;
1913#endif // QT_NO_SPINBOX
1914 default:
1915 QWindowsXPStyle::drawComplexControl(control, option, painter, widget);
1916 break;
1917 }
1918}
1919
1920/*!
1921 \internal
1922 */
1923QSize QWindowsVistaStyle::sizeFromContents(ContentsType type, const QStyleOption *option,
1924 const QSize &size, const QWidget *widget) const
1925{
1926 if (!QWindowsVistaStylePrivate::useVista())
1927 return QWindowsStyle::sizeFromContents(type, option, size, widget);
1928
1929 QSize sz(size);
1930 switch (type) {
1931 case CT_MenuItem:
1932 sz = QWindowsXPStyle::sizeFromContents(type, option, size, widget);
1933 int minimumHeight;
1934 {
1935 SIZE size;
1936 MARGINS margins;
1937 XPThemeData theme(widget, 0, QLatin1String("MENU"), MENU_POPUPCHECKBACKGROUND, MBI_HOT);
1938 pGetThemePartSize(theme.handle(), NULL, MENU_POPUPCHECK, 0, NULL,TS_TRUE, &size);
1939 pGetThemeMargins(theme.handle(), NULL, MENU_POPUPCHECK, 0, TMT_CONTENTMARGINS, NULL, &margins);
1940 minimumHeight = qMax<qint32>(size.cy + margins.cyBottomHeight+ margins.cyTopHeight, sz.height());
1941 sz.rwidth() += size.cx + margins.cxLeftWidth + margins.cxRightWidth;
1942 }
1943
1944 if (const QStyleOptionMenuItem *menuitem = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) {
1945 if (menuitem->menuItemType != QStyleOptionMenuItem::Separator)
1946 sz.setHeight(minimumHeight);
1947 }
1948 return sz;
1949#ifndef QT_NO_MENUBAR
1950 case CT_MenuBarItem:
1951 if (!sz.isEmpty())
1952 sz += QSize(windowsItemHMargin * 5 + 1, 5);
1953 return sz;
1954 break;
1955#endif
1956 case CT_ItemViewItem:
1957 sz = QWindowsXPStyle::sizeFromContents(type, option, size, widget);
1958 sz.rheight() += 2;
1959 return sz;
1960 case CT_SpinBox:
1961 {
1962 //Spinbox adds frame twice
1963 sz = QWindowsStyle::sizeFromContents(type, option, size, widget);
1964 int border = proxy()->pixelMetric(PM_SpinBoxFrameWidth, option, widget);
1965 sz -= QSize(2*border, 2*border);
1966 }
1967 return sz;
1968 default:
1969 break;
1970 }
1971 return QWindowsXPStyle::sizeFromContents(type, option, size, widget);
1972}
1973
1974/*!
1975 \internal
1976 */
1977QRect QWindowsVistaStyle::subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const
1978{
1979 if (!QWindowsVistaStylePrivate::useVista())
1980 return QWindowsStyle::subElementRect(element, option, widget);
1981
1982 QRect rect = QWindowsXPStyle::subElementRect(element, option, widget);
1983 switch (element) {
1984
1985 case SE_PushButtonContents:
1986 if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) {
1987 MARGINS borderSize;
1988 HTHEME theme = pOpenThemeData(widget ? QWindowsVistaStylePrivate::winId(widget) : 0, L"Button");
1989 if (theme) {
1990 int stateId = PBS_NORMAL;
1991 if (!(option->state & State_Enabled))
1992 stateId = PBS_DISABLED;
1993 else if (option->state & State_Sunken)
1994 stateId = PBS_PRESSED;
1995 else if (option->state & State_MouseOver)
1996 stateId = PBS_HOT;
1997 else if (btn->features & QStyleOptionButton::DefaultButton)
1998 stateId = PBS_DEFAULTED;
1999
2000 int border = proxy()->pixelMetric(PM_DefaultFrameWidth, btn, widget);
2001 rect = option->rect.adjusted(border, border, -border, -border);
2002
2003 int result = pGetThemeMargins(theme,
2004 NULL,
2005 BP_PUSHBUTTON,
2006 stateId,
2007 TMT_CONTENTMARGINS,
2008 NULL,
2009 &borderSize);
2010
2011 if (result == S_OK) {
2012 rect.adjust(borderSize.cxLeftWidth, borderSize.cyTopHeight,
2013 -borderSize.cxRightWidth, -borderSize.cyBottomHeight);
2014 rect = visualRect(option->direction, option->rect, rect);
2015 }
2016 }
2017 }
2018 break;
2019
2020 case SE_HeaderArrow:
2021 {
2022 QRect r = rect;
2023 int h = option->rect.height();
2024 int w = option->rect.width();
2025 int x = option->rect.x();
2026 int y = option->rect.y();
2027 int margin = proxy()->pixelMetric(QStyle::PM_HeaderMargin, option, widget);
2028
2029 XPThemeData theme(widget, 0, QLatin1String("HEADER"), HP_HEADERSORTARROW, HSAS_SORTEDDOWN, option->rect);
2030
2031 int arrowWidth = 13;
2032 int arrowHeight = 5;
2033 if (theme.isValid()) {
2034 SIZE size;
2035 if (pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size) == S_OK) {
2036 arrowWidth = size.cx;
2037 arrowHeight = size.cy;
2038 }
2039 }
2040 if (option->state & State_Horizontal) {
2041 r.setRect(x + w/2 - arrowWidth/2, y , arrowWidth, arrowHeight);
2042 } else {
2043 int vert_size = w / 2;
2044 r.setRect(x + 5, y + h - margin * 2 - vert_size,
2045 w - margin * 2 - 5, vert_size);
2046 }
2047 rect = visualRect(option->direction, option->rect, r);
2048 }
2049 break;
2050
2051 case SE_HeaderLabel:
2052 {
2053 int margin = proxy()->pixelMetric(QStyle::PM_HeaderMargin, option, widget);
2054 QRect r = option->rect;
2055 r.setRect(option->rect.x() + margin, option->rect.y() + margin,
2056 option->rect.width() - margin * 2, option->rect.height() - margin * 2);
2057 if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) {
2058 // Subtract width needed for arrow, if there is one
2059 if (header->sortIndicator != QStyleOptionHeader::None) {
2060 if (!(option->state & State_Horizontal)) //horizontal arrows are positioned on top
2061 r.setHeight(r.height() - (option->rect.width() / 2) - (margin * 2));
2062 }
2063 }
2064 rect = visualRect(option->direction, option->rect, r);
2065 }
2066 break;
2067 case SE_ProgressBarContents:
2068 rect = QCommonStyle::subElementRect(SE_ProgressBarGroove, option, widget);
2069 break;
2070 case SE_ItemViewItemDecoration:
2071 if (qstyleoption_cast<const QStyleOptionViewItemV4 *>(option))
2072 rect.adjust(-2, 0, 2, 0);
2073 break;
2074 case SE_ItemViewItemFocusRect:
2075 if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast<const QStyleOptionViewItemV4 *>(option)) {
2076 QRect textRect = subElementRect(QStyle::SE_ItemViewItemText, option, widget);
2077 QRect displayRect = subElementRect(QStyle::SE_ItemViewItemDecoration, option, widget);
2078 if (!vopt->icon.isNull())
2079 rect = textRect.united(displayRect);
2080 else
2081 rect = textRect;
2082 rect = rect.adjusted(1, 0, -1, 0);
2083 }
2084 break;
2085 default:
2086 break;
2087 }
2088 return rect;
2089}
2090
2091
2092/*
2093 This function is used by subControlRect to check if a button
2094 should be drawn for the given subControl given a set of window flags.
2095*/
2096static bool buttonVisible(const QStyle::SubControl sc, const QStyleOptionTitleBar *tb){
2097
2098 bool isMinimized = tb->titleBarState & Qt::WindowMinimized;
2099 bool isMaximized = tb->titleBarState & Qt::WindowMaximized;
2100 const uint flags = tb->titleBarFlags;
2101 bool retVal = false;
2102 switch (sc) {
2103 case QStyle::SC_TitleBarContextHelpButton:
2104 if (flags & Qt::WindowContextHelpButtonHint)
2105 retVal = true;
2106 break;
2107 case QStyle::SC_TitleBarMinButton:
2108 if (!isMinimized && (flags & Qt::WindowMinimizeButtonHint))
2109 retVal = true;
2110 break;
2111 case QStyle::SC_TitleBarNormalButton:
2112 if (isMinimized && (flags & Qt::WindowMinimizeButtonHint))
2113 retVal = true;
2114 else if (isMaximized && (flags & Qt::WindowMaximizeButtonHint))
2115 retVal = true;
2116 break;
2117 case QStyle::SC_TitleBarMaxButton:
2118 if (!isMaximized && (flags & Qt::WindowMaximizeButtonHint))
2119 retVal = true;
2120 break;
2121 case QStyle::SC_TitleBarShadeButton:
2122 if (!isMinimized && flags & Qt::WindowShadeButtonHint)
2123 retVal = true;
2124 break;
2125 case QStyle::SC_TitleBarUnshadeButton:
2126 if (isMinimized && flags & Qt::WindowShadeButtonHint)
2127 retVal = true;
2128 break;
2129 case QStyle::SC_TitleBarCloseButton:
2130 if (flags & Qt::WindowSystemMenuHint)
2131 retVal = true;
2132 break;
2133 case QStyle::SC_TitleBarSysMenu:
2134 if (flags & Qt::WindowSystemMenuHint)
2135 retVal = true;
2136 break;
2137 default :
2138 retVal = true;
2139 }
2140 return retVal;
2141}
2142
2143
2144/*! \internal */
2145int QWindowsVistaStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget,
2146 QStyleHintReturn *returnData) const
2147{
2148 QWindowsVistaStylePrivate *d = const_cast<QWindowsVistaStylePrivate*>(d_func());
2149 int ret = 0;
2150 switch (hint) {
2151 case SH_MessageBox_CenterButtons:
2152 ret = false;
2153 break;
2154 case SH_ToolTip_Mask:
2155 if (option) {
2156 if (QStyleHintReturnMask *mask = qstyleoption_cast<QStyleHintReturnMask*>(returnData)) {
2157 ret = true;
2158 XPThemeData themeData(widget, 0, QLatin1String("TOOLTIP"), TTP_STANDARD, TTSS_NORMAL, option->rect);
2159 mask->region = d->region(themeData);
2160 }
2161 }
2162 break;
2163 case SH_Table_GridLineColor:
2164 if (option)
2165 ret = option->palette.color(QPalette::Base).darker(118).rgb();
2166 else
2167 ret = -1;
2168 break;
2169 default:
2170 ret = QWindowsXPStyle::styleHint(hint, option, widget, returnData);
2171 break;
2172 }
2173 return ret;
2174}
2175
2176
2177/*!
2178 \internal
2179 */
2180QRect QWindowsVistaStyle::subControlRect(ComplexControl control, const QStyleOptionComplex *option,
2181 SubControl subControl, const QWidget *widget) const
2182{
2183 if (!QWindowsVistaStylePrivate::useVista())
2184 return QWindowsStyle::subControlRect(control, option, subControl, widget);
2185
2186 QRect rect = QWindowsXPStyle::subControlRect(control, option, subControl, widget);
2187 switch (control) {
2188#ifndef QT_NO_COMBOBOX
2189 case CC_ComboBox:
2190 if (const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
2191 int x = cb->rect.x(),
2192 y = cb->rect.y(),
2193 wi = cb->rect.width(),
2194 he = cb->rect.height();
2195 int xpos = x;
2196 int margin = cb->frame ? 3 : 0;
2197 int bmarg = cb->frame ? 2 : 0;
2198 int arrowButtonWidth = bmarg + 16;
2199 xpos += wi - arrowButtonWidth;
2200
2201 switch (subControl) {
2202 case SC_ComboBoxFrame:
2203 rect = cb->rect;
2204 break;
2205 case SC_ComboBoxArrow:
2206 rect.setRect(xpos, y , arrowButtonWidth, he);
2207 break;
2208 case SC_ComboBoxEditField:
2209 rect.setRect(x + margin, y + margin, wi - 2 * margin - 16, he - 2 * margin);
2210 break;
2211 case SC_ComboBoxListBoxPopup:
2212 rect = cb->rect;
2213 break;
2214 default:
2215 break;
2216 }
2217 rect = visualRect(cb->direction, cb->rect, rect);
2218 return rect;
2219 }
2220#endif // QT_NO_COMBOBOX
2221 case CC_TitleBar:
2222 if (const QStyleOptionTitleBar *tb = qstyleoption_cast<const QStyleOptionTitleBar *>(option)) {
2223 if (!buttonVisible(subControl, tb))
2224 return rect;
2225 const bool isToolTitle = false;
2226 const int height = tb->rect.height();
2227 const int width = tb->rect.width();
2228 int buttonWidth = GetSystemMetrics(SM_CXSIZE) - 4;
2229
2230 const int frameWidth = proxy()->pixelMetric(PM_MdiSubWindowFrameWidth, option, widget);
2231 const bool sysmenuHint = (tb->titleBarFlags & Qt::WindowSystemMenuHint) != 0;
2232 const bool minimizeHint = (tb->titleBarFlags & Qt::WindowMinimizeButtonHint) != 0;
2233 const bool maximizeHint = (tb->titleBarFlags & Qt::WindowMaximizeButtonHint) != 0;
2234 const bool contextHint = (tb->titleBarFlags & Qt::WindowContextHelpButtonHint) != 0;
2235 const bool shadeHint = (tb->titleBarFlags & Qt::WindowShadeButtonHint) != 0;
2236
2237 switch (subControl) {
2238 case SC_TitleBarLabel:
2239 rect = QRect(frameWidth, 0, width - (buttonWidth + frameWidth + 10), height);
2240 if (isToolTitle) {
2241 if (sysmenuHint) {
2242 rect.adjust(0, 0, -buttonWidth - 3, 0);
2243 }
2244 if (minimizeHint || maximizeHint)
2245 rect.adjust(0, 0, -buttonWidth - 2, 0);
2246 } else {
2247 if (sysmenuHint) {
2248 const int leftOffset = height - 8;
2249 rect.adjust(leftOffset, 0, 0, 4);
2250 }
2251 if (minimizeHint)
2252 rect.adjust(0, 0, -buttonWidth - 2, 0);
2253 if (maximizeHint)
2254 rect.adjust(0, 0, -buttonWidth - 2, 0);
2255 if (contextHint)
2256 rect.adjust(0, 0, -buttonWidth - 2, 0);
2257 if (shadeHint)
2258 rect.adjust(0, 0, -buttonWidth - 2, 0);
2259 }
2260 rect.translate(0, 2);
2261 rect = visualRect(option->direction, option->rect, rect);
2262 break;
2263 case SC_TitleBarSysMenu:
2264 {
2265 const int controlTop = 6;
2266 const int controlHeight = height - controlTop - 3;
2267 int iconExtent = proxy()->pixelMetric(PM_SmallIconSize);
2268 QSize iconSize = tb->icon.actualSize(QSize(iconExtent, iconExtent));
2269 if (tb->icon.isNull())
2270 iconSize = QSize(controlHeight, controlHeight);
2271 int hPad = (controlHeight - iconSize.height())/2;
2272 int vPad = (controlHeight - iconSize.width())/2;
2273 rect = QRect(frameWidth + hPad, controlTop + vPad, iconSize.width(), iconSize.height());
2274 rect.translate(0, 3);
2275 rect = visualRect(option->direction, option->rect, rect);
2276 }
2277 break;
2278 default:
2279 break;
2280 }
2281 }
2282 break;
2283 default:
2284 break;
2285 }
2286 return rect;
2287}
2288
2289/*!
2290 \internal
2291 */
2292bool QWindowsVistaStyle::event(QEvent *e)
2293{
2294 Q_D(QWindowsVistaStyle);
2295 switch (e->type()) {
2296 case QEvent::Timer:
2297 {
2298 QTimerEvent *timerEvent = (QTimerEvent *)e;
2299 if (d->animationTimer.timerId() == timerEvent->timerId()) {
2300 d->timerEvent();
2301 e->accept();
2302 return true;
2303 }
2304 }
2305 break;
2306 default:
2307 break;
2308 }
2309 return QWindowsXPStyle::event(e);
2310}
2311
2312/*!
2313 \internal
2314 */
2315QStyle::SubControl QWindowsVistaStyle::hitTestComplexControl(ComplexControl control, const QStyleOptionComplex *option,
2316 const QPoint &pos, const QWidget *widget) const
2317{
2318 if (!QWindowsVistaStylePrivate::useVista()) {
2319 return QWindowsStyle::hitTestComplexControl(control, option, pos, widget);
2320 }
2321 return QWindowsXPStyle::hitTestComplexControl(control, option, pos, widget);
2322}
2323
2324/*!
2325 \internal
2326 */
2327int QWindowsVistaStyle::pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const
2328{
2329 if (!QWindowsVistaStylePrivate::useVista()) {
2330 return QWindowsStyle::pixelMetric(metric, option, widget);
2331 }
2332 switch (metric) {
2333
2334 case PM_DockWidgetTitleBarButtonMargin:
2335 return int(QStyleHelper::dpiScaled(5.));
2336 case PM_ScrollBarSliderMin:
2337 return int(QStyleHelper::dpiScaled(18.));
2338 case PM_MenuHMargin:
2339 case PM_MenuVMargin:
2340 return 0;
2341 case PM_MenuPanelWidth:
2342 return 3;
2343 default:
2344 break;
2345 }
2346 return QWindowsXPStyle::pixelMetric(metric, option, widget);
2347}
2348
2349/*!
2350 \internal
2351 */
2352QPalette QWindowsVistaStyle::standardPalette() const
2353{
2354 return QWindowsXPStyle::standardPalette();
2355}
2356
2357/*!
2358 \internal
2359 */
2360void QWindowsVistaStyle::polish(QApplication *app)
2361{
2362 QWindowsXPStyle::polish(app);
2363}
2364
2365/*!
2366 \internal
2367 */
2368void QWindowsVistaStyle::polish(QWidget *widget)
2369{
2370 QWindowsXPStyle::polish(widget);
2371#ifndef QT_NO_LINEEDIT
2372 if (qobject_cast<QLineEdit*>(widget))
2373 widget->setAttribute(Qt::WA_Hover);
2374 else
2375#endif // QT_NO_LINEEDIT
2376 if (qobject_cast<QGroupBox*>(widget))
2377 widget->setAttribute(Qt::WA_Hover);
2378 else if (qobject_cast<QCommandLinkButton*>(widget)) {
2379 QFont buttonFont = widget->font();
2380 buttonFont.setFamily(QLatin1String("Segoe UI"));
2381 widget->setFont(buttonFont);
2382 }
2383 else if (widget->inherits("QTipLabel")){
2384 //note that since tooltips are not reused
2385 //we do not have to care about unpolishing
2386 widget->setContentsMargins(3, 0, 4, 0);
2387 COLORREF bgRef;
2388 HTHEME theme = pOpenThemeData(widget ? QWindowsVistaStylePrivate::winId(widget) : 0, L"TOOLTIP");
2389 if (theme) {
2390 if (pGetThemeColor(theme, TTP_STANDARD, TTSS_NORMAL, TMT_TEXTCOLOR, &bgRef) == S_OK) {
2391 QColor textColor = QColor::fromRgb(bgRef);
2392 QPalette pal;
2393 pal.setColor(QPalette::All, QPalette::ToolTipText, textColor);
2394 widget->setPalette(pal);
2395 }
2396 }
2397 } else if (qobject_cast<QMessageBox *> (widget)) {
2398 widget->setAttribute(Qt::WA_StyledBackground);
2399 QDialogButtonBox *buttonBox = qFindChild<QDialogButtonBox *>(widget,QLatin1String("qt_msgbox_buttonbox"));
2400 if (buttonBox)
2401 buttonBox->setContentsMargins(0, 9, 0, 0);
2402 }
2403#ifndef QT_NO_INPUTDIALOG
2404 else if (qobject_cast<QInputDialog *> (widget)) {
2405 widget->setAttribute(Qt::WA_StyledBackground);
2406 QDialogButtonBox *buttonBox = qFindChild<QDialogButtonBox *>(widget,QLatin1String("qt_inputdlg_buttonbox"));
2407 if (buttonBox)
2408 buttonBox->setContentsMargins(0, 9, 0, 0);
2409 }
2410#endif // QT_NO_INPUTDIALOG
2411 else if (QTreeView *tree = qobject_cast<QTreeView *> (widget)) {
2412 tree->viewport()->setAttribute(Qt::WA_Hover);
2413 }
2414 else if (QListView *list = qobject_cast<QListView *> (widget)) {
2415 list->viewport()->setAttribute(Qt::WA_Hover);
2416 }
2417}
2418
2419/*!
2420 \internal
2421 */
2422void QWindowsVistaStyle::unpolish(QWidget *widget)
2423{
2424 QWindowsXPStyle::unpolish(widget);
2425
2426 QWindowsVistaStylePrivate *d = const_cast<QWindowsVistaStylePrivate*>(d_func());
2427 d->stopAnimation(widget);
2428
2429#ifndef QT_NO_LINEEDIT
2430 if (qobject_cast<QLineEdit*>(widget))
2431 widget->setAttribute(Qt::WA_Hover, false);
2432 else
2433#endif // QT_NO_LINEEDIT
2434 if (qobject_cast<QGroupBox*>(widget))
2435 widget->setAttribute(Qt::WA_Hover, false);
2436 else if (qobject_cast<QMessageBox *> (widget)) {
2437 widget->setAttribute(Qt::WA_StyledBackground, false);
2438 QDialogButtonBox *buttonBox = qFindChild<QDialogButtonBox *>(widget,QLatin1String("qt_msgbox_buttonbox"));
2439 if (buttonBox)
2440 buttonBox->setContentsMargins(0, 0, 0, 0);
2441 }
2442#ifndef QT_NO_INPUTDIALOG
2443 else if (qobject_cast<QInputDialog *> (widget)) {
2444 widget->setAttribute(Qt::WA_StyledBackground, false);
2445 QDialogButtonBox *buttonBox = qFindChild<QDialogButtonBox *>(widget,QLatin1String("qt_inputdlg_buttonbox"));
2446 if (buttonBox)
2447 buttonBox->setContentsMargins(0, 0, 0, 0);
2448 }
2449#endif // QT_NO_INPUTDIALOG
2450 else if (QTreeView *tree = qobject_cast<QTreeView *> (widget)) {
2451 tree->viewport()->setAttribute(Qt::WA_Hover, false);
2452 } else if (qobject_cast<QCommandLinkButton*>(widget)) {
2453 QFont font = QApplication::font("QCommandLinkButton");
2454 QFont widgetFont = widget->font();
2455 widgetFont.setFamily(font.family()); //Only family set by polish
2456 widget->setFont(widgetFont);
2457 }
2458}
2459
2460
2461/*!
2462 \internal
2463 */
2464void QWindowsVistaStyle::unpolish(QApplication *app)
2465{
2466 QWindowsXPStyle::unpolish(app);
2467}
2468
2469/*!
2470 \internal
2471 */
2472void QWindowsVistaStyle::polish(QPalette &pal)
2473{
2474 QWindowsStyle::polish(pal);
2475 pal.setBrush(QPalette::AlternateBase, pal.base().color().darker(104));
2476}
2477
2478/*!
2479 \internal
2480 */
2481QPixmap QWindowsVistaStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *option,
2482 const QWidget *widget) const
2483{
2484 if (!QWindowsVistaStylePrivate::useVista()) {
2485 return QWindowsStyle::standardPixmap(standardPixmap, option, widget);
2486 }
2487 return QWindowsXPStyle::standardPixmap(standardPixmap, option, widget);
2488}
2489
2490QWindowsVistaStylePrivate::QWindowsVistaStylePrivate() :
2491 QWindowsXPStylePrivate(), m_treeViewHelper(0)
2492{
2493 resolveSymbols();
2494}
2495
2496QWindowsVistaStylePrivate::~QWindowsVistaStylePrivate()
2497{
2498 delete m_treeViewHelper;
2499}
2500
2501void QWindowsVistaStylePrivate::timerEvent()
2502{
2503 for (int i = animations.size() - 1 ; i >= 0 ; --i) {
2504
2505 if (animations[i]->widget())
2506 animations[i]->widget()->update();
2507
2508 if (!animations[i]->widget() ||
2509 !animations[i]->widget()->isEnabled() ||
2510 !animations[i]->widget()->isVisible() ||
2511 animations[i]->widget()->window()->isMinimized() ||
2512 !animations[i]->running() ||
2513 !QWindowsVistaStylePrivate::useVista())
2514 {
2515 QWindowsVistaAnimation *a = animations.takeAt(i);
2516 delete a;
2517 }
2518 }
2519 if (animations.size() == 0 && animationTimer.isActive()) {
2520 animationTimer.stop();
2521 }
2522}
2523
2524void QWindowsVistaStylePrivate::stopAnimation(const QWidget *w)
2525{
2526 for (int i = animations.size() - 1 ; i >= 0 ; --i) {
2527 if (animations[i]->widget() == w) {
2528 QWindowsVistaAnimation *a = animations.takeAt(i);
2529 delete a;
2530 break;
2531 }
2532 }
2533}
2534
2535void QWindowsVistaStylePrivate::startAnimation(QWindowsVistaAnimation *t)
2536{
2537 Q_Q(QWindowsVistaStyle);
2538 stopAnimation(t->widget());
2539 animations.append(t);
2540 if (animations.size() > 0 && !animationTimer.isActive()) {
2541 animationTimer.start(45, q);
2542 }
2543}
2544
2545bool QWindowsVistaStylePrivate::transitionsEnabled() const
2546{
2547 BOOL animEnabled = false;
2548 if (SystemParametersInfo(SPI_GETCLIENTAREAANIMATION, 0, &animEnabled, 0))
2549 {
2550 if (animEnabled)
2551 return true;
2552 }
2553 return false;
2554}
2555
2556
2557QWindowsVistaAnimation * QWindowsVistaStylePrivate::widgetAnimation(const QWidget *widget) const
2558{
2559 if (!widget)
2560 return 0;
2561 foreach (QWindowsVistaAnimation *a, animations) {
2562 if (a->widget() == widget)
2563 return a;
2564 }
2565 return 0;
2566}
2567
2568
2569/*! \internal
2570 Returns true if all the necessary theme engine symbols were
2571 resolved.
2572*/
2573bool QWindowsVistaStylePrivate::resolveSymbols()
2574{
2575 static bool tried = false;
2576 if (!tried) {
2577 tried = true;
2578 QSystemLibrary themeLib(QLatin1String("uxtheme"));
2579 pSetWindowTheme = (PtrSetWindowTheme )themeLib.resolve("SetWindowTheme");
2580 pIsThemePartDefined = (PtrIsThemePartDefined )themeLib.resolve("IsThemePartDefined");
2581 pGetThemePartSize = (PtrGetThemePartSize )themeLib.resolve("GetThemePartSize");
2582 pOpenThemeData = (PtrOpenThemeData )themeLib.resolve("OpenThemeData");
2583 pCloseThemeData = (PtrCloseThemeData )themeLib.resolve("CloseThemeData");
2584 pDrawThemeBackground = (PtrDrawThemeBackground )themeLib.resolve("DrawThemeBackground");
2585 pDrawThemeBackgroundEx = (PtrDrawThemeBackgroundEx )themeLib.resolve("DrawThemeBackgroundEx");
2586 pGetCurrentThemeName = (PtrGetCurrentThemeName )themeLib.resolve("GetCurrentThemeName");
2587 pGetThemeBool = (PtrGetThemeBool )themeLib.resolve("GetThemeBool");
2588 pGetThemeColor = (PtrGetThemeColor )themeLib.resolve("GetThemeColor");
2589 pGetThemeEnumValue = (PtrGetThemeEnumValue )themeLib.resolve("GetThemeEnumValue");
2590 pGetThemeFilename = (PtrGetThemeFilename )themeLib.resolve("GetThemeFilename");
2591 pGetThemeFont = (PtrGetThemeFont )themeLib.resolve("GetThemeFont");
2592 pGetThemeInt = (PtrGetThemeInt )themeLib.resolve("GetThemeInt");
2593 pGetThemeIntList = (PtrGetThemeIntList )themeLib.resolve("GetThemeIntList");
2594 pGetThemeMargins = (PtrGetThemeMargins )themeLib.resolve("GetThemeMargins");
2595 pGetThemeMetric = (PtrGetThemeMetric )themeLib.resolve("GetThemeMetric");
2596 pGetThemePartSize = (PtrGetThemePartSize )themeLib.resolve("GetThemePartSize");
2597 pGetThemePosition = (PtrGetThemePosition )themeLib.resolve("GetThemePosition");
2598 pGetThemeRect = (PtrGetThemeRect )themeLib.resolve("GetThemeRect");
2599 pGetThemeString = (PtrGetThemeString )themeLib.resolve("GetThemeString");
2600 pGetThemeTransitionDuration = (PtrGetThemeTransitionDuration)themeLib.resolve("GetThemeTransitionDuration");
2601 pGetThemePropertyOrigin = (PtrGetThemePropertyOrigin)themeLib.resolve("GetThemePropertyOrigin");
2602 }
2603 return pGetThemeTransitionDuration != 0;
2604}
2605
2606/*
2607 * We need to set the windows explorer theme explicitly on a native widget
2608 * in order to get Vista-style item view themes
2609 */
2610QWidget *QWindowsVistaStylePrivate::treeViewHelper()
2611{
2612 if (!m_treeViewHelper) {
2613 m_treeViewHelper = new QWidget(0);
2614 pSetWindowTheme(m_treeViewHelper->winId(), L"explorer", NULL);
2615 }
2616 return m_treeViewHelper;
2617}
2618
2619
2620/*!
2621\internal
2622*/
2623QIcon QWindowsVistaStyle::standardIconImplementation(StandardPixmap standardIcon,
2624 const QStyleOption *option,
2625 const QWidget *widget) const
2626{
2627 if (!QWindowsVistaStylePrivate::useVista()) {
2628 return QWindowsStyle::standardIconImplementation(standardIcon, option, widget);
2629 }
2630
2631 QWindowsVistaStylePrivate *d = const_cast<QWindowsVistaStylePrivate *>(d_func());
2632 switch(standardIcon) {
2633 case SP_CommandLink:
2634 {
2635 XPThemeData theme(0, 0, QLatin1String("BUTTON"), BP_COMMANDLINKGLYPH, CMDLGS_NORMAL);
2636 if (theme.isValid()) {
2637 SIZE size;
2638 pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size);
2639 QIcon linkGlyph;
2640 QPixmap pm = QPixmap(size.cx, size.cy);
2641 pm.fill(Qt::transparent);
2642 QPainter p(&pm);
2643 theme.painter = &p;
2644 theme.rect = QRect(0, 0, size.cx, size.cy);
2645 d->drawBackground(theme);
2646 linkGlyph.addPixmap(pm, QIcon::Normal, QIcon::Off); // Normal
2647 pm.fill(Qt::transparent);
2648
2649 theme.stateId = CMDLGS_PRESSED;
2650 d->drawBackground(theme);
2651 linkGlyph.addPixmap(pm, QIcon::Normal, QIcon::On); // Pressed
2652 pm.fill(Qt::transparent);
2653
2654 theme.stateId = CMDLGS_HOT;
2655 d->drawBackground(theme);
2656 linkGlyph.addPixmap(pm, QIcon::Active, QIcon::Off); // Hover
2657 pm.fill(Qt::transparent);
2658
2659 theme.stateId = CMDLGS_DISABLED;
2660 d->drawBackground(theme);
2661 linkGlyph.addPixmap(pm, QIcon::Disabled, QIcon::Off); // Disabled
2662 return linkGlyph;
2663 }
2664 }
2665 break;
2666 default:
2667 break;
2668 }
2669 return QWindowsXPStyle::standardIconImplementation(standardIcon, option, widget);
2670}
2671
2672QT_END_NAMESPACE
2673
2674#endif //QT_NO_WINDOWSVISTA
Note: See TracBrowser for help on using the repository browser.