|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2009 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 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
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 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
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 |
|
48 QT_BEGIN_NAMESPACE |
|
49 |
|
50 static const int windowsItemFrame = 2; // menu item frame width |
|
51 static const int windowsItemHMargin = 3; // menu item hor text margin |
|
52 static const int windowsItemVMargin = 4; // menu item ver text margin |
|
53 static const int windowsArrowHMargin = 6; // arrow horizontal margin |
|
54 static 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 |
|
82 typedef HRESULT (WINAPI *PtrGetThemePartSize)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, OPTIONAL RECT *prc, enum THEMESIZE eSize, OUT SIZE *psz); |
|
83 typedef HTHEME (WINAPI *PtrOpenThemeData)(HWND hwnd, LPCWSTR pszClassList); |
|
84 typedef HTHEME (WINAPI *PtrOpenThemeData)(HWND hwnd, LPCWSTR pszClassList); |
|
85 typedef HRESULT (WINAPI *PtrCloseThemeData)(HTHEME hTheme); |
|
86 typedef HRESULT (WINAPI *PtrDrawThemeBackground)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, OPTIONAL const RECT *pClipRect); |
|
87 typedef HRESULT (WINAPI *PtrDrawThemeBackgroundEx)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, OPTIONAL const DTBGOPTS *pOptions); |
|
88 typedef HRESULT (WINAPI *PtrGetCurrentThemeName)(OUT LPWSTR pszThemeFileName, int cchMaxNameChars, OUT OPTIONAL LPWSTR pszColorBuff, int cchMaxColorChars, OUT OPTIONAL LPWSTR pszSizeBuff, int cchMaxSizeChars); |
|
89 typedef HRESULT (WINAPI *PtrGetThemeBool)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT BOOL *pfVal); |
|
90 typedef HRESULT (WINAPI *PtrGetThemeColor)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT COLORREF *pColor); |
|
91 typedef HRESULT (WINAPI *PtrGetThemeEnumValue)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT int *piVal); |
|
92 typedef HRESULT (WINAPI *PtrGetThemeFilename)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT LPWSTR pszThemeFileName, int cchMaxBuffChars); |
|
93 typedef HRESULT (WINAPI *PtrGetThemeFont)(HTHEME hTheme, OPTIONAL HDC hdc, int iPartId, int iStateId, int iPropId, OUT LOGFONT *pFont); |
|
94 typedef HRESULT (WINAPI *PtrGetThemeInt)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT int *piVal); |
|
95 typedef HRESULT (WINAPI *PtrGetThemeIntList)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT INTLIST *pIntList); |
|
96 typedef HRESULT (WINAPI *PtrGetThemeMargins)(HTHEME hTheme, OPTIONAL HDC hdc, int iPartId, int iStateId, int iPropId, OPTIONAL RECT *prc, OUT MARGINS *pMargins); |
|
97 typedef HRESULT (WINAPI *PtrGetThemeMetric)(HTHEME hTheme, OPTIONAL HDC hdc, int iPartId, int iStateId, int iPropId, OUT int *piVal); |
|
98 typedef HRESULT (WINAPI *PtrGetThemePartSize)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, OPTIONAL RECT *prc, enum THEMESIZE eSize, OUT SIZE *psz); |
|
99 typedef HRESULT (WINAPI *PtrGetThemePosition)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT POINT *pPoint); |
|
100 typedef HRESULT (WINAPI *PtrGetThemeRect)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT RECT *pRect); |
|
101 typedef HRESULT (WINAPI *PtrGetThemeString)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT LPWSTR pszBuff, int cchMaxBuffChars); |
|
102 typedef HRESULT (WINAPI *PtrGetThemeTransitionDuration)(HTHEME hTheme, int iPartId, int iStateFromId, int iStateToId, int iPropId, int *pDuration); |
|
103 typedef HRESULT (WINAPI *PtrIsThemePartDefined)(HTHEME hTheme, int iPartId, int iStateId); |
|
104 typedef HRESULT (WINAPI *PtrSetWindowTheme)(HWND hwnd, LPCWSTR pszSubAppName, LPCWSTR pszSubIdList); |
|
105 typedef HRESULT (WINAPI *PtrGetThemePropertyOrigin)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT enum PROPERTYORIGIN *pOrigin); |
|
106 |
|
107 static PtrIsThemePartDefined pIsThemePartDefined = 0; |
|
108 static PtrOpenThemeData pOpenThemeData = 0; |
|
109 static PtrCloseThemeData pCloseThemeData = 0; |
|
110 static PtrDrawThemeBackground pDrawThemeBackground = 0; |
|
111 static PtrDrawThemeBackgroundEx pDrawThemeBackgroundEx = 0; |
|
112 static PtrGetCurrentThemeName pGetCurrentThemeName = 0; |
|
113 static PtrGetThemeBool pGetThemeBool = 0; |
|
114 static PtrGetThemeColor pGetThemeColor = 0; |
|
115 static PtrGetThemeEnumValue pGetThemeEnumValue = 0; |
|
116 static PtrGetThemeFilename pGetThemeFilename = 0; |
|
117 static PtrGetThemeFont pGetThemeFont = 0; |
|
118 static PtrGetThemeInt pGetThemeInt = 0; |
|
119 static PtrGetThemeIntList pGetThemeIntList = 0; |
|
120 static PtrGetThemeMargins pGetThemeMargins = 0; |
|
121 static PtrGetThemeMetric pGetThemeMetric = 0; |
|
122 static PtrGetThemePartSize pGetThemePartSize = 0; |
|
123 static PtrGetThemePosition pGetThemePosition = 0; |
|
124 static PtrGetThemeRect pGetThemeRect = 0; |
|
125 static PtrGetThemeString pGetThemeString = 0; |
|
126 static PtrGetThemeTransitionDuration pGetThemeTransitionDuration= 0; |
|
127 static PtrSetWindowTheme pSetWindowTheme = 0; |
|
128 static 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 */ |
|
134 bool 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 */ |
|
156 QWindowsVistaStyle::QWindowsVistaStyle() |
|
157 : QWindowsXPStyle(*new QWindowsVistaStylePrivate) |
|
158 { |
|
159 } |
|
160 |
|
161 //convert Qt state flags to uxtheme button states |
|
162 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 |
|
193 void Animation::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 */ |
|
208 void Animation::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 */ |
|
254 void Transition::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 */ |
|
281 void Pulse::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 */ |
|
331 void 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 Animation *anim = d->widgetAnimation(widget); |
|
397 Transition *t = new Transition; |
|
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 (Animation *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 (Animation *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 */ |
|
879 void 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 Animation *anim = d->widgetAnimation(widget); |
|
933 |
|
934 QStyleOptionButton opt = *button; |
|
935 opt.state = (QStyle::State)oldState; |
|
936 |
|
937 startImage.fill(0); |
|
938 Transition *t = new Transition; |
|
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 (Animation *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 Animation *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 Pulse *pulse = new Pulse; |
|
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 Animation *a = new Animation; |
|
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 (Animation *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 (Animation *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, ©Opt, 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 */ |
|
1539 void 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 Animation *anim = d->widgetAnimation(widget); |
|
1607 Transition *t = new Transition; |
|
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 (Animation *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 */ |
|
1922 QSize 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 */ |
|
1999 QRect 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 */ |
|
2118 static 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 */ |
|
2167 int 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 */ |
|
2202 QRect 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 xpos += wi - bmarg - 16; |
|
2221 |
|
2222 switch (subControl) { |
|
2223 case SC_ComboBoxFrame: |
|
2224 rect = cb->rect; |
|
2225 break; |
|
2226 case SC_ComboBoxArrow: |
|
2227 rect.setRect(xpos, y , wi - xpos, he); |
|
2228 break; |
|
2229 case SC_ComboBoxEditField: |
|
2230 rect.setRect(x + margin, y + margin, wi - 2 * margin - 16, he - 2 * margin); |
|
2231 break; |
|
2232 case SC_ComboBoxListBoxPopup: |
|
2233 rect = cb->rect; |
|
2234 break; |
|
2235 default: |
|
2236 break; |
|
2237 } |
|
2238 rect = visualRect(cb->direction, cb->rect, rect); |
|
2239 return rect; |
|
2240 } |
|
2241 #endif // QT_NO_COMBOBOX |
|
2242 case CC_TitleBar: |
|
2243 if (const QStyleOptionTitleBar *tb = qstyleoption_cast<const QStyleOptionTitleBar *>(option)) { |
|
2244 if (!buttonVisible(subControl, tb)) |
|
2245 return rect; |
|
2246 const bool isToolTitle = false; |
|
2247 const int height = tb->rect.height(); |
|
2248 const int width = tb->rect.width(); |
|
2249 int buttonWidth = GetSystemMetrics(SM_CXSIZE) - 4; |
|
2250 |
|
2251 const int frameWidth = proxy()->pixelMetric(PM_MdiSubWindowFrameWidth, option, widget); |
|
2252 const bool sysmenuHint = (tb->titleBarFlags & Qt::WindowSystemMenuHint) != 0; |
|
2253 const bool minimizeHint = (tb->titleBarFlags & Qt::WindowMinimizeButtonHint) != 0; |
|
2254 const bool maximizeHint = (tb->titleBarFlags & Qt::WindowMaximizeButtonHint) != 0; |
|
2255 const bool contextHint = (tb->titleBarFlags & Qt::WindowContextHelpButtonHint) != 0; |
|
2256 const bool shadeHint = (tb->titleBarFlags & Qt::WindowShadeButtonHint) != 0; |
|
2257 |
|
2258 switch (subControl) { |
|
2259 case SC_TitleBarLabel: |
|
2260 rect = QRect(frameWidth, 0, width - (buttonWidth + frameWidth + 10), height); |
|
2261 if (isToolTitle) { |
|
2262 if (sysmenuHint) { |
|
2263 rect.adjust(0, 0, -buttonWidth - 3, 0); |
|
2264 } |
|
2265 if (minimizeHint || maximizeHint) |
|
2266 rect.adjust(0, 0, -buttonWidth - 2, 0); |
|
2267 } else { |
|
2268 if (sysmenuHint) { |
|
2269 const int leftOffset = height - 8; |
|
2270 rect.adjust(leftOffset, 0, 0, 4); |
|
2271 } |
|
2272 if (minimizeHint) |
|
2273 rect.adjust(0, 0, -buttonWidth - 2, 0); |
|
2274 if (maximizeHint) |
|
2275 rect.adjust(0, 0, -buttonWidth - 2, 0); |
|
2276 if (contextHint) |
|
2277 rect.adjust(0, 0, -buttonWidth - 2, 0); |
|
2278 if (shadeHint) |
|
2279 rect.adjust(0, 0, -buttonWidth - 2, 0); |
|
2280 } |
|
2281 rect.translate(0, 2); |
|
2282 rect = visualRect(option->direction, option->rect, rect); |
|
2283 break; |
|
2284 case SC_TitleBarSysMenu: |
|
2285 { |
|
2286 const int controlTop = 6; |
|
2287 const int controlHeight = height - controlTop - 3; |
|
2288 int iconExtent = proxy()->pixelMetric(PM_SmallIconSize); |
|
2289 QSize iconSize = tb->icon.actualSize(QSize(iconExtent, iconExtent)); |
|
2290 if (tb->icon.isNull()) |
|
2291 iconSize = QSize(controlHeight, controlHeight); |
|
2292 int hPad = (controlHeight - iconSize.height())/2; |
|
2293 int vPad = (controlHeight - iconSize.width())/2; |
|
2294 rect = QRect(frameWidth + hPad, controlTop + vPad, iconSize.width(), iconSize.height()); |
|
2295 rect.translate(0, 3); |
|
2296 rect = visualRect(option->direction, option->rect, rect); |
|
2297 } |
|
2298 break; |
|
2299 default: |
|
2300 break; |
|
2301 } |
|
2302 } |
|
2303 break; |
|
2304 default: |
|
2305 break; |
|
2306 } |
|
2307 return rect; |
|
2308 } |
|
2309 |
|
2310 /*! |
|
2311 \internal |
|
2312 */ |
|
2313 bool QWindowsVistaStyle::event(QEvent *e) |
|
2314 { |
|
2315 Q_D(QWindowsVistaStyle); |
|
2316 switch (e->type()) { |
|
2317 case QEvent::Timer: |
|
2318 { |
|
2319 QTimerEvent *timerEvent = (QTimerEvent *)e; |
|
2320 if (d->animationTimer.timerId() == timerEvent->timerId()) { |
|
2321 d->timerEvent(); |
|
2322 e->accept(); |
|
2323 return true; |
|
2324 } |
|
2325 } |
|
2326 break; |
|
2327 default: |
|
2328 break; |
|
2329 } |
|
2330 return QWindowsXPStyle::event(e); |
|
2331 } |
|
2332 |
|
2333 /*! |
|
2334 \internal |
|
2335 */ |
|
2336 QStyle::SubControl QWindowsVistaStyle::hitTestComplexControl(ComplexControl control, const QStyleOptionComplex *option, |
|
2337 const QPoint &pos, const QWidget *widget) const |
|
2338 { |
|
2339 if (!QWindowsVistaStylePrivate::useVista()) { |
|
2340 return QWindowsStyle::hitTestComplexControl(control, option, pos, widget); |
|
2341 } |
|
2342 return QWindowsXPStyle::hitTestComplexControl(control, option, pos, widget); |
|
2343 } |
|
2344 |
|
2345 /*! |
|
2346 \internal |
|
2347 */ |
|
2348 int QWindowsVistaStyle::pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const |
|
2349 { |
|
2350 if (!QWindowsVistaStylePrivate::useVista()) { |
|
2351 return QWindowsStyle::pixelMetric(metric, option, widget); |
|
2352 } |
|
2353 switch (metric) { |
|
2354 |
|
2355 case PM_DockWidgetTitleBarButtonMargin: |
|
2356 return int(QStyleHelper::dpiScaled(5.)); |
|
2357 case PM_ScrollBarSliderMin: |
|
2358 return int(QStyleHelper::dpiScaled(18.)); |
|
2359 case PM_MenuHMargin: |
|
2360 case PM_MenuVMargin: |
|
2361 return 0; |
|
2362 case PM_MenuPanelWidth: |
|
2363 return 3; |
|
2364 default: |
|
2365 break; |
|
2366 } |
|
2367 return QWindowsXPStyle::pixelMetric(metric, option, widget); |
|
2368 } |
|
2369 |
|
2370 /*! |
|
2371 \internal |
|
2372 */ |
|
2373 QPalette QWindowsVistaStyle::standardPalette() const |
|
2374 { |
|
2375 return QWindowsXPStyle::standardPalette(); |
|
2376 } |
|
2377 |
|
2378 /*! |
|
2379 \internal |
|
2380 */ |
|
2381 void QWindowsVistaStyle::polish(QApplication *app) |
|
2382 { |
|
2383 QWindowsXPStyle::polish(app); |
|
2384 } |
|
2385 |
|
2386 /*! |
|
2387 \internal |
|
2388 */ |
|
2389 void QWindowsVistaStyle::polish(QWidget *widget) |
|
2390 { |
|
2391 QWindowsXPStyle::polish(widget); |
|
2392 #ifndef QT_NO_LINEEDIT |
|
2393 if (qobject_cast<QLineEdit*>(widget)) |
|
2394 widget->setAttribute(Qt::WA_Hover); |
|
2395 else |
|
2396 #endif // QT_NO_LINEEDIT |
|
2397 if (qobject_cast<QGroupBox*>(widget)) |
|
2398 widget->setAttribute(Qt::WA_Hover); |
|
2399 else if (qobject_cast<QCommandLinkButton*>(widget)) { |
|
2400 QFont buttonFont = widget->font(); |
|
2401 buttonFont.setFamily(QLatin1String("Segoe UI")); |
|
2402 widget->setFont(buttonFont); |
|
2403 } |
|
2404 else if (widget->inherits("QTipLabel")){ |
|
2405 //note that since tooltips are not reused |
|
2406 //we do not have to care about unpolishing |
|
2407 widget->setContentsMargins(3, 0, 4, 0); |
|
2408 COLORREF bgRef; |
|
2409 HTHEME theme = pOpenThemeData(widget ? QWindowsVistaStylePrivate::winId(widget) : 0, L"TOOLTIP"); |
|
2410 if (theme) { |
|
2411 if (pGetThemeColor(theme, TTP_STANDARD, TTSS_NORMAL, TMT_TEXTCOLOR, &bgRef) == S_OK) { |
|
2412 QColor textColor = QColor::fromRgb(bgRef); |
|
2413 QPalette pal; |
|
2414 pal.setColor(QPalette::All, QPalette::ToolTipText, textColor); |
|
2415 widget->setPalette(pal); |
|
2416 } |
|
2417 } |
|
2418 } else if (qobject_cast<QMessageBox *> (widget)) { |
|
2419 widget->setAttribute(Qt::WA_StyledBackground); |
|
2420 QDialogButtonBox *buttonBox = qFindChild<QDialogButtonBox *>(widget,QLatin1String("qt_msgbox_buttonbox")); |
|
2421 if (buttonBox) |
|
2422 buttonBox->setContentsMargins(0, 9, 0, 0); |
|
2423 } |
|
2424 #ifndef QT_NO_INPUTDIALOG |
|
2425 else if (qobject_cast<QInputDialog *> (widget)) { |
|
2426 widget->setAttribute(Qt::WA_StyledBackground); |
|
2427 QDialogButtonBox *buttonBox = qFindChild<QDialogButtonBox *>(widget,QLatin1String("qt_inputdlg_buttonbox")); |
|
2428 if (buttonBox) |
|
2429 buttonBox->setContentsMargins(0, 9, 0, 0); |
|
2430 } |
|
2431 #endif // QT_NO_INPUTDIALOG |
|
2432 else if (QTreeView *tree = qobject_cast<QTreeView *> (widget)) { |
|
2433 tree->viewport()->setAttribute(Qt::WA_Hover); |
|
2434 } |
|
2435 else if (QListView *list = qobject_cast<QListView *> (widget)) { |
|
2436 list->viewport()->setAttribute(Qt::WA_Hover); |
|
2437 } |
|
2438 } |
|
2439 |
|
2440 /*! |
|
2441 \internal |
|
2442 */ |
|
2443 void QWindowsVistaStyle::unpolish(QWidget *widget) |
|
2444 { |
|
2445 QWindowsXPStyle::unpolish(widget); |
|
2446 |
|
2447 QWindowsVistaStylePrivate *d = const_cast<QWindowsVistaStylePrivate*>(d_func()); |
|
2448 d->stopAnimation(widget); |
|
2449 |
|
2450 #ifndef QT_NO_LINEEDIT |
|
2451 if (qobject_cast<QLineEdit*>(widget)) |
|
2452 widget->setAttribute(Qt::WA_Hover, false); |
|
2453 else |
|
2454 #endif // QT_NO_LINEEDIT |
|
2455 if (qobject_cast<QGroupBox*>(widget)) |
|
2456 widget->setAttribute(Qt::WA_Hover, false); |
|
2457 else if (qobject_cast<QMessageBox *> (widget)) { |
|
2458 widget->setAttribute(Qt::WA_StyledBackground, false); |
|
2459 QDialogButtonBox *buttonBox = qFindChild<QDialogButtonBox *>(widget,QLatin1String("qt_msgbox_buttonbox")); |
|
2460 if (buttonBox) |
|
2461 buttonBox->setContentsMargins(0, 0, 0, 0); |
|
2462 } |
|
2463 #ifndef QT_NO_INPUTDIALOG |
|
2464 else if (qobject_cast<QInputDialog *> (widget)) { |
|
2465 widget->setAttribute(Qt::WA_StyledBackground, false); |
|
2466 QDialogButtonBox *buttonBox = qFindChild<QDialogButtonBox *>(widget,QLatin1String("qt_inputdlg_buttonbox")); |
|
2467 if (buttonBox) |
|
2468 buttonBox->setContentsMargins(0, 0, 0, 0); |
|
2469 } |
|
2470 #endif // QT_NO_INPUTDIALOG |
|
2471 else if (QTreeView *tree = qobject_cast<QTreeView *> (widget)) { |
|
2472 tree->viewport()->setAttribute(Qt::WA_Hover, false); |
|
2473 } else if (qobject_cast<QCommandLinkButton*>(widget)) { |
|
2474 QFont font = QApplication::font("QCommandLinkButton"); |
|
2475 QFont widgetFont = widget->font(); |
|
2476 widgetFont.setFamily(font.family()); //Only family set by polish |
|
2477 widget->setFont(widgetFont); |
|
2478 } |
|
2479 } |
|
2480 |
|
2481 |
|
2482 /*! |
|
2483 \internal |
|
2484 */ |
|
2485 void QWindowsVistaStyle::unpolish(QApplication *app) |
|
2486 { |
|
2487 QWindowsXPStyle::unpolish(app); |
|
2488 } |
|
2489 |
|
2490 /*! |
|
2491 \internal |
|
2492 */ |
|
2493 void QWindowsVistaStyle::polish(QPalette &pal) |
|
2494 { |
|
2495 QWindowsStyle::polish(pal); |
|
2496 pal.setBrush(QPalette::AlternateBase, pal.base().color().darker(104)); |
|
2497 } |
|
2498 |
|
2499 /*! |
|
2500 \internal |
|
2501 */ |
|
2502 QPixmap QWindowsVistaStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *option, |
|
2503 const QWidget *widget) const |
|
2504 { |
|
2505 if (!QWindowsVistaStylePrivate::useVista()) { |
|
2506 return QWindowsStyle::standardPixmap(standardPixmap, option, widget); |
|
2507 } |
|
2508 return QWindowsXPStyle::standardPixmap(standardPixmap, option, widget); |
|
2509 } |
|
2510 |
|
2511 QWindowsVistaStylePrivate::QWindowsVistaStylePrivate() : |
|
2512 QWindowsXPStylePrivate(), m_treeViewHelper(0) |
|
2513 { |
|
2514 resolveSymbols(); |
|
2515 } |
|
2516 |
|
2517 QWindowsVistaStylePrivate::~QWindowsVistaStylePrivate() |
|
2518 { |
|
2519 delete m_treeViewHelper; |
|
2520 } |
|
2521 |
|
2522 void QWindowsVistaStylePrivate::timerEvent() |
|
2523 { |
|
2524 for (int i = animations.size() - 1 ; i >= 0 ; --i) { |
|
2525 |
|
2526 if (animations[i]->widget()) |
|
2527 animations[i]->widget()->update(); |
|
2528 |
|
2529 if (!animations[i]->widget() || |
|
2530 !animations[i]->widget()->isEnabled() || |
|
2531 !animations[i]->widget()->isVisible() || |
|
2532 animations[i]->widget()->window()->isMinimized() || |
|
2533 !animations[i]->running() || |
|
2534 !QWindowsVistaStylePrivate::useVista()) |
|
2535 { |
|
2536 Animation *a = animations.takeAt(i); |
|
2537 delete a; |
|
2538 } |
|
2539 } |
|
2540 if (animations.size() == 0 && animationTimer.isActive()) { |
|
2541 animationTimer.stop(); |
|
2542 } |
|
2543 } |
|
2544 |
|
2545 void QWindowsVistaStylePrivate::stopAnimation(const QWidget *w) |
|
2546 { |
|
2547 for (int i = animations.size() - 1 ; i >= 0 ; --i) { |
|
2548 if (animations[i]->widget() == w) { |
|
2549 Animation *a = animations.takeAt(i); |
|
2550 delete a; |
|
2551 break; |
|
2552 } |
|
2553 } |
|
2554 } |
|
2555 |
|
2556 void QWindowsVistaStylePrivate::startAnimation(Animation *t) |
|
2557 { |
|
2558 Q_Q(QWindowsVistaStyle); |
|
2559 stopAnimation(t->widget()); |
|
2560 animations.append(t); |
|
2561 if (animations.size() > 0 && !animationTimer.isActive()) { |
|
2562 animationTimer.start(45, q); |
|
2563 } |
|
2564 } |
|
2565 |
|
2566 bool QWindowsVistaStylePrivate::transitionsEnabled() const |
|
2567 { |
|
2568 BOOL animEnabled = false; |
|
2569 if (SystemParametersInfo(SPI_GETCLIENTAREAANIMATION, 0, &animEnabled, 0)) |
|
2570 { |
|
2571 if (animEnabled) |
|
2572 return true; |
|
2573 } |
|
2574 return false; |
|
2575 } |
|
2576 |
|
2577 |
|
2578 Animation * QWindowsVistaStylePrivate::widgetAnimation(const QWidget *widget) const |
|
2579 { |
|
2580 if (!widget) |
|
2581 return 0; |
|
2582 foreach (Animation *a, animations) { |
|
2583 if (a->widget() == widget) |
|
2584 return a; |
|
2585 } |
|
2586 return 0; |
|
2587 } |
|
2588 |
|
2589 |
|
2590 /*! \internal |
|
2591 Returns true if all the necessary theme engine symbols were |
|
2592 resolved. |
|
2593 */ |
|
2594 bool QWindowsVistaStylePrivate::resolveSymbols() |
|
2595 { |
|
2596 static bool tried = false; |
|
2597 if (!tried) { |
|
2598 tried = true; |
|
2599 QLibrary themeLib(QLatin1String("uxtheme")); |
|
2600 pSetWindowTheme = (PtrSetWindowTheme )themeLib.resolve("SetWindowTheme"); |
|
2601 pIsThemePartDefined = (PtrIsThemePartDefined )themeLib.resolve("IsThemePartDefined"); |
|
2602 pGetThemePartSize = (PtrGetThemePartSize )themeLib.resolve("GetThemePartSize"); |
|
2603 pOpenThemeData = (PtrOpenThemeData )themeLib.resolve("OpenThemeData"); |
|
2604 pCloseThemeData = (PtrCloseThemeData )themeLib.resolve("CloseThemeData"); |
|
2605 pDrawThemeBackground = (PtrDrawThemeBackground )themeLib.resolve("DrawThemeBackground"); |
|
2606 pDrawThemeBackgroundEx = (PtrDrawThemeBackgroundEx )themeLib.resolve("DrawThemeBackgroundEx"); |
|
2607 pGetCurrentThemeName = (PtrGetCurrentThemeName )themeLib.resolve("GetCurrentThemeName"); |
|
2608 pGetThemeBool = (PtrGetThemeBool )themeLib.resolve("GetThemeBool"); |
|
2609 pGetThemeColor = (PtrGetThemeColor )themeLib.resolve("GetThemeColor"); |
|
2610 pGetThemeEnumValue = (PtrGetThemeEnumValue )themeLib.resolve("GetThemeEnumValue"); |
|
2611 pGetThemeFilename = (PtrGetThemeFilename )themeLib.resolve("GetThemeFilename"); |
|
2612 pGetThemeFont = (PtrGetThemeFont )themeLib.resolve("GetThemeFont"); |
|
2613 pGetThemeInt = (PtrGetThemeInt )themeLib.resolve("GetThemeInt"); |
|
2614 pGetThemeIntList = (PtrGetThemeIntList )themeLib.resolve("GetThemeIntList"); |
|
2615 pGetThemeMargins = (PtrGetThemeMargins )themeLib.resolve("GetThemeMargins"); |
|
2616 pGetThemeMetric = (PtrGetThemeMetric )themeLib.resolve("GetThemeMetric"); |
|
2617 pGetThemePartSize = (PtrGetThemePartSize )themeLib.resolve("GetThemePartSize"); |
|
2618 pGetThemePosition = (PtrGetThemePosition )themeLib.resolve("GetThemePosition"); |
|
2619 pGetThemeRect = (PtrGetThemeRect )themeLib.resolve("GetThemeRect"); |
|
2620 pGetThemeString = (PtrGetThemeString )themeLib.resolve("GetThemeString"); |
|
2621 pGetThemeTransitionDuration = (PtrGetThemeTransitionDuration)themeLib.resolve("GetThemeTransitionDuration"); |
|
2622 pGetThemePropertyOrigin = (PtrGetThemePropertyOrigin)themeLib.resolve("GetThemePropertyOrigin"); |
|
2623 } |
|
2624 return pGetThemeTransitionDuration != 0; |
|
2625 } |
|
2626 |
|
2627 /* |
|
2628 * We need to set the windows explorer theme explicitly on a native widget |
|
2629 * in order to get Vista-style item view themes |
|
2630 */ |
|
2631 QWidget *QWindowsVistaStylePrivate::treeViewHelper() |
|
2632 { |
|
2633 if (!m_treeViewHelper) { |
|
2634 m_treeViewHelper = new QWidget(0); |
|
2635 pSetWindowTheme(m_treeViewHelper->winId(), L"explorer", NULL); |
|
2636 } |
|
2637 return m_treeViewHelper; |
|
2638 } |
|
2639 |
|
2640 |
|
2641 /*! |
|
2642 \internal |
|
2643 */ |
|
2644 QIcon QWindowsVistaStyle::standardIconImplementation(StandardPixmap standardIcon, |
|
2645 const QStyleOption *option, |
|
2646 const QWidget *widget) const |
|
2647 { |
|
2648 if (!QWindowsVistaStylePrivate::useVista()) { |
|
2649 return QWindowsStyle::standardIconImplementation(standardIcon, option, widget); |
|
2650 } |
|
2651 |
|
2652 QWindowsVistaStylePrivate *d = const_cast<QWindowsVistaStylePrivate *>(d_func()); |
|
2653 switch(standardIcon) { |
|
2654 case SP_CommandLink: |
|
2655 { |
|
2656 XPThemeData theme(0, 0, QLatin1String("BUTTON"), BP_COMMANDLINKGLYPH, CMDLGS_NORMAL); |
|
2657 if (theme.isValid()) { |
|
2658 SIZE size; |
|
2659 pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); |
|
2660 QIcon linkGlyph; |
|
2661 QPixmap pm = QPixmap(size.cx, size.cy); |
|
2662 pm.fill(Qt::transparent); |
|
2663 QPainter p(&pm); |
|
2664 theme.painter = &p; |
|
2665 theme.rect = QRect(0, 0, size.cx, size.cy); |
|
2666 d->drawBackground(theme); |
|
2667 linkGlyph.addPixmap(pm, QIcon::Normal, QIcon::Off); // Normal |
|
2668 pm.fill(Qt::transparent); |
|
2669 |
|
2670 theme.stateId = CMDLGS_PRESSED; |
|
2671 d->drawBackground(theme); |
|
2672 linkGlyph.addPixmap(pm, QIcon::Normal, QIcon::On); // Pressed |
|
2673 pm.fill(Qt::transparent); |
|
2674 |
|
2675 theme.stateId = CMDLGS_HOT; |
|
2676 d->drawBackground(theme); |
|
2677 linkGlyph.addPixmap(pm, QIcon::Active, QIcon::Off); // Hover |
|
2678 pm.fill(Qt::transparent); |
|
2679 |
|
2680 theme.stateId = CMDLGS_DISABLED; |
|
2681 d->drawBackground(theme); |
|
2682 linkGlyph.addPixmap(pm, QIcon::Disabled, QIcon::Off); // Disabled |
|
2683 return linkGlyph; |
|
2684 } |
|
2685 } |
|
2686 break; |
|
2687 default: |
|
2688 break; |
|
2689 } |
|
2690 return QWindowsXPStyle::standardIconImplementation(standardIcon, option, widget); |
|
2691 } |
|
2692 |
|
2693 QT_END_NAMESPACE |
|
2694 |
|
2695 #endif //QT_NO_WINDOWSVISTA |