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

Last change on this file since 836 was 651, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.2 sources.

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