|
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 #include "qwindowsxpstyle.h" |
|
42 #include "qwindowsxpstyle_p.h" |
|
43 |
|
44 #if !defined(QT_NO_STYLE_WINDOWSXP) || defined(QT_PLUGIN) |
|
45 |
|
46 #include <private/qobject_p.h> |
|
47 #include <private/qpaintengine_raster_p.h> |
|
48 #include <private/qapplication_p.h> |
|
49 #include <private/qstylehelper_p.h> |
|
50 #include <qlibrary.h> |
|
51 #include <qpainter.h> |
|
52 #include <qpaintengine.h> |
|
53 #include <qwidget.h> |
|
54 #include <qapplication.h> |
|
55 #include <qpixmapcache.h> |
|
56 |
|
57 #include <qdesktopwidget.h> |
|
58 #include <qtoolbutton.h> |
|
59 #include <qtabbar.h> |
|
60 #include <qcombobox.h> |
|
61 #include <qscrollbar.h> |
|
62 #include <qheaderview.h> |
|
63 #include <qspinbox.h> |
|
64 #include <qlistview.h> |
|
65 #include <qstackedwidget.h> |
|
66 #include <qpushbutton.h> |
|
67 #include <qtoolbar.h> |
|
68 #include <qlabel.h> |
|
69 #include <qvarlengtharray.h> |
|
70 #include <qdebug.h> |
|
71 |
|
72 QT_BEGIN_NAMESPACE |
|
73 |
|
74 // Runtime resolved theme engine function calls |
|
75 typedef bool (WINAPI *PtrIsAppThemed)(); |
|
76 typedef bool (WINAPI *PtrIsThemeActive)(); |
|
77 typedef HRESULT (WINAPI *PtrGetThemePartSize)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, OPTIONAL RECT *prc, enum THEMESIZE eSize, OUT SIZE *psz); |
|
78 typedef HTHEME (WINAPI *PtrOpenThemeData)(HWND hwnd, LPCWSTR pszClassList); |
|
79 typedef HRESULT (WINAPI *PtrCloseThemeData)(HTHEME hTheme); |
|
80 typedef HRESULT (WINAPI *PtrDrawThemeBackground)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, OPTIONAL const RECT *pClipRect); |
|
81 typedef HRESULT (WINAPI *PtrDrawThemeBackgroundEx)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, OPTIONAL const DTBGOPTS *pOptions); |
|
82 typedef HRESULT (WINAPI *PtrGetCurrentThemeName)(OUT LPWSTR pszThemeFileName, int cchMaxNameChars, OUT OPTIONAL LPWSTR pszColorBuff, int cchMaxColorChars, OUT OPTIONAL LPWSTR pszSizeBuff, int cchMaxSizeChars); |
|
83 typedef HRESULT (WINAPI *PtrGetThemeDocumentationProperty)(LPCWSTR pszThemeName, LPCWSTR pszPropertyName, OUT LPWSTR pszValueBuff, int cchMaxValChars); |
|
84 typedef HRESULT (WINAPI *PtrGetThemeBool)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT BOOL *pfVal); |
|
85 typedef HRESULT (WINAPI *PtrGetThemeColor)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT COLORREF *pColor); |
|
86 typedef HRESULT (WINAPI *PtrGetThemeEnumValue)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT int *piVal); |
|
87 typedef HRESULT (WINAPI *PtrGetThemeFilename)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT LPWSTR pszThemeFileName, int cchMaxBuffChars); |
|
88 typedef HRESULT (WINAPI *PtrGetThemeFont)(HTHEME hTheme, OPTIONAL HDC hdc, int iPartId, int iStateId, int iPropId, OUT LOGFONT *pFont); |
|
89 typedef HRESULT (WINAPI *PtrGetThemeInt)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT int *piVal); |
|
90 typedef HRESULT (WINAPI *PtrGetThemeIntList)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT INTLIST *pIntList); |
|
91 typedef HRESULT (WINAPI *PtrGetThemeMargins)(HTHEME hTheme, OPTIONAL HDC hdc, int iPartId, int iStateId, int iPropId, OPTIONAL RECT *prc, OUT MARGINS *pMargins); |
|
92 typedef HRESULT (WINAPI *PtrGetThemeMetric)(HTHEME hTheme, OPTIONAL HDC hdc, int iPartId, int iStateId, int iPropId, OUT int *piVal); |
|
93 typedef HRESULT (WINAPI *PtrGetThemePartSize)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, OPTIONAL RECT *prc, enum THEMESIZE eSize, OUT SIZE *psz); |
|
94 typedef HRESULT (WINAPI *PtrGetThemePosition)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT POINT *pPoint); |
|
95 typedef HRESULT (WINAPI *PtrGetThemePropertyOrigin)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT enum PROPERTYORIGIN *pOrigin); |
|
96 typedef HRESULT (WINAPI *PtrGetThemeRect)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT RECT *pRect); |
|
97 typedef HRESULT (WINAPI *PtrGetThemeString)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT LPWSTR pszBuff, int cchMaxBuffChars); |
|
98 typedef HRESULT (WINAPI *PtrGetThemeBackgroundRegion)(HTHEME hTheme, OPTIONAL HDC hdc, int iPartId, int iStateId, const RECT *pRect, OUT HRGN *pRegion); |
|
99 typedef BOOL (WINAPI *PtrIsThemeBackgroundPartiallyTransparent)(HTHEME hTheme, int iPartId, int iStateId); |
|
100 |
|
101 static PtrIsAppThemed pIsAppThemed = 0; |
|
102 static PtrIsThemeActive pIsThemeActive = 0; |
|
103 static PtrOpenThemeData pOpenThemeData = 0; |
|
104 static PtrCloseThemeData pCloseThemeData = 0; |
|
105 static PtrDrawThemeBackground pDrawThemeBackground = 0; |
|
106 static PtrDrawThemeBackgroundEx pDrawThemeBackgroundEx = 0; |
|
107 static PtrGetCurrentThemeName pGetCurrentThemeName = 0; |
|
108 static PtrGetThemeBool pGetThemeBool = 0; |
|
109 static PtrGetThemeColor pGetThemeColor = 0; |
|
110 static PtrGetThemeEnumValue pGetThemeEnumValue = 0; |
|
111 static PtrGetThemeFilename pGetThemeFilename = 0; |
|
112 static PtrGetThemeFont pGetThemeFont = 0; |
|
113 static PtrGetThemeInt pGetThemeInt = 0; |
|
114 static PtrGetThemeIntList pGetThemeIntList = 0; |
|
115 static PtrGetThemeMargins pGetThemeMargins = 0; |
|
116 static PtrGetThemeMetric pGetThemeMetric = 0; |
|
117 static PtrGetThemePartSize pGetThemePartSize = 0; |
|
118 static PtrGetThemePosition pGetThemePosition = 0; |
|
119 static PtrGetThemePropertyOrigin pGetThemePropertyOrigin = 0; |
|
120 static PtrGetThemeRect pGetThemeRect = 0; |
|
121 static PtrGetThemeString pGetThemeString = 0; |
|
122 static PtrGetThemeBackgroundRegion pGetThemeBackgroundRegion = 0; |
|
123 static PtrGetThemeDocumentationProperty pGetThemeDocumentationProperty = 0; |
|
124 static PtrIsThemeBackgroundPartiallyTransparent pIsThemeBackgroundPartiallyTransparent = 0; |
|
125 |
|
126 // General const values |
|
127 static const int windowsItemFrame = 2; // menu item frame width |
|
128 static const int windowsItemHMargin = 3; // menu item hor text margin |
|
129 static const int windowsItemVMargin = 0; // menu item ver text margin |
|
130 static const int windowsArrowHMargin = 6; // arrow horizontal margin |
|
131 static const int windowsRightBorder = 12; // right border on windows |
|
132 |
|
133 // External function calls |
|
134 extern Q_GUI_EXPORT HDC qt_win_display_dc(); |
|
135 extern QRegion qt_region_from_HRGN(HRGN rgn); |
|
136 |
|
137 |
|
138 |
|
139 // Theme data helper ------------------------------------------------------------------------------ |
|
140 /* \internal |
|
141 Returns true if the themedata is valid for use. |
|
142 */ |
|
143 bool XPThemeData::isValid() |
|
144 { |
|
145 return QWindowsXPStylePrivate::useXP() && name.size() && handle(); |
|
146 } |
|
147 |
|
148 |
|
149 /* \internal |
|
150 Returns the theme engine handle to the specific class. |
|
151 If the handle hasn't been opened before, it opens the data, and |
|
152 adds it to a static map, for caching. |
|
153 */ |
|
154 HTHEME XPThemeData::handle() |
|
155 { |
|
156 if (!QWindowsXPStylePrivate::useXP()) |
|
157 return 0; |
|
158 |
|
159 if (!htheme && QWindowsXPStylePrivate::handleMap) |
|
160 htheme = QWindowsXPStylePrivate::handleMap->operator[](name); |
|
161 |
|
162 if (!htheme) { |
|
163 htheme = pOpenThemeData(QWindowsXPStylePrivate::winId(widget), (wchar_t*)name.utf16()); |
|
164 if (htheme) { |
|
165 if (!QWindowsXPStylePrivate::handleMap) |
|
166 QWindowsXPStylePrivate::handleMap = new QMap<QString, HTHEME>; |
|
167 QWindowsXPStylePrivate::handleMap->operator[](name) = htheme; |
|
168 } |
|
169 } |
|
170 |
|
171 return htheme; |
|
172 } |
|
173 |
|
174 /* \internal |
|
175 Converts a QRect to the native RECT structure. |
|
176 */ |
|
177 RECT XPThemeData::toRECT(const QRect &qr) |
|
178 { |
|
179 RECT r; |
|
180 r.left = qr.x(); |
|
181 r.right = qr.x() + qr.width(); |
|
182 r.top = qr.y(); |
|
183 r.bottom = qr.y() + qr.height(); |
|
184 return r; |
|
185 } |
|
186 |
|
187 /* \internal |
|
188 Returns the native region of a part, if the part is considered |
|
189 transparent. The region is scaled to the parts size (rect). |
|
190 */ |
|
191 HRGN XPThemeData::mask() |
|
192 { |
|
193 if (!pIsThemeBackgroundPartiallyTransparent(handle(), partId, stateId)) |
|
194 return 0; |
|
195 |
|
196 HRGN hrgn; |
|
197 HDC dc = painter == 0 ? 0 : painter->paintEngine()->getDC(); |
|
198 RECT nativeRect = toRECT(rect); |
|
199 pGetThemeBackgroundRegion(handle(), dc, partId, stateId, &nativeRect, &hrgn); |
|
200 if (dc) |
|
201 painter->paintEngine()->releaseDC(dc); |
|
202 return hrgn; |
|
203 } |
|
204 |
|
205 // QWindowsXPStylePrivate ------------------------------------------------------------------------- |
|
206 // Static initializations |
|
207 QWidget *QWindowsXPStylePrivate::limboWidget = 0; |
|
208 QPixmap *QWindowsXPStylePrivate::tabbody = 0; |
|
209 QMap<QString,HTHEME> *QWindowsXPStylePrivate::handleMap = 0; |
|
210 bool QWindowsXPStylePrivate::use_xp = false; |
|
211 QBasicAtomicInt QWindowsXPStylePrivate::ref = Q_BASIC_ATOMIC_INITIALIZER(-1); // -1 based refcounting |
|
212 |
|
213 /* \internal |
|
214 Checks if the theme engine can/should be used, or if we should |
|
215 fall back to Windows style. |
|
216 */ |
|
217 bool QWindowsXPStylePrivate::useXP(bool update) |
|
218 { |
|
219 if (!update) |
|
220 return use_xp; |
|
221 return (use_xp = resolveSymbols() && pIsThemeActive() |
|
222 && (pIsAppThemed() || !QApplication::instance())); |
|
223 } |
|
224 |
|
225 /* \internal |
|
226 Handles refcounting, and queries the theme engine for usage. |
|
227 */ |
|
228 void QWindowsXPStylePrivate::init(bool force) |
|
229 { |
|
230 if (ref.ref() && !force) |
|
231 return; |
|
232 if (!force) // -1 based atomic refcounting |
|
233 ref.ref(); |
|
234 |
|
235 useXP(true); |
|
236 } |
|
237 |
|
238 /* \internal |
|
239 Cleans up all static data. |
|
240 */ |
|
241 void QWindowsXPStylePrivate::cleanup(bool force) |
|
242 { |
|
243 if(bufferBitmap) { |
|
244 if (bufferDC && nullBitmap) |
|
245 SelectObject(bufferDC, nullBitmap); |
|
246 DeleteObject(bufferBitmap); |
|
247 bufferBitmap = 0; |
|
248 } |
|
249 |
|
250 if(bufferDC) |
|
251 DeleteDC(bufferDC); |
|
252 bufferDC = 0; |
|
253 |
|
254 if (ref.deref() && !force) |
|
255 return; |
|
256 if (!force) // -1 based atomic refcounting |
|
257 ref.deref(); |
|
258 |
|
259 use_xp = false; |
|
260 cleanupHandleMap(); |
|
261 if (limboWidget) { |
|
262 if (QApplication::closingDown()) |
|
263 delete limboWidget; |
|
264 else |
|
265 limboWidget->deleteLater(); |
|
266 } |
|
267 delete tabbody; |
|
268 limboWidget = 0; |
|
269 tabbody = 0; |
|
270 } |
|
271 |
|
272 /* \internal |
|
273 Closes all open theme data handles to ensure that we don't leak |
|
274 resources, and that we don't refere to old handles when for |
|
275 example the user changes the theme style. |
|
276 */ |
|
277 void QWindowsXPStylePrivate::cleanupHandleMap() |
|
278 { |
|
279 if (!handleMap) |
|
280 return; |
|
281 |
|
282 QMap<QString, HTHEME>::Iterator it; |
|
283 for (it = handleMap->begin(); it != handleMap->end(); ++it) |
|
284 pCloseThemeData(it.value()); |
|
285 delete handleMap; |
|
286 handleMap = 0; |
|
287 } |
|
288 |
|
289 /*! \internal |
|
290 This function will always return a valid window handle, and might |
|
291 create a limbo widget to do so. |
|
292 We often need a window handle to for example open theme data, so |
|
293 this function ensures that we get one. |
|
294 */ |
|
295 HWND QWindowsXPStylePrivate::winId(const QWidget *widget) |
|
296 { |
|
297 if (widget && widget->internalWinId()) |
|
298 return widget->internalWinId(); |
|
299 |
|
300 if (!limboWidget) { |
|
301 limboWidget = new QWidget(0); |
|
302 limboWidget->setObjectName(QLatin1String("xp_limbo_widget")); |
|
303 } |
|
304 |
|
305 return limboWidget->winId(); |
|
306 } |
|
307 |
|
308 /*! \internal |
|
309 Returns the pointer to a tab widgets body pixmap, scaled to the |
|
310 height of the screen. This way the theme engine doesn't need to |
|
311 scale the body for every time we ask for it. (Speed optimization) |
|
312 */ |
|
313 const QPixmap *QWindowsXPStylePrivate::tabBody(QWidget *) |
|
314 { |
|
315 if (!tabbody) { |
|
316 SIZE sz; |
|
317 XPThemeData theme(0, 0, QLatin1String("TAB"), TABP_BODY); |
|
318 pGetThemePartSize(theme.handle(), qt_win_display_dc(), TABP_BODY, 0, 0, TS_TRUE, &sz); |
|
319 |
|
320 tabbody = new QPixmap(sz.cx, QApplication::desktop()->screenGeometry().height()); |
|
321 QPainter painter(tabbody); |
|
322 theme.rect = QRect(0, 0, sz.cx, sz.cy); |
|
323 drawBackground(theme); |
|
324 // We fill with the last line of the themedata, that |
|
325 // way we don't get a tiled pixmap inside big tabs |
|
326 QPixmap temp(sz.cx, 1); |
|
327 painter.drawPixmap(0, 0, temp, 0, sz.cy-1, -1, -1); |
|
328 painter.drawTiledPixmap(0, sz.cy, sz.cx, tabbody->height()-sz.cy, temp); |
|
329 } |
|
330 return tabbody; |
|
331 } |
|
332 |
|
333 /*! \internal |
|
334 Returns true if all the necessary theme engine symbols were |
|
335 resolved. |
|
336 */ |
|
337 bool QWindowsXPStylePrivate::resolveSymbols() |
|
338 { |
|
339 static bool tried = false; |
|
340 if (!tried) { |
|
341 tried = true; |
|
342 QLibrary themeLib(QLatin1String("uxtheme")); |
|
343 pIsAppThemed = (PtrIsAppThemed)themeLib.resolve("IsAppThemed"); |
|
344 if (pIsAppThemed) { |
|
345 pIsThemeActive = (PtrIsThemeActive )themeLib.resolve("IsThemeActive"); |
|
346 pGetThemePartSize = (PtrGetThemePartSize )themeLib.resolve("GetThemePartSize"); |
|
347 pOpenThemeData = (PtrOpenThemeData )themeLib.resolve("OpenThemeData"); |
|
348 pCloseThemeData = (PtrCloseThemeData )themeLib.resolve("CloseThemeData"); |
|
349 pDrawThemeBackground = (PtrDrawThemeBackground )themeLib.resolve("DrawThemeBackground"); |
|
350 pDrawThemeBackgroundEx = (PtrDrawThemeBackgroundEx )themeLib.resolve("DrawThemeBackgroundEx"); |
|
351 pGetCurrentThemeName = (PtrGetCurrentThemeName )themeLib.resolve("GetCurrentThemeName"); |
|
352 pGetThemeBool = (PtrGetThemeBool )themeLib.resolve("GetThemeBool"); |
|
353 pGetThemeColor = (PtrGetThemeColor )themeLib.resolve("GetThemeColor"); |
|
354 pGetThemeEnumValue = (PtrGetThemeEnumValue )themeLib.resolve("GetThemeEnumValue"); |
|
355 pGetThemeFilename = (PtrGetThemeFilename )themeLib.resolve("GetThemeFilename"); |
|
356 pGetThemeFont = (PtrGetThemeFont )themeLib.resolve("GetThemeFont"); |
|
357 pGetThemeInt = (PtrGetThemeInt )themeLib.resolve("GetThemeInt"); |
|
358 pGetThemeIntList = (PtrGetThemeIntList )themeLib.resolve("GetThemeIntList"); |
|
359 pGetThemeMargins = (PtrGetThemeMargins )themeLib.resolve("GetThemeMargins"); |
|
360 pGetThemeMetric = (PtrGetThemeMetric )themeLib.resolve("GetThemeMetric"); |
|
361 pGetThemePartSize = (PtrGetThemePartSize )themeLib.resolve("GetThemePartSize"); |
|
362 pGetThemePosition = (PtrGetThemePosition )themeLib.resolve("GetThemePosition"); |
|
363 pGetThemePropertyOrigin = (PtrGetThemePropertyOrigin)themeLib.resolve("GetThemePropertyOrigin"); |
|
364 pGetThemeRect = (PtrGetThemeRect )themeLib.resolve("GetThemeRect"); |
|
365 pGetThemeString = (PtrGetThemeString )themeLib.resolve("GetThemeString"); |
|
366 pGetThemeBackgroundRegion = (PtrGetThemeBackgroundRegion )themeLib.resolve("GetThemeBackgroundRegion"); |
|
367 pGetThemeDocumentationProperty = (PtrGetThemeDocumentationProperty )themeLib.resolve("GetThemeDocumentationProperty"); |
|
368 pIsThemeBackgroundPartiallyTransparent = (PtrIsThemeBackgroundPartiallyTransparent)themeLib.resolve("IsThemeBackgroundPartiallyTransparent"); |
|
369 } |
|
370 } |
|
371 |
|
372 return pIsAppThemed != 0; |
|
373 } |
|
374 |
|
375 /*! \internal |
|
376 Returns a native buffer (DIB section) of at least the size of |
|
377 ( \a x , \a y ). The buffer has a 32 bit depth, to not lose |
|
378 the alpha values on proper alpha-pixmaps. |
|
379 */ |
|
380 HBITMAP QWindowsXPStylePrivate::buffer(int w, int h) |
|
381 { |
|
382 // If we already have a HBITMAP which is of adequate size, just return that |
|
383 if (bufferBitmap) { |
|
384 if (bufferW >= w && bufferH >= h) |
|
385 return bufferBitmap; |
|
386 // Not big enough, discard the old one |
|
387 if (bufferDC && nullBitmap) |
|
388 SelectObject(bufferDC, nullBitmap); |
|
389 DeleteObject(bufferBitmap); |
|
390 bufferBitmap = 0; |
|
391 } |
|
392 |
|
393 w = qMax(bufferW, w); |
|
394 h = qMax(bufferH, h); |
|
395 |
|
396 if (!bufferDC) |
|
397 bufferDC = CreateCompatibleDC(qt_win_display_dc()); |
|
398 |
|
399 // Define the header |
|
400 BITMAPINFO bmi; |
|
401 memset(&bmi, 0, sizeof(bmi)); |
|
402 bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); |
|
403 bmi.bmiHeader.biWidth = w; |
|
404 bmi.bmiHeader.biHeight = -h; |
|
405 bmi.bmiHeader.biPlanes = 1; |
|
406 bmi.bmiHeader.biBitCount = 32; |
|
407 bmi.bmiHeader.biCompression = BI_RGB; |
|
408 |
|
409 // Create the pixmap |
|
410 bufferPixels = 0; |
|
411 bufferBitmap = CreateDIBSection(bufferDC, &bmi, DIB_RGB_COLORS, (void **) &bufferPixels, 0, 0); |
|
412 GdiFlush(); |
|
413 nullBitmap = (HBITMAP)SelectObject(bufferDC, bufferBitmap); |
|
414 |
|
415 if (!bufferBitmap) { |
|
416 qErrnoWarning("QWindowsXPStylePrivate::buffer(w,h), failed to create dibsection"); |
|
417 bufferW = 0; |
|
418 bufferH = 0; |
|
419 return 0; |
|
420 } |
|
421 if (!bufferPixels) { |
|
422 qErrnoWarning("QWindowsXPStylePrivate::buffer(w,h), did not allocate pixel data"); |
|
423 bufferW = 0; |
|
424 bufferH = 0; |
|
425 return 0; |
|
426 } |
|
427 bufferW = w; |
|
428 bufferH = h; |
|
429 #ifdef DEBUG_XP_STYLE |
|
430 qDebug("Creating new dib section (%d, %d)", w, h); |
|
431 #endif |
|
432 return bufferBitmap; |
|
433 } |
|
434 |
|
435 /*! \internal |
|
436 Returns true if the part contains any transparency at all. This does |
|
437 not indicate what kind of transparency we're dealing with. It can be |
|
438 - Alpha transparency |
|
439 - Masked transparency |
|
440 */ |
|
441 bool QWindowsXPStylePrivate::isTransparent(XPThemeData &themeData) |
|
442 { |
|
443 return pIsThemeBackgroundPartiallyTransparent(themeData.handle(), themeData.partId, |
|
444 themeData.stateId); |
|
445 } |
|
446 |
|
447 |
|
448 /*! \internal |
|
449 Returns a QRegion of the region of the part |
|
450 */ |
|
451 QRegion QWindowsXPStylePrivate::region(XPThemeData &themeData) |
|
452 { |
|
453 HRGN hRgn = 0; |
|
454 RECT rect = themeData.toRECT(themeData.rect); |
|
455 if (!SUCCEEDED(pGetThemeBackgroundRegion(themeData.handle(), bufferHDC(), themeData.partId, |
|
456 themeData.stateId, &rect, &hRgn))) |
|
457 return QRegion(); |
|
458 |
|
459 HRGN dest = CreateRectRgn(0, 0, 0, 0); |
|
460 const bool success = CombineRgn(dest, hRgn, 0, RGN_COPY) != ERROR; |
|
461 |
|
462 QRegion region; |
|
463 |
|
464 if (success) |
|
465 region = qt_region_from_HRGN(dest); |
|
466 |
|
467 DeleteObject(hRgn); |
|
468 DeleteObject(dest); |
|
469 |
|
470 return region; |
|
471 } |
|
472 |
|
473 /*! \internal |
|
474 Sets the parts region on a window. |
|
475 */ |
|
476 void QWindowsXPStylePrivate::setTransparency(QWidget *widget, XPThemeData &themeData) |
|
477 { |
|
478 HRGN hrgn = themeData.mask(); |
|
479 if (hrgn && widget) |
|
480 SetWindowRgn(winId(widget), hrgn, true); |
|
481 } |
|
482 |
|
483 /*! \internal |
|
484 Returns true if the native doublebuffer contains a pixel which |
|
485 has a non-0xFF alpha value. Should only be use when its |
|
486 guaranteed that data painted into the buffer wasn't a proper |
|
487 alpha pixmap. |
|
488 */ |
|
489 bool QWindowsXPStylePrivate::hasAnyData(const QRect &rect) |
|
490 { |
|
491 const int startX = rect.left(); |
|
492 const int startY = rect.top(); |
|
493 const int w = rect.width(); |
|
494 const int h = rect.height(); |
|
495 |
|
496 for (int y = startY; y < h; ++y) { |
|
497 register DWORD *buffer = (DWORD*)bufferPixels + (y * bufferW); |
|
498 for (int x = startX; x < w; ++x, ++buffer) { |
|
499 int alpha = (*buffer) >> 24; |
|
500 if (alpha != 0xFF) // buffer has been touched |
|
501 return true; |
|
502 } |
|
503 } |
|
504 return false; |
|
505 } |
|
506 |
|
507 /*! \internal |
|
508 Returns true if the native doublebuffer contains pixels with |
|
509 varying alpha value. |
|
510 */ |
|
511 bool QWindowsXPStylePrivate::hasAlphaChannel(const QRect &rect) |
|
512 { |
|
513 const int startX = rect.left(); |
|
514 const int startY = rect.top(); |
|
515 const int w = rect.width(); |
|
516 const int h = rect.height(); |
|
517 |
|
518 int firstAlpha = -1; |
|
519 for (int y = startY; y < h/2; ++y) { |
|
520 register DWORD *buffer = (DWORD*)bufferPixels + (y * bufferW); |
|
521 for (int x = startX; x < w; ++x, ++buffer) { |
|
522 int alpha = (*buffer) >> 24; |
|
523 if (firstAlpha == -1) |
|
524 firstAlpha = alpha; |
|
525 else if (alpha != firstAlpha) |
|
526 return true; |
|
527 } |
|
528 } |
|
529 return false; |
|
530 } |
|
531 |
|
532 /*! \internal |
|
533 When the theme engine paints both a true alpha pixmap and a glyph |
|
534 into our buffer, the glyph might not contain a proper alpha value. |
|
535 The rule of thumb for premultiplied pixmaps is that the color |
|
536 values of a pixel can never be higher than the alpha values, so |
|
537 we use this to our advantage here, and fix all instances where |
|
538 this occures. |
|
539 */ |
|
540 bool QWindowsXPStylePrivate::fixAlphaChannel(const QRect &rect) |
|
541 { |
|
542 const int startX = rect.left(); |
|
543 const int startY = rect.top(); |
|
544 const int w = rect.width(); |
|
545 const int h = rect.height(); |
|
546 bool hasFixedAlphaValue = false; |
|
547 |
|
548 for (int y = startY; y < h; ++y) { |
|
549 register DWORD *buffer = (DWORD*)bufferPixels + (y * bufferW); |
|
550 for (register int x = startX; x < w; ++x, ++buffer) { |
|
551 uint pixel = *buffer; |
|
552 int alpha = qAlpha(pixel); |
|
553 if (qRed(pixel) > alpha || qGreen(pixel) > alpha || qBlue(pixel) > alpha) { |
|
554 *buffer |= 0xff000000; |
|
555 hasFixedAlphaValue = true; |
|
556 } |
|
557 } |
|
558 } |
|
559 return hasFixedAlphaValue; |
|
560 } |
|
561 |
|
562 /*! \internal |
|
563 Swaps the alpha values on certain pixels: |
|
564 0xFF?????? -> 0x00?????? |
|
565 0x00?????? -> 0xFF?????? |
|
566 Used to determin the mask of a non-alpha transparent pixmap in |
|
567 the native doublebuffer, and swap the alphas so we may paint |
|
568 the image as a Premultiplied QImage with drawImage(), and obtain |
|
569 the mask transparency. |
|
570 */ |
|
571 bool QWindowsXPStylePrivate::swapAlphaChannel(const QRect &rect, bool allPixels) |
|
572 { |
|
573 const int startX = rect.left(); |
|
574 const int startY = rect.top(); |
|
575 const int w = rect.width(); |
|
576 const int h = rect.height(); |
|
577 bool valueChange = false; |
|
578 |
|
579 // Flip the alphas, so that 255-alpha pixels are 0, and 0-alpha are 255. |
|
580 for (int y = startY; y < h; ++y) { |
|
581 register DWORD *buffer = (DWORD*)bufferPixels + (y * bufferW); |
|
582 for (register int x = startX; x < w; ++x, ++buffer) { |
|
583 if (allPixels) { |
|
584 *buffer |= 0xFF000000; |
|
585 continue; |
|
586 } |
|
587 register unsigned int alphaValue = (*buffer) & 0xFF000000; |
|
588 if (alphaValue == 0xFF000000) { |
|
589 *buffer = 0; |
|
590 valueChange = true; |
|
591 } else if (alphaValue == 0) { |
|
592 *buffer |= 0xFF000000; |
|
593 valueChange = true; |
|
594 } |
|
595 } |
|
596 } |
|
597 return valueChange; |
|
598 } |
|
599 |
|
600 /*! \internal |
|
601 Main theme drawing function. |
|
602 Determines the correct lowlevel drawing method depending on several |
|
603 factors. |
|
604 Use drawBackgroundThruNativeBuffer() if: |
|
605 - Painter does not have an HDC |
|
606 - Theme part is flipped (mirrored horizontally) |
|
607 else use drawBackgroundDirectly(). |
|
608 */ |
|
609 void QWindowsXPStylePrivate::drawBackground(XPThemeData &themeData) |
|
610 { |
|
611 if (themeData.rect.isEmpty()) |
|
612 return; |
|
613 |
|
614 QPainter *painter = themeData.painter; |
|
615 Q_ASSERT_X(painter != 0, "QWindowsXPStylePrivate::drawBackground()", "Trying to draw a theme part without a painter"); |
|
616 if (!painter || !painter->isActive()) |
|
617 return; |
|
618 |
|
619 painter->save(); |
|
620 |
|
621 QMatrix m = painter->matrix(); |
|
622 bool complexXForm = m.m11() != 1.0 || m.m22() != 1.0 || m.m12() != 0.0 || m.m21() != 0.0; |
|
623 |
|
624 bool translucentToplevel = false; |
|
625 QPaintDevice *pdev = painter->device(); |
|
626 if (pdev->devType() == QInternal::Widget) { |
|
627 QWidget *win = ((QWidget *) pdev)->window(); |
|
628 translucentToplevel = win->testAttribute(Qt::WA_TranslucentBackground); |
|
629 } |
|
630 |
|
631 bool useFallback = painter->paintEngine()->getDC() == 0 |
|
632 || painter->opacity() != 1.0 |
|
633 || themeData.rotate |
|
634 || complexXForm |
|
635 || themeData.mirrorVertically |
|
636 || (themeData.mirrorHorizontally && pDrawThemeBackgroundEx == 0) |
|
637 || translucentToplevel; |
|
638 |
|
639 if (!useFallback) |
|
640 drawBackgroundDirectly(themeData); |
|
641 else |
|
642 drawBackgroundThruNativeBuffer(themeData); |
|
643 |
|
644 painter->restore(); |
|
645 } |
|
646 |
|
647 /*! \internal |
|
648 This function draws the theme parts directly to the paintengines HDC. |
|
649 Do not use this if you need to perform other transformations on the |
|
650 resulting data. |
|
651 */ |
|
652 void QWindowsXPStylePrivate::drawBackgroundDirectly(XPThemeData &themeData) |
|
653 { |
|
654 QPainter *painter = themeData.painter; |
|
655 HDC dc = painter->paintEngine()->getDC(); |
|
656 |
|
657 QPoint redirectionDelta(int(painter->deviceMatrix().dx()), |
|
658 int(painter->deviceMatrix().dy())); |
|
659 QRect area = themeData.rect.translated(redirectionDelta); |
|
660 |
|
661 QRegion sysRgn = painter->paintEngine()->systemClip(); |
|
662 if (sysRgn.isEmpty()) |
|
663 sysRgn = area; |
|
664 else |
|
665 sysRgn &= area; |
|
666 if (painter->hasClipping()) |
|
667 sysRgn &= painter->clipRegion().translated(redirectionDelta); |
|
668 SelectClipRgn(dc, sysRgn.handle()); |
|
669 |
|
670 #ifdef DEBUG_XP_STYLE |
|
671 printf("---[ DIRECT PAINTING ]------------------> Name(%-10s) Part(%d) State(%d)\n", |
|
672 qPrintable(themeData.name), themeData.partId, themeData.stateId); |
|
673 showProperties(themeData); |
|
674 #endif |
|
675 |
|
676 RECT drawRECT = themeData.toRECT(area); |
|
677 DTBGOPTS drawOptions; |
|
678 drawOptions.dwSize = sizeof(drawOptions); |
|
679 drawOptions.rcClip = themeData.toRECT(sysRgn.boundingRect()); |
|
680 drawOptions.dwFlags = DTBG_CLIPRECT |
|
681 | (themeData.noBorder ? DTBG_OMITBORDER : 0) |
|
682 | (themeData.noContent ? DTBG_OMITCONTENT : 0) |
|
683 | (themeData.mirrorHorizontally ? DTBG_MIRRORDC : 0); |
|
684 |
|
685 if (pDrawThemeBackgroundEx != 0) { |
|
686 pDrawThemeBackgroundEx(themeData.handle(), dc, themeData.partId, themeData.stateId, &(drawRECT), &drawOptions); |
|
687 } else { |
|
688 // We are running on a system where the uxtheme.dll does not have |
|
689 // the DrawThemeBackgroundEx function, so we need to clip away |
|
690 // borders or contents manually. All flips and mirrors uses the |
|
691 // fallback implementation |
|
692 |
|
693 int borderSize = 0; |
|
694 PROPERTYORIGIN origin = PO_NOTFOUND; |
|
695 pGetThemePropertyOrigin(themeData.handle(), themeData.partId, themeData.stateId, TMT_BORDERSIZE, &origin); |
|
696 pGetThemeInt(themeData.handle(), themeData.partId, themeData.stateId, TMT_BORDERSIZE, &borderSize); |
|
697 |
|
698 // Clip away border region |
|
699 QRegion extraClip = sysRgn; |
|
700 if ((origin == PO_CLASS || origin == PO_PART || origin == PO_STATE) && borderSize > 0) { |
|
701 if (themeData.noBorder) { |
|
702 // extraClip &= area is already done |
|
703 drawRECT = themeData.toRECT(area.adjusted(-borderSize, -borderSize, borderSize, borderSize)); |
|
704 } |
|
705 |
|
706 // Clip away content region |
|
707 if (themeData.noContent) { |
|
708 QRegion content = area.adjusted(borderSize, borderSize, -borderSize, -borderSize); |
|
709 extraClip ^= content; |
|
710 } |
|
711 |
|
712 // Set the clip region, if used.. |
|
713 if (themeData.noBorder || themeData.noContent) |
|
714 SelectClipRgn(dc, extraClip.handle()); |
|
715 } |
|
716 |
|
717 pDrawThemeBackground(themeData.handle(), dc, themeData.partId, themeData.stateId, &(drawRECT), &(drawOptions.rcClip)); |
|
718 } |
|
719 SelectClipRgn(dc, 0); |
|
720 } |
|
721 |
|
722 /*! \internal |
|
723 This function uses a secondary Native doublebuffer for painting parts. |
|
724 It should only be used when the painteengine doesn't provide a proper |
|
725 HDC for direct painting (e.g. when doing a grabWidget(), painting to |
|
726 other pixmaps etc), or when special transformations are needed (e.g. |
|
727 flips (horizonal mirroring only, vertical are handled by the theme |
|
728 engine). |
|
729 */ |
|
730 void QWindowsXPStylePrivate::drawBackgroundThruNativeBuffer(XPThemeData &themeData) |
|
731 { |
|
732 QPainter *painter = themeData.painter; |
|
733 QRect rect = themeData.rect; |
|
734 |
|
735 if ((themeData.rotate + 90) % 180 == 0) { // Catch 90,270,etc.. degree flips. |
|
736 rect = QRect(0, 0, rect.height(), rect.width()); |
|
737 } |
|
738 rect.moveTo(0,0); |
|
739 int partId = themeData.partId; |
|
740 int stateId = themeData.stateId; |
|
741 int w = rect.width(); |
|
742 int h = rect.height(); |
|
743 |
|
744 // Values initialized later, either from cached values, or from function calls |
|
745 AlphaChannelType alphaType = UnknownAlpha; |
|
746 bool stateHasData = true; // We assume so; |
|
747 bool hasAlpha = false; |
|
748 bool partIsTransparent; |
|
749 bool inspectData; |
|
750 bool potentialInvalidAlpha; |
|
751 |
|
752 QString pixmapCacheKey = QString::fromLatin1("$qt_xp_%1p%2s%3s%4b%5c%6w%7h").arg(themeData.name) |
|
753 .arg(partId).arg(stateId).arg(!themeData.noBorder).arg(!themeData.noContent) |
|
754 .arg(w).arg(h); |
|
755 QPixmap cachedPixmap; |
|
756 ThemeMapKey key(themeData); |
|
757 ThemeMapData data = alphaCache.value(key); |
|
758 |
|
759 bool haveCachedPixmap = false; |
|
760 bool isCached = data.dataValid; |
|
761 if (isCached) { |
|
762 if (!(stateHasData = data.hasAnyData)) |
|
763 return; // Cached NOOP |
|
764 inspectData = data.wasAlphaSwapped; |
|
765 partIsTransparent = data.partIsTransparent; |
|
766 hasAlpha = data.hasAlphaChannel; |
|
767 alphaType = data.alphaType; |
|
768 potentialInvalidAlpha = data.hadInvalidAlpha; |
|
769 |
|
770 haveCachedPixmap = QPixmapCache::find(pixmapCacheKey, cachedPixmap); |
|
771 |
|
772 #ifdef DEBUG_XP_STYLE |
|
773 char buf[25]; |
|
774 ::sprintf(buf, "+ Pixmap(%3d, %3d) ]", w, h); |
|
775 printf("---[ CACHED %s--------> Name(%-10s) Part(%d) State(%d)\n", |
|
776 haveCachedPixmap ? buf : "]-------------------", |
|
777 qPrintable(themeData.name), themeData.partId, themeData.stateId); |
|
778 #endif |
|
779 } else { |
|
780 // Not cached, so get values from Theme Engine |
|
781 BOOL tmt_borderonly = false; |
|
782 COLORREF tmt_transparentcolor = 0x0; |
|
783 PROPERTYORIGIN proporigin = PO_NOTFOUND; |
|
784 pGetThemeBool(themeData.handle(), themeData.partId, themeData.stateId, TMT_BORDERONLY, &tmt_borderonly); |
|
785 pGetThemeColor(themeData.handle(), themeData.partId, themeData.stateId, TMT_TRANSPARENTCOLOR, &tmt_transparentcolor); |
|
786 pGetThemePropertyOrigin(themeData.handle(), themeData.partId, themeData.stateId, TMT_CAPTIONMARGINS, &proporigin); |
|
787 inspectData = (tmt_transparentcolor != 0 || tmt_borderonly || proporigin == PO_PART || proporigin == PO_STATE); |
|
788 |
|
789 // ### This is a vista-specific workaround for broken alpha in titlebar pixmaps |
|
790 if ((QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based)) { |
|
791 if (themeData.partId == WP_CAPTION || themeData.partId == WP_SMALLCAPTION) |
|
792 inspectData = false; |
|
793 } |
|
794 |
|
795 partIsTransparent = isTransparent(themeData); |
|
796 |
|
797 potentialInvalidAlpha = false; |
|
798 pGetThemePropertyOrigin(themeData.handle(), themeData.partId, themeData.stateId, TMT_GLYPHTYPE, &proporigin); |
|
799 if (proporigin == PO_PART || proporigin == PO_STATE) { |
|
800 int tmt_glyphtype = GT_NONE; |
|
801 pGetThemeEnumValue(themeData.handle(), themeData.partId, themeData.stateId, TMT_GLYPHTYPE, &tmt_glyphtype); |
|
802 potentialInvalidAlpha = partIsTransparent && !inspectData && tmt_glyphtype == GT_IMAGEGLYPH; |
|
803 } |
|
804 |
|
805 #ifdef DEBUG_XP_STYLE |
|
806 printf("---[ NOT CACHED ]-----------------------> Name(%-10s) Part(%d) State(%d)\n", |
|
807 qPrintable(themeData.name), themeData.partId, themeData.stateId); |
|
808 printf("-->partIsTransparen = %d\n", partIsTransparent); |
|
809 printf("-->inspectData = %d\n", inspectData); |
|
810 printf("-->potentialInvalidAlpha = %d\n", potentialInvalidAlpha); |
|
811 showProperties(themeData); |
|
812 #endif |
|
813 } |
|
814 bool wasAlphaSwapped = false; |
|
815 bool wasAlphaFixed = false; |
|
816 |
|
817 // OLD PSDK Workaround ------------------------------------------------------------------------ |
|
818 // See if we need extra clipping for the older PSDK, which does |
|
819 // not have a DrawThemeBackgroundEx function for DTGB_OMITBORDER |
|
820 // and DTGB_OMITCONTENT |
|
821 bool addBorderContentClipping = false; |
|
822 QRegion extraClip; |
|
823 QRect area = rect; |
|
824 if (themeData.noBorder || themeData.noContent) { |
|
825 extraClip = area; |
|
826 // We are running on a system where the uxtheme.dll does not have |
|
827 // the DrawThemeBackgroundEx function, so we need to clip away |
|
828 // borders or contents manually. |
|
829 |
|
830 int borderSize = 0; |
|
831 PROPERTYORIGIN origin = PO_NOTFOUND; |
|
832 pGetThemePropertyOrigin(themeData.handle(), themeData.partId, themeData.stateId, TMT_BORDERSIZE, &origin); |
|
833 pGetThemeInt(themeData.handle(), themeData.partId, themeData.stateId, TMT_BORDERSIZE, &borderSize); |
|
834 |
|
835 // Clip away border region |
|
836 if ((origin == PO_CLASS || origin == PO_PART || origin == PO_STATE) && borderSize > 0) { |
|
837 if (themeData.noBorder) { |
|
838 extraClip &= area; |
|
839 area = area.adjusted(-borderSize, -borderSize, borderSize, borderSize); |
|
840 } |
|
841 |
|
842 // Clip away content region |
|
843 if (themeData.noContent) { |
|
844 QRegion content = area.adjusted(borderSize, borderSize, -borderSize, -borderSize); |
|
845 extraClip ^= content; |
|
846 } |
|
847 } |
|
848 addBorderContentClipping = (themeData.noBorder | themeData.noContent); |
|
849 } |
|
850 |
|
851 QImage img; |
|
852 if (!haveCachedPixmap) { // If the pixmap is not cached, generate it! ------------------------- |
|
853 buffer(w, h); // Ensure a buffer of at least (w, h) in size |
|
854 HDC dc = bufferHDC(); |
|
855 |
|
856 // Clear the buffer |
|
857 if (alphaType != NoAlpha) { |
|
858 // Consider have separate "memset" function for small chunks for more speedup |
|
859 memset(bufferPixels, inspectData ? 0xFF : 0x00, bufferW * h * 4); |
|
860 } |
|
861 |
|
862 // Difference between area and rect |
|
863 int dx = area.x() - rect.x(); |
|
864 int dy = area.y() - rect.y(); |
|
865 int dr = area.right() - rect.right(); |
|
866 int db = area.bottom() - rect.bottom(); |
|
867 |
|
868 // Adjust so painting rect starts from Origo |
|
869 rect.moveTo(0,0); |
|
870 area.moveTo(dx,dy); |
|
871 DTBGOPTS drawOptions; |
|
872 drawOptions.dwSize = sizeof(drawOptions); |
|
873 drawOptions.rcClip = themeData.toRECT(rect); |
|
874 drawOptions.dwFlags = DTBG_CLIPRECT |
|
875 | (themeData.noBorder ? DTBG_OMITBORDER : 0) |
|
876 | (themeData.noContent ? DTBG_OMITCONTENT : 0); |
|
877 |
|
878 // Drawing the part into the backing store |
|
879 if (pDrawThemeBackgroundEx != 0) { |
|
880 RECT rect(themeData.toRECT(area)); |
|
881 pDrawThemeBackgroundEx(themeData.handle(), dc, themeData.partId, themeData.stateId, &rect, &drawOptions); |
|
882 } else { |
|
883 // Set the clip region, if used.. |
|
884 if (addBorderContentClipping) { |
|
885 SelectClipRgn(dc, extraClip.handle()); |
|
886 // Compensate for the noBorder area difference (noContent has the same area) |
|
887 drawOptions.rcClip = themeData.toRECT(rect.adjusted(dx, dy, dr, db)); |
|
888 } |
|
889 |
|
890 pDrawThemeBackground(themeData.handle(), dc, themeData.partId, themeData.stateId, &(drawOptions.rcClip), 0); |
|
891 |
|
892 if (addBorderContentClipping) |
|
893 SelectClipRgn(dc, 0); |
|
894 } |
|
895 |
|
896 // If not cached, analyze the buffer data to figure |
|
897 // out alpha type, and if it contains data |
|
898 if (!isCached) { |
|
899 if (inspectData) |
|
900 stateHasData = hasAnyData(rect); |
|
901 // SHORTCUT: If the part's state has no data, cache it for NOOP later |
|
902 if (!stateHasData) { |
|
903 memset(&data, 0, sizeof(data)); |
|
904 data.dataValid = true; |
|
905 alphaCache.insert(key, data); |
|
906 return; |
|
907 } |
|
908 hasAlpha = hasAlphaChannel(rect); |
|
909 if (!hasAlpha && partIsTransparent) |
|
910 potentialInvalidAlpha = true; |
|
911 #if defined(DEBUG_XP_STYLE) && 1 |
|
912 dumpNativeDIB(w, h); |
|
913 #endif |
|
914 } |
|
915 |
|
916 // Swap alpha values, if needed |
|
917 if (inspectData) |
|
918 wasAlphaSwapped = swapAlphaChannel(rect); |
|
919 |
|
920 // Fix alpha values, if needed |
|
921 if (potentialInvalidAlpha) |
|
922 wasAlphaFixed = fixAlphaChannel(rect); |
|
923 |
|
924 QImage::Format format; |
|
925 if ((partIsTransparent && !wasAlphaSwapped) || (!partIsTransparent && hasAlpha)) { |
|
926 format = QImage::Format_ARGB32_Premultiplied; |
|
927 alphaType = RealAlpha; |
|
928 } else if (wasAlphaSwapped) { |
|
929 format = QImage::Format_ARGB32_Premultiplied; |
|
930 alphaType = MaskAlpha; |
|
931 } else { |
|
932 format = QImage::Format_RGB32; |
|
933 // The image data we got from the theme engine does not have any transparency, |
|
934 // thus the alpha channel is set to 0. |
|
935 // However, Format_RGB32 requires the alpha part to be set to 0xff, thus |
|
936 // we must flip it from 0x00 to 0xff |
|
937 swapAlphaChannel(rect, true); |
|
938 alphaType = NoAlpha; |
|
939 } |
|
940 #if defined(DEBUG_XP_STYLE) && 1 |
|
941 printf("Image format is: %s\n", alphaType == RealAlpha ? "Real Alpha" : alphaType == MaskAlpha ? "Masked Alpha" : "No Alpha"); |
|
942 #endif |
|
943 img = QImage(bufferPixels, bufferW, bufferH, format); |
|
944 } |
|
945 |
|
946 // Blitting backing store |
|
947 bool useRegion = partIsTransparent && !hasAlpha && !wasAlphaSwapped; |
|
948 |
|
949 QRegion newRegion; |
|
950 QRegion oldRegion; |
|
951 if (useRegion) { |
|
952 newRegion = region(themeData); |
|
953 oldRegion = painter->clipRegion(); |
|
954 painter->setClipRegion(newRegion); |
|
955 #if defined(DEBUG_XP_STYLE) && 0 |
|
956 printf("Using region:\n"); |
|
957 QVector<QRect> rects = newRegion.rects(); |
|
958 for (int i = 0; i < rects.count(); ++i) { |
|
959 const QRect &r = rects.at(i); |
|
960 printf(" (%d, %d, %d, %d)\n", r.x(), r.y(), r.right(), r.bottom()); |
|
961 } |
|
962 #endif |
|
963 } |
|
964 |
|
965 if (addBorderContentClipping) |
|
966 painter->setClipRegion(extraClip, Qt::IntersectClip); |
|
967 |
|
968 if (!themeData.mirrorHorizontally && !themeData.mirrorVertically && !themeData.rotate) { |
|
969 if (!haveCachedPixmap) |
|
970 painter->drawImage(themeData.rect, img, rect); |
|
971 else |
|
972 painter->drawPixmap(themeData.rect, cachedPixmap); |
|
973 } else { |
|
974 // This is _slow_! |
|
975 // Make a copy containing only the necessary data, and mirror |
|
976 // on all wanted axes. Then draw the copy. |
|
977 // If cached, the normal pixmap is cached, instead of caching |
|
978 // all possible orientations for each part and state. |
|
979 QImage imgCopy; |
|
980 if (!haveCachedPixmap) |
|
981 imgCopy = img.copy(rect); |
|
982 else |
|
983 imgCopy = cachedPixmap.toImage(); |
|
984 |
|
985 if (themeData.rotate) { |
|
986 QMatrix rotMatrix; |
|
987 rotMatrix.rotate(themeData.rotate); |
|
988 imgCopy = imgCopy.transformed(rotMatrix); |
|
989 } |
|
990 if (themeData.mirrorHorizontally || themeData.mirrorVertically) { |
|
991 imgCopy = imgCopy.mirrored(themeData.mirrorHorizontally, themeData.mirrorVertically); |
|
992 } |
|
993 painter->drawImage(themeData.rect, |
|
994 imgCopy); |
|
995 } |
|
996 |
|
997 if (useRegion || addBorderContentClipping) { |
|
998 if (oldRegion.isEmpty()) |
|
999 painter->setClipping(false); |
|
1000 else |
|
1001 painter->setClipRegion(oldRegion); |
|
1002 } |
|
1003 |
|
1004 // Cache the pixmap to avoid expensive swapAlphaChannel() calls |
|
1005 if (!haveCachedPixmap && w && h) { |
|
1006 QPixmap pix = QPixmap::fromImage(img).copy(rect); |
|
1007 QPixmapCache::insert(pixmapCacheKey, pix); |
|
1008 #ifdef DEBUG_XP_STYLE |
|
1009 printf("+++Adding pixmap to cache, size(%d, %d), wasAlphaSwapped(%d), wasAlphaFixed(%d), name(%s)\n", |
|
1010 w, h, wasAlphaSwapped, wasAlphaFixed, qPrintable(pixmapCacheKey)); |
|
1011 #endif |
|
1012 } |
|
1013 |
|
1014 // Add to theme part cache |
|
1015 if (!isCached) { |
|
1016 memset(&data, 0, sizeof(data)); |
|
1017 data.dataValid = true; |
|
1018 data.partIsTransparent = partIsTransparent; |
|
1019 data.alphaType = alphaType; |
|
1020 data.hasAlphaChannel = hasAlpha; |
|
1021 data.hasAnyData = stateHasData; |
|
1022 data.wasAlphaSwapped = wasAlphaSwapped; |
|
1023 data.hadInvalidAlpha = wasAlphaFixed; |
|
1024 alphaCache.insert(key, data); |
|
1025 } |
|
1026 } |
|
1027 |
|
1028 |
|
1029 // ------------------------------------------------------------------------------------------------ |
|
1030 |
|
1031 /*! |
|
1032 \class QWindowsXPStyle |
|
1033 \brief The QWindowsXPStyle class provides a Microsoft Windows XP-like look and feel. |
|
1034 |
|
1035 \ingroup appearance |
|
1036 |
|
1037 \warning This style is only available on the Windows XP platform |
|
1038 because it makes use of Windows XP's style engine. |
|
1039 |
|
1040 Most of the functions are documented in the base classes |
|
1041 QWindowsStyle, QCommonStyle, and QStyle, but the |
|
1042 QWindowsXPStyle overloads of drawComplexControl(), drawControl(), |
|
1043 drawControlMask(), drawPrimitive(), proxy()->subControlRect(), and |
|
1044 sizeFromContents(), are documented here. |
|
1045 |
|
1046 \img qwindowsxpstyle.png |
|
1047 \sa QMacStyle, QWindowsStyle, QPlastiqueStyle, QCDEStyle, QMotifStyle |
|
1048 */ |
|
1049 |
|
1050 /*! |
|
1051 Constructs a QWindowsStyle |
|
1052 */ |
|
1053 QWindowsXPStyle::QWindowsXPStyle() |
|
1054 : QWindowsStyle(*new QWindowsXPStylePrivate) |
|
1055 { |
|
1056 } |
|
1057 |
|
1058 /*! |
|
1059 Destroys the style. |
|
1060 */ |
|
1061 QWindowsXPStyle::~QWindowsXPStyle() |
|
1062 { |
|
1063 } |
|
1064 |
|
1065 /*! \reimp */ |
|
1066 void QWindowsXPStyle::unpolish(QApplication *app) |
|
1067 { |
|
1068 QWindowsStyle::unpolish(app); |
|
1069 } |
|
1070 |
|
1071 /*! \reimp */ |
|
1072 void QWindowsXPStyle::polish(QApplication *app) |
|
1073 { |
|
1074 QWindowsStyle::polish(app); |
|
1075 if (!QWindowsXPStylePrivate::useXP()) |
|
1076 return; |
|
1077 } |
|
1078 |
|
1079 /*! \reimp */ |
|
1080 void QWindowsXPStyle::polish(QWidget *widget) |
|
1081 { |
|
1082 QWindowsStyle::polish(widget); |
|
1083 if (!QWindowsXPStylePrivate::useXP()) |
|
1084 return; |
|
1085 |
|
1086 if (qobject_cast<QAbstractButton*>(widget) |
|
1087 || qobject_cast<QToolButton*>(widget) |
|
1088 || qobject_cast<QTabBar*>(widget) |
|
1089 #ifndef QT_NO_COMBOBOX |
|
1090 || qobject_cast<QComboBox*>(widget) |
|
1091 #endif // QT_NO_COMBOBOX |
|
1092 || qobject_cast<QScrollBar*>(widget) |
|
1093 || qobject_cast<QSlider*>(widget) |
|
1094 || qobject_cast<QHeaderView*>(widget) |
|
1095 #ifndef QT_NO_SPINBOX |
|
1096 || qobject_cast<QAbstractSpinBox*>(widget) |
|
1097 || qobject_cast<QSpinBox*>(widget) |
|
1098 #endif // QT_NO_SPINBOX |
|
1099 || widget->inherits("QWorkspaceChild") |
|
1100 || widget->inherits("Q3TitleBar")) |
|
1101 widget->setAttribute(Qt::WA_Hover); |
|
1102 |
|
1103 #ifndef QT_NO_RUBBERBAND |
|
1104 if (qobject_cast<QRubberBand*>(widget)) { |
|
1105 widget->setWindowOpacity(0.6); |
|
1106 } |
|
1107 #endif |
|
1108 if (qobject_cast<QStackedWidget*>(widget) && |
|
1109 qobject_cast<QTabWidget*>(widget->parent())) |
|
1110 widget->parentWidget()->setAttribute(Qt::WA_ContentsPropagated); |
|
1111 |
|
1112 Q_D(QWindowsXPStyle); |
|
1113 if (!d->hasInitColors) { |
|
1114 // Get text color for group box labels |
|
1115 COLORREF cref; |
|
1116 XPThemeData theme(0, 0, QLatin1String("BUTTON"), 0, 0); |
|
1117 pGetThemeColor(theme.handle(), BP_GROUPBOX, GBS_NORMAL, TMT_TEXTCOLOR, &cref); |
|
1118 d->groupBoxTextColor = qRgb(GetRValue(cref), GetGValue(cref), GetBValue(cref)); |
|
1119 pGetThemeColor(theme.handle(), BP_GROUPBOX, GBS_DISABLED, TMT_TEXTCOLOR, &cref); |
|
1120 d->groupBoxTextColorDisabled = qRgb(GetRValue(cref), GetGValue(cref), GetBValue(cref)); |
|
1121 // Where does this color come from? |
|
1122 //pGetThemeColor(theme.handle(), TKP_TICS, TSS_NORMAL, TMT_COLOR, &cref); |
|
1123 d->sliderTickColor = qRgb(165, 162, 148); |
|
1124 d->hasInitColors = true; |
|
1125 } |
|
1126 } |
|
1127 |
|
1128 /*! \reimp */ |
|
1129 void QWindowsXPStyle::polish(QPalette &pal) |
|
1130 { |
|
1131 QWindowsStyle::polish(pal); |
|
1132 pal.setBrush(QPalette::AlternateBase, pal.base().color().darker(110)); |
|
1133 } |
|
1134 |
|
1135 /*! \reimp */ |
|
1136 void QWindowsXPStyle::unpolish(QWidget *widget) |
|
1137 { |
|
1138 #ifndef QT_NO_RUBBERBAND |
|
1139 if (qobject_cast<QRubberBand*>(widget)) { |
|
1140 widget->setWindowOpacity(1.0); |
|
1141 } |
|
1142 #endif |
|
1143 Q_D(QWindowsXPStyle); |
|
1144 // Unpolish of widgets is the first thing that |
|
1145 // happens when a theme changes, or the theme |
|
1146 // engine is turned off. So we detect it here. |
|
1147 bool oldState = QWindowsXPStylePrivate::useXP(); |
|
1148 bool newState = QWindowsXPStylePrivate::useXP(true); |
|
1149 if ((oldState != newState) && newState) { |
|
1150 d->cleanup(true); |
|
1151 d->init(true); |
|
1152 } else { |
|
1153 // Cleanup handle map, if just changing style, |
|
1154 // or turning it on. In both cases the values |
|
1155 // already in the map might be old (other style). |
|
1156 d->cleanupHandleMap(); |
|
1157 } |
|
1158 if (qobject_cast<QAbstractButton*>(widget) |
|
1159 || qobject_cast<QToolButton*>(widget) |
|
1160 || qobject_cast<QTabBar*>(widget) |
|
1161 #ifndef QT_NO_COMBOBOX |
|
1162 || qobject_cast<QComboBox*>(widget) |
|
1163 #endif // QT_NO_COMBOBOX |
|
1164 || qobject_cast<QScrollBar*>(widget) |
|
1165 || qobject_cast<QSlider*>(widget) |
|
1166 || qobject_cast<QHeaderView*>(widget) |
|
1167 #ifndef QT_NO_SPINBOX |
|
1168 || qobject_cast<QAbstractSpinBox*>(widget) |
|
1169 || qobject_cast<QSpinBox*>(widget) |
|
1170 #endif // QT_NO_SPINBOX |
|
1171 || widget->inherits("QWorkspaceChild") |
|
1172 || widget->inherits("Q3TitleBar")) |
|
1173 widget->setAttribute(Qt::WA_Hover, false); |
|
1174 QWindowsStyle::unpolish(widget); |
|
1175 } |
|
1176 |
|
1177 /*! \reimp */ |
|
1178 QRect QWindowsXPStyle::subElementRect(SubElement sr, const QStyleOption *option, const QWidget *widget) const |
|
1179 { |
|
1180 if (!QWindowsXPStylePrivate::useXP()) { |
|
1181 return QWindowsStyle::subElementRect(sr, option, widget); |
|
1182 } |
|
1183 |
|
1184 QRect rect(option->rect); |
|
1185 switch(sr) { |
|
1186 case SE_DockWidgetCloseButton: |
|
1187 case SE_DockWidgetFloatButton: |
|
1188 rect = QWindowsStyle::subElementRect(sr, option, widget); |
|
1189 return rect.translated(0, 1); |
|
1190 break; |
|
1191 case SE_TabWidgetTabContents: |
|
1192 if (qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(option)) |
|
1193 { |
|
1194 rect = QWindowsStyle::subElementRect(sr, option, widget); |
|
1195 if (sr == SE_TabWidgetTabContents) |
|
1196 rect.adjust(0, 0, -2, -2); |
|
1197 } |
|
1198 break; |
|
1199 case SE_TabWidgetTabBar: { |
|
1200 rect = QWindowsStyle::subElementRect(sr, option, widget); |
|
1201 const QStyleOptionTabWidgetFrame *twfOption = |
|
1202 qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(option); |
|
1203 if (twfOption && twfOption->direction == Qt::RightToLeft |
|
1204 && (twfOption->shape == QTabBar::RoundedNorth |
|
1205 || twfOption->shape == QTabBar::RoundedSouth)) |
|
1206 { |
|
1207 QStyleOptionTab otherOption; |
|
1208 otherOption.shape = (twfOption->shape == QTabBar::RoundedNorth |
|
1209 ? QTabBar::RoundedEast : QTabBar::RoundedSouth); |
|
1210 int overlap = proxy()->pixelMetric(PM_TabBarBaseOverlap, &otherOption, widget); |
|
1211 int borderThickness = proxy()->pixelMetric(PM_DefaultFrameWidth, option, widget); |
|
1212 rect.adjust(-overlap + borderThickness, 0, -overlap + borderThickness, 0); |
|
1213 } |
|
1214 break;} |
|
1215 |
|
1216 case SE_PushButtonContents: |
|
1217 if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) { |
|
1218 MARGINS borderSize; |
|
1219 if (widget) { |
|
1220 XPThemeData buttontheme(widget, 0, QLatin1String("Button")); |
|
1221 HTHEME theme = buttontheme.handle(); |
|
1222 if (theme) { |
|
1223 int stateId; |
|
1224 if (!(option->state & State_Enabled)) |
|
1225 stateId = PBS_DISABLED; |
|
1226 else if (option->state & State_Sunken) |
|
1227 stateId = PBS_PRESSED; |
|
1228 else if (option->state & State_MouseOver) |
|
1229 stateId = PBS_HOT; |
|
1230 else if (btn->features & QStyleOptionButton::DefaultButton) |
|
1231 stateId = PBS_DEFAULTED; |
|
1232 else |
|
1233 stateId = PBS_NORMAL; |
|
1234 |
|
1235 int border = proxy()->pixelMetric(PM_DefaultFrameWidth, btn, widget); |
|
1236 rect = option->rect.adjusted(border, border, -border, -border); |
|
1237 |
|
1238 int result = pGetThemeMargins(theme, |
|
1239 NULL, |
|
1240 BP_PUSHBUTTON, |
|
1241 stateId, |
|
1242 TMT_CONTENTMARGINS, |
|
1243 NULL, |
|
1244 &borderSize); |
|
1245 |
|
1246 if (result == S_OK) { |
|
1247 rect.adjust(borderSize.cxLeftWidth, borderSize.cyTopHeight, |
|
1248 -borderSize.cxRightWidth, -borderSize.cyBottomHeight); |
|
1249 rect = visualRect(option->direction, option->rect, rect); |
|
1250 } |
|
1251 } |
|
1252 } |
|
1253 } |
|
1254 break; |
|
1255 case SE_ProgressBarContents: |
|
1256 rect = QCommonStyle::subElementRect(SE_ProgressBarGroove, option, widget); |
|
1257 if (option->state & QStyle::State_Horizontal) |
|
1258 rect.adjust(4, 3, -4, -3); |
|
1259 else |
|
1260 rect.adjust(3, 2, -3, -2); |
|
1261 break; |
|
1262 default: |
|
1263 rect = QWindowsStyle::subElementRect(sr, option, widget); |
|
1264 } |
|
1265 return rect; |
|
1266 } |
|
1267 |
|
1268 /*! |
|
1269 \reimp |
|
1270 */ |
|
1271 void QWindowsXPStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *option, QPainter *p, |
|
1272 const QWidget *widget) const |
|
1273 { |
|
1274 QWindowsXPStylePrivate *d = const_cast<QWindowsXPStylePrivate*>(d_func()); |
|
1275 |
|
1276 if (!QWindowsXPStylePrivate::useXP()) { |
|
1277 QWindowsStyle::drawPrimitive(pe, option, p, widget); |
|
1278 return; |
|
1279 } |
|
1280 |
|
1281 QString name; |
|
1282 int partId = 0; |
|
1283 int stateId = 0; |
|
1284 QRect rect = option->rect; |
|
1285 State flags = option->state; |
|
1286 bool hMirrored = false; |
|
1287 bool vMirrored = false; |
|
1288 bool noBorder = false; |
|
1289 bool noContent = false; |
|
1290 int rotate = 0; |
|
1291 |
|
1292 switch (pe) { |
|
1293 case PE_FrameTabBarBase: |
|
1294 if (const QStyleOptionTabBarBase *tbb |
|
1295 = qstyleoption_cast<const QStyleOptionTabBarBase *>(option)) { |
|
1296 p->save(); |
|
1297 switch (tbb->shape) { |
|
1298 case QTabBar::RoundedNorth: |
|
1299 p->setPen(QPen(tbb->palette.dark(), 0)); |
|
1300 p->drawLine(tbb->rect.topLeft(), tbb->rect.topRight()); |
|
1301 break; |
|
1302 case QTabBar::RoundedWest: |
|
1303 p->setPen(QPen(tbb->palette.dark(), 0)); |
|
1304 p->drawLine(tbb->rect.left(), tbb->rect.top(), tbb->rect.left(), tbb->rect.bottom()); |
|
1305 break; |
|
1306 case QTabBar::RoundedSouth: |
|
1307 p->setPen(QPen(tbb->palette.dark(), 0)); |
|
1308 p->drawLine(tbb->rect.left(), tbb->rect.top(), |
|
1309 tbb->rect.right(), tbb->rect.top()); |
|
1310 break; |
|
1311 case QTabBar::RoundedEast: |
|
1312 p->setPen(QPen(tbb->palette.dark(), 0)); |
|
1313 p->drawLine(tbb->rect.topLeft(), tbb->rect.bottomLeft()); |
|
1314 break; |
|
1315 case QTabBar::TriangularNorth: |
|
1316 case QTabBar::TriangularEast: |
|
1317 case QTabBar::TriangularWest: |
|
1318 case QTabBar::TriangularSouth: |
|
1319 p->restore(); |
|
1320 QWindowsStyle::drawPrimitive(pe, option, p, widget); |
|
1321 return; |
|
1322 } |
|
1323 p->restore(); |
|
1324 } |
|
1325 return; |
|
1326 case PE_PanelButtonBevel: |
|
1327 name = QLatin1String("BUTTON"); |
|
1328 partId = BP_PUSHBUTTON; |
|
1329 if (!(flags & State_Enabled)) |
|
1330 stateId = PBS_DISABLED; |
|
1331 else if ((flags & State_Sunken) || (flags & State_On)) |
|
1332 stateId = PBS_PRESSED; |
|
1333 else if (flags & State_MouseOver) |
|
1334 stateId = PBS_HOT; |
|
1335 //else if (flags & State_ButtonDefault) |
|
1336 // stateId = PBS_DEFAULTED; |
|
1337 else |
|
1338 stateId = PBS_NORMAL; |
|
1339 break; |
|
1340 |
|
1341 case PE_PanelButtonTool: |
|
1342 if (widget && widget->inherits("QDockWidgetTitleButton")) { |
|
1343 if (const QWidget *dw = widget->parentWidget()) |
|
1344 if (dw->isWindow()) |
|
1345 return; |
|
1346 } |
|
1347 name = QLatin1String("TOOLBAR"); |
|
1348 partId = TP_BUTTON; |
|
1349 if (!(flags & State_Enabled)) |
|
1350 stateId = TS_DISABLED; |
|
1351 else if (flags & State_Sunken) |
|
1352 stateId = TS_PRESSED; |
|
1353 else if (flags & State_MouseOver) |
|
1354 stateId = flags & State_On ? TS_HOTCHECKED : TS_HOT; |
|
1355 else if (flags & State_On) |
|
1356 stateId = TS_CHECKED; |
|
1357 else if (!(flags & State_AutoRaise)) |
|
1358 stateId = TS_HOT; |
|
1359 else |
|
1360 stateId = TS_NORMAL; |
|
1361 break; |
|
1362 |
|
1363 case PE_IndicatorButtonDropDown: |
|
1364 name = QLatin1String("TOOLBAR"); |
|
1365 partId = TP_SPLITBUTTONDROPDOWN; |
|
1366 if (!(flags & State_Enabled)) |
|
1367 stateId = TS_DISABLED; |
|
1368 else if (flags & State_Sunken) |
|
1369 stateId = TS_PRESSED; |
|
1370 else if (flags & State_MouseOver) |
|
1371 stateId = flags & State_On ? TS_HOTCHECKED : TS_HOT; |
|
1372 else if (flags & State_On) |
|
1373 stateId = TS_CHECKED; |
|
1374 else if (!(flags & State_AutoRaise)) |
|
1375 stateId = TS_HOT; |
|
1376 else |
|
1377 stateId = TS_NORMAL; |
|
1378 if (option->direction == Qt::RightToLeft) |
|
1379 hMirrored = true; |
|
1380 break; |
|
1381 |
|
1382 case PE_IndicatorCheckBox: |
|
1383 name = QLatin1String("BUTTON"); |
|
1384 partId = BP_CHECKBOX; |
|
1385 if (!(flags & State_Enabled)) |
|
1386 stateId = CBS_UNCHECKEDDISABLED; |
|
1387 else if (flags & State_Sunken) |
|
1388 stateId = CBS_UNCHECKEDPRESSED; |
|
1389 else if (flags & State_MouseOver) |
|
1390 stateId = CBS_UNCHECKEDHOT; |
|
1391 else |
|
1392 stateId = CBS_UNCHECKEDNORMAL; |
|
1393 |
|
1394 if (flags & State_On) |
|
1395 stateId += CBS_CHECKEDNORMAL-1; |
|
1396 else if (flags & State_NoChange) |
|
1397 stateId += CBS_MIXEDNORMAL-1; |
|
1398 |
|
1399 break; |
|
1400 |
|
1401 case PE_IndicatorRadioButton: |
|
1402 name = QLatin1String("BUTTON"); |
|
1403 partId = BP_RADIOBUTTON; |
|
1404 if (!(flags & State_Enabled)) |
|
1405 stateId = RBS_UNCHECKEDDISABLED; |
|
1406 else if (flags & State_Sunken) |
|
1407 stateId = RBS_UNCHECKEDPRESSED; |
|
1408 else if (flags & State_MouseOver) |
|
1409 stateId = RBS_UNCHECKEDHOT; |
|
1410 else |
|
1411 stateId = RBS_UNCHECKEDNORMAL; |
|
1412 |
|
1413 if (flags & State_On) |
|
1414 stateId += RBS_CHECKEDNORMAL-1; |
|
1415 break; |
|
1416 |
|
1417 case PE_IndicatorDockWidgetResizeHandle: |
|
1418 return; |
|
1419 |
|
1420 case PE_Frame: |
|
1421 { |
|
1422 if (flags & State_Raised) |
|
1423 return; |
|
1424 name = QLatin1String("LISTVIEW"); |
|
1425 partId = LVP_LISTGROUP; |
|
1426 XPThemeData theme(0, 0, name, partId, 0); |
|
1427 |
|
1428 if (!(flags & State_Enabled)) |
|
1429 stateId = ETS_DISABLED; |
|
1430 else |
|
1431 stateId = ETS_NORMAL; |
|
1432 int fillType; |
|
1433 if (pGetThemeEnumValue(theme.handle(), partId, stateId, TMT_BGTYPE, &fillType) == S_OK) { |
|
1434 if (fillType == BT_BORDERFILL) { |
|
1435 COLORREF bcRef; |
|
1436 pGetThemeColor(theme.handle(), partId, stateId, TMT_BORDERCOLOR, &bcRef); |
|
1437 QColor bordercolor(qRgb(GetRValue(bcRef), GetGValue(bcRef), GetBValue(bcRef))); |
|
1438 QPen oldPen = p->pen(); |
|
1439 // int borderSize = 1; |
|
1440 // pGetThemeInt(theme.handle(), partId, stateId, TMT_BORDERCOLOR, &borderSize); |
|
1441 |
|
1442 // Inner white border |
|
1443 p->setPen(QPen(option->palette.base().color(), 1)); |
|
1444 p->drawRect(option->rect.adjusted(1, 1, -2, -2)); |
|
1445 // Outer dark border |
|
1446 p->setPen(QPen(bordercolor, 1)); |
|
1447 p->drawRect(option->rect.adjusted(0, 0, -1, -1)); |
|
1448 p->setPen(oldPen); |
|
1449 return; |
|
1450 } else if (fillType == BT_NONE) { |
|
1451 return; |
|
1452 } else { |
|
1453 break; |
|
1454 } |
|
1455 } |
|
1456 } |
|
1457 case PE_FrameLineEdit: { |
|
1458 // we try to check if this lineedit is a delegate on a QAbstractItemView-derived class. |
|
1459 QWidget *parentWidget = 0; |
|
1460 if (widget) |
|
1461 parentWidget = widget->parentWidget(); |
|
1462 if (parentWidget) |
|
1463 parentWidget = parentWidget->parentWidget(); |
|
1464 if (widget && widget->inherits("QLineEdit") |
|
1465 && parentWidget && parentWidget->inherits("QAbstractItemView")) { |
|
1466 QPen oldPen = p->pen(); |
|
1467 // Inner white border |
|
1468 p->setPen(QPen(option->palette.base().color(), 1)); |
|
1469 p->drawRect(option->rect.adjusted(1, 1, -2, -2)); |
|
1470 // Outer dark border |
|
1471 p->setPen(QPen(option->palette.shadow().color(), 1)); |
|
1472 p->drawRect(option->rect.adjusted(0, 0, -1, -1)); |
|
1473 p->setPen(oldPen); |
|
1474 return; |
|
1475 } else if (qstyleoption_cast<const QStyleOptionFrame *>(option)) { |
|
1476 name = QLatin1String("EDIT"); |
|
1477 partId = EP_EDITTEXT; |
|
1478 noContent = true; |
|
1479 if (!(flags & State_Enabled)) |
|
1480 stateId = ETS_DISABLED; |
|
1481 else |
|
1482 stateId = ETS_NORMAL; |
|
1483 } |
|
1484 break; |
|
1485 } |
|
1486 |
|
1487 case PE_PanelLineEdit: |
|
1488 if (const QStyleOptionFrame *panel = qstyleoption_cast<const QStyleOptionFrame *>(option)) { |
|
1489 name = QLatin1String("EDIT"); |
|
1490 partId = EP_EDITTEXT; |
|
1491 noBorder = true; |
|
1492 QBrush bg; |
|
1493 bool usePalette = false; |
|
1494 bool isEnabled = flags & State_Enabled; |
|
1495 uint resolve_mask = panel->palette.resolve(); |
|
1496 |
|
1497 #ifndef QT_NO_SPINBOX |
|
1498 //Since spin box includes a line edit we need to resolve the palette on the spin box instead |
|
1499 if (widget) { |
|
1500 if (QAbstractSpinBox *spinbox = qobject_cast<QAbstractSpinBox*>(widget->parentWidget())) |
|
1501 resolve_mask = spinbox->palette().resolve(); |
|
1502 } |
|
1503 #endif // QT_NO_SPINBOX |
|
1504 if (resolve_mask & (1 << QPalette::Base)) { |
|
1505 // Base color is set for this widget, so use it |
|
1506 bg = panel->palette.brush(QPalette::Base); |
|
1507 usePalette = true; |
|
1508 } |
|
1509 |
|
1510 stateId = isEnabled ? ETS_NORMAL : ETS_DISABLED; |
|
1511 |
|
1512 if (usePalette) { |
|
1513 p->fillRect(panel->rect, bg); |
|
1514 } else { |
|
1515 XPThemeData theme(0, p, name, partId, stateId, rect); |
|
1516 if (!theme.isValid()) { |
|
1517 QWindowsStyle::drawPrimitive(pe, option, p, widget); |
|
1518 return; |
|
1519 } |
|
1520 int bgType; |
|
1521 pGetThemeEnumValue( theme.handle(), |
|
1522 partId, |
|
1523 stateId, |
|
1524 TMT_BGTYPE, |
|
1525 &bgType); |
|
1526 if( bgType == BT_IMAGEFILE ) { |
|
1527 theme.mirrorHorizontally = hMirrored; |
|
1528 theme.mirrorVertically = vMirrored; |
|
1529 theme.noBorder = noBorder; |
|
1530 theme.noContent = noContent; |
|
1531 theme.rotate = rotate; |
|
1532 d->drawBackground(theme); |
|
1533 } else { |
|
1534 QBrush fillColor = option->palette.brush(QPalette::Base); |
|
1535 |
|
1536 if (!isEnabled) { |
|
1537 PROPERTYORIGIN origin = PO_NOTFOUND; |
|
1538 pGetThemePropertyOrigin(theme.handle(), theme.partId, theme.stateId, TMT_FILLCOLOR, &origin); |
|
1539 // Use only if the fill property comes from our part |
|
1540 if ((origin == PO_PART || origin == PO_STATE)) { |
|
1541 COLORREF bgRef; |
|
1542 pGetThemeColor(theme.handle(), partId, stateId, TMT_FILLCOLOR, &bgRef); |
|
1543 fillColor = QBrush(qRgb(GetRValue(bgRef), GetGValue(bgRef), GetBValue(bgRef))); |
|
1544 } |
|
1545 } |
|
1546 p->fillRect(option->rect, fillColor); |
|
1547 } |
|
1548 } |
|
1549 |
|
1550 if (panel->lineWidth > 0) |
|
1551 proxy()->drawPrimitive(PE_FrameLineEdit, panel, p, widget); |
|
1552 return; |
|
1553 } |
|
1554 break; |
|
1555 |
|
1556 case PE_FrameTabWidget: |
|
1557 if (const QStyleOptionTabWidgetFrame *tab = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(option)) |
|
1558 { |
|
1559 name = QLatin1String("TAB"); |
|
1560 partId = TABP_PANE; |
|
1561 |
|
1562 if (widget) { |
|
1563 bool useGradient = true; |
|
1564 const int maxlength = 256; |
|
1565 wchar_t themeFileName[maxlength]; |
|
1566 wchar_t themeColor[maxlength]; |
|
1567 // Due to a a scaling issue with the XP Silver theme, tab gradients are not used with it |
|
1568 if (pGetCurrentThemeName(themeFileName, maxlength, themeColor, maxlength, NULL, 0) == S_OK) { |
|
1569 wchar_t *offset = 0; |
|
1570 if ((offset = wcsrchr(themeFileName, QChar(QLatin1Char('\\')).unicode())) != NULL) { |
|
1571 offset++; |
|
1572 if (!lstrcmp(offset, L"Luna.msstyles") && !lstrcmp(offset, L"Metallic")) { |
|
1573 useGradient = false; |
|
1574 } |
|
1575 } |
|
1576 } |
|
1577 // This should work, but currently there's an error in the ::drawBackgroundDirectly() |
|
1578 // code, when using the HDC directly.. |
|
1579 if (useGradient) { |
|
1580 QStyleOptionTabWidgetFrame frameOpt = *tab; |
|
1581 frameOpt.rect = widget->rect(); |
|
1582 QRect contentsRect = subElementRect(SE_TabWidgetTabContents, &frameOpt, widget); |
|
1583 QRegion reg = option->rect; |
|
1584 reg -= contentsRect; |
|
1585 p->setClipRegion(reg); |
|
1586 XPThemeData theme(widget, p, name, partId, stateId, rect); |
|
1587 theme.mirrorHorizontally = hMirrored; |
|
1588 theme.mirrorVertically = vMirrored; |
|
1589 d->drawBackground(theme); |
|
1590 p->setClipRect(contentsRect); |
|
1591 partId = TABP_BODY; |
|
1592 } |
|
1593 } |
|
1594 switch (tab->shape) { |
|
1595 case QTabBar::RoundedNorth: |
|
1596 case QTabBar::TriangularNorth: |
|
1597 break; |
|
1598 case QTabBar::RoundedSouth: |
|
1599 case QTabBar::TriangularSouth: |
|
1600 vMirrored = true; |
|
1601 break; |
|
1602 case QTabBar::RoundedEast: |
|
1603 case QTabBar::TriangularEast: |
|
1604 rotate = 90; |
|
1605 break; |
|
1606 case QTabBar::RoundedWest: |
|
1607 case QTabBar::TriangularWest: |
|
1608 rotate = 90; |
|
1609 hMirrored = true; |
|
1610 break; |
|
1611 default: |
|
1612 break; |
|
1613 } |
|
1614 } |
|
1615 break; |
|
1616 |
|
1617 case PE_FrameMenu: |
|
1618 p->save(); |
|
1619 p->setPen(option->palette.dark().color()); |
|
1620 p->drawRect(rect.adjusted(0, 0, -1, -1)); |
|
1621 p->restore(); |
|
1622 return; |
|
1623 |
|
1624 case PE_PanelMenuBar: |
|
1625 break; |
|
1626 |
|
1627 case PE_FrameDockWidget: |
|
1628 if (const QStyleOptionFrame *frm = qstyleoption_cast<const QStyleOptionFrame *>(option)) |
|
1629 { |
|
1630 name = QLatin1String("WINDOW"); |
|
1631 if (flags & State_Active) |
|
1632 stateId = FS_ACTIVE; |
|
1633 else |
|
1634 stateId = FS_INACTIVE; |
|
1635 |
|
1636 int fwidth = proxy()->pixelMetric(PM_DockWidgetFrameWidth, frm, widget); |
|
1637 |
|
1638 XPThemeData theme(widget, p, name, 0, stateId); |
|
1639 if (!theme.isValid()) |
|
1640 break; |
|
1641 theme.rect = QRect(frm->rect.x(), frm->rect.y(), frm->rect.x()+fwidth, frm->rect.height()-fwidth); theme.partId = WP_SMALLFRAMELEFT; |
|
1642 d->drawBackground(theme); |
|
1643 theme.rect = QRect(frm->rect.width()-fwidth, frm->rect.y(), fwidth, frm->rect.height()-fwidth); |
|
1644 theme.partId = WP_SMALLFRAMERIGHT; |
|
1645 d->drawBackground(theme); |
|
1646 theme.rect = QRect(frm->rect.x(), frm->rect.bottom()-fwidth+1, frm->rect.width(), fwidth); |
|
1647 theme.partId = WP_SMALLFRAMEBOTTOM; |
|
1648 d->drawBackground(theme); |
|
1649 return; |
|
1650 } |
|
1651 break; |
|
1652 |
|
1653 case PE_IndicatorHeaderArrow: |
|
1654 { |
|
1655 #if 0 // XP theme engine doesn't know about this :( |
|
1656 name = QLatin1String("HEADER"); |
|
1657 partId = HP_HEADERSORTARROW; |
|
1658 if (flags & State_Down) |
|
1659 stateId = HSAS_SORTEDDOWN; |
|
1660 else |
|
1661 stateId = HSAS_SORTEDUP; |
|
1662 #else |
|
1663 if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) { |
|
1664 p->save(); |
|
1665 p->setPen(option->palette.dark().color()); |
|
1666 p->translate(0, option->rect.height()/2 - 4); |
|
1667 if (header->sortIndicator & QStyleOptionHeader::SortUp) { // invert logic to follow Windows style guide |
|
1668 p->drawLine(option->rect.x(), option->rect.y(), option->rect.x()+8, option->rect.y()); |
|
1669 p->drawLine(option->rect.x()+1, option->rect.y()+1, option->rect.x()+7, option->rect.y()+1); |
|
1670 p->drawLine(option->rect.x()+2, option->rect.y()+2, option->rect.x()+6, option->rect.y()+2); |
|
1671 p->drawLine(option->rect.x()+3, option->rect.y()+3, option->rect.x()+5, option->rect.y()+3); |
|
1672 p->drawPoint(option->rect.x()+4, option->rect.y()+4); |
|
1673 } else if(header->sortIndicator & QStyleOptionHeader::SortDown) { |
|
1674 p->drawLine(option->rect.x(), option->rect.y()+4, option->rect.x()+8, option->rect.y()+4); |
|
1675 p->drawLine(option->rect.x()+1, option->rect.y()+3, option->rect.x()+7, option->rect.y()+3); |
|
1676 p->drawLine(option->rect.x()+2, option->rect.y()+2, option->rect.x()+6, option->rect.y()+2); |
|
1677 p->drawLine(option->rect.x()+3, option->rect.y()+1, option->rect.x()+5, option->rect.y()+1); |
|
1678 p->drawPoint(option->rect.x()+4, option->rect.y()); |
|
1679 } |
|
1680 p->restore(); |
|
1681 return; |
|
1682 } |
|
1683 #endif |
|
1684 } |
|
1685 break; |
|
1686 |
|
1687 case PE_FrameStatusBarItem: |
|
1688 name = QLatin1String("STATUS"); |
|
1689 partId = SP_PANE; |
|
1690 break; |
|
1691 |
|
1692 case PE_FrameGroupBox: |
|
1693 name = QLatin1String("BUTTON"); |
|
1694 partId = BP_GROUPBOX; |
|
1695 if (!(flags & State_Enabled)) |
|
1696 stateId = GBS_DISABLED; |
|
1697 else |
|
1698 stateId = GBS_NORMAL; |
|
1699 if (const QStyleOptionFrame *frame = qstyleoption_cast<const QStyleOptionFrame *>(option)) { |
|
1700 const QStyleOptionFrameV2 *frame2 = qstyleoption_cast<const QStyleOptionFrameV2 *>(option); |
|
1701 if (frame2->features & QStyleOptionFrameV2::Flat) { |
|
1702 // Windows XP does not have a theme part for a flat GroupBox, paint it with the windows style |
|
1703 QRect fr = frame->rect; |
|
1704 QPoint p1(fr.x(), fr.y() + 1); |
|
1705 QPoint p2(fr.x() + fr.width(), p1.y() + 1); |
|
1706 rect = QRect(p1, p2); |
|
1707 name = QLatin1String(""); |
|
1708 } |
|
1709 } |
|
1710 break; |
|
1711 |
|
1712 case PE_IndicatorProgressChunk: |
|
1713 { |
|
1714 Qt::Orientation orient = Qt::Horizontal; |
|
1715 bool inverted = false; |
|
1716 if (const QStyleOptionProgressBarV2 *pb2 = qstyleoption_cast<const QStyleOptionProgressBarV2 *>(option)) { |
|
1717 orient = pb2->orientation; |
|
1718 if (pb2->invertedAppearance) |
|
1719 inverted = true; |
|
1720 } |
|
1721 if (orient == Qt::Horizontal) { |
|
1722 partId = PP_CHUNK; |
|
1723 rect = QRect(option->rect.x(), option->rect.y(), option->rect.width(), option->rect.height() ); |
|
1724 if (inverted && option->direction == Qt::LeftToRight) |
|
1725 hMirrored = true; |
|
1726 } else { |
|
1727 partId = PP_CHUNKVERT; |
|
1728 rect = QRect(option->rect.x(), option->rect.y(), option->rect.width(), option->rect.height()); |
|
1729 } |
|
1730 name = QLatin1String("PROGRESS"); |
|
1731 stateId = 1; |
|
1732 } |
|
1733 break; |
|
1734 |
|
1735 case PE_Q3DockWindowSeparator: |
|
1736 name = QLatin1String("TOOLBAR"); |
|
1737 if (flags & State_Horizontal) |
|
1738 partId = TP_SEPARATOR; |
|
1739 else |
|
1740 partId = TP_SEPARATORVERT; |
|
1741 break; |
|
1742 |
|
1743 case PE_FrameWindow: |
|
1744 if (const QStyleOptionFrame *frm = qstyleoption_cast<const QStyleOptionFrame *>(option)) |
|
1745 { |
|
1746 name = QLatin1String("WINDOW"); |
|
1747 if (flags & State_Active) |
|
1748 stateId = FS_ACTIVE; |
|
1749 else |
|
1750 stateId = FS_INACTIVE; |
|
1751 |
|
1752 int fwidth = frm->lineWidth + frm->midLineWidth; |
|
1753 |
|
1754 XPThemeData theme(0, p, name, 0, stateId); |
|
1755 if (!theme.isValid()) |
|
1756 break; |
|
1757 |
|
1758 theme.rect = QRect(option->rect.x(), option->rect.y()+fwidth, option->rect.x()+fwidth, option->rect.height()-fwidth); |
|
1759 theme.partId = WP_FRAMELEFT; |
|
1760 d->drawBackground(theme); |
|
1761 theme.rect = QRect(option->rect.width()-fwidth, option->rect.y()+fwidth, fwidth, option->rect.height()-fwidth); |
|
1762 theme.partId = WP_FRAMERIGHT; |
|
1763 d->drawBackground(theme); |
|
1764 theme.rect = QRect(option->rect.x(), option->rect.height()-fwidth, option->rect.width(), fwidth); |
|
1765 theme.partId = WP_FRAMEBOTTOM; |
|
1766 d->drawBackground(theme); |
|
1767 theme.rect = QRect(option->rect.x(), option->rect.y(), option->rect.width(), option->rect.y()+fwidth); |
|
1768 theme.partId = WP_CAPTION; |
|
1769 d->drawBackground(theme); |
|
1770 return; |
|
1771 } |
|
1772 break; |
|
1773 |
|
1774 case PE_IndicatorBranch: |
|
1775 { |
|
1776 static const int decoration_size = 9; |
|
1777 int mid_h = option->rect.x() + option->rect.width() / 2; |
|
1778 int mid_v = option->rect.y() + option->rect.height() / 2; |
|
1779 int bef_h = mid_h; |
|
1780 int bef_v = mid_v; |
|
1781 int aft_h = mid_h; |
|
1782 int aft_v = mid_v; |
|
1783 QBrush brush(option->palette.dark().color(), Qt::Dense4Pattern); |
|
1784 if (option->state & State_Item) { |
|
1785 if (option->direction == Qt::RightToLeft) |
|
1786 p->fillRect(option->rect.left(), mid_v, bef_h - option->rect.left(), 1, brush); |
|
1787 else |
|
1788 p->fillRect(aft_h, mid_v, option->rect.right() - aft_h + 1, 1, brush); |
|
1789 } |
|
1790 if (option->state & State_Sibling) |
|
1791 p->fillRect(mid_h, aft_v, 1, option->rect.bottom() - aft_v + 1, brush); |
|
1792 if (option->state & (State_Open | State_Children | State_Item | State_Sibling)) |
|
1793 p->fillRect(mid_h, option->rect.y(), 1, bef_v - option->rect.y(), brush); |
|
1794 if (option->state & State_Children) { |
|
1795 int delta = decoration_size / 2; |
|
1796 bef_h -= delta; |
|
1797 bef_v -= delta; |
|
1798 aft_h += delta; |
|
1799 aft_v += delta; |
|
1800 XPThemeData theme(0, p, QLatin1String("TREEVIEW")); |
|
1801 theme.rect = QRect(bef_h, bef_v, decoration_size, decoration_size); |
|
1802 theme.partId = TVP_GLYPH; |
|
1803 theme.stateId = flags & QStyle::State_Open ? GLPS_OPENED : GLPS_CLOSED; |
|
1804 d->drawBackground(theme); |
|
1805 } |
|
1806 } |
|
1807 return; |
|
1808 |
|
1809 case PE_IndicatorToolBarSeparator: |
|
1810 if (option->rect.height() < 3) { |
|
1811 // XP style requires a few pixels for the separator |
|
1812 // to be visible. |
|
1813 QWindowsStyle::drawPrimitive(pe, option, p, widget); |
|
1814 return; |
|
1815 } |
|
1816 name = QLatin1String("TOOLBAR"); |
|
1817 partId = TP_SEPARATOR; |
|
1818 |
|
1819 if (option->state & State_Horizontal) |
|
1820 partId = TP_SEPARATOR; |
|
1821 else |
|
1822 partId = TP_SEPARATORVERT; |
|
1823 |
|
1824 break; |
|
1825 |
|
1826 case PE_IndicatorToolBarHandle: |
|
1827 |
|
1828 name = QLatin1String("REBAR"); |
|
1829 partId = RP_GRIPPER; |
|
1830 if (option->state & State_Horizontal) { |
|
1831 partId = RP_GRIPPER; |
|
1832 rect.adjust(0, 0, -2, 0); |
|
1833 } |
|
1834 else { |
|
1835 partId = RP_GRIPPERVERT; |
|
1836 rect.adjust(0, 0, 0, -2); |
|
1837 } |
|
1838 break; |
|
1839 |
|
1840 case PE_IndicatorItemViewItemCheck: { |
|
1841 QStyleOptionButton button; |
|
1842 button.QStyleOption::operator=(*option); |
|
1843 button.state &= ~State_MouseOver; |
|
1844 proxy()->drawPrimitive(PE_IndicatorCheckBox, &button, p, widget); |
|
1845 return; |
|
1846 } |
|
1847 |
|
1848 default: |
|
1849 break; |
|
1850 } |
|
1851 |
|
1852 XPThemeData theme(0, p, name, partId, stateId, rect); |
|
1853 if (!theme.isValid()) { |
|
1854 QWindowsStyle::drawPrimitive(pe, option, p, widget); |
|
1855 return; |
|
1856 } |
|
1857 theme.mirrorHorizontally = hMirrored; |
|
1858 theme.mirrorVertically = vMirrored; |
|
1859 theme.noBorder = noBorder; |
|
1860 theme.noContent = noContent; |
|
1861 theme.rotate = rotate; |
|
1862 d->drawBackground(theme); |
|
1863 } |
|
1864 |
|
1865 /*! |
|
1866 \reimp |
|
1867 */ |
|
1868 void QWindowsXPStyle::drawControl(ControlElement element, const QStyleOption *option, QPainter *p, |
|
1869 const QWidget *widget) const |
|
1870 { |
|
1871 QWindowsXPStylePrivate *d = const_cast<QWindowsXPStylePrivate*>(d_func()); |
|
1872 if (!QWindowsXPStylePrivate::useXP()) { |
|
1873 QWindowsStyle::drawControl(element, option, p, widget); |
|
1874 return; |
|
1875 } |
|
1876 |
|
1877 QRect rect(option->rect); |
|
1878 State flags = option->state; |
|
1879 |
|
1880 int rotate = 0; |
|
1881 bool hMirrored = false; |
|
1882 bool vMirrored = false; |
|
1883 |
|
1884 QString name; |
|
1885 int partId = 0; |
|
1886 int stateId = 0; |
|
1887 switch (element) { |
|
1888 case CE_SizeGrip: |
|
1889 { |
|
1890 name = QLatin1String("STATUS"); |
|
1891 partId = SP_GRIPPER; |
|
1892 SIZE sz; |
|
1893 XPThemeData theme(0, p, name, partId, 0); |
|
1894 pGetThemePartSize(theme.handle(), 0, partId, 0, 0, TS_TRUE, &sz); |
|
1895 --sz.cy; |
|
1896 if (const QStyleOptionSizeGrip *sg = qstyleoption_cast<const QStyleOptionSizeGrip *>(option)) { |
|
1897 switch (sg->corner) { |
|
1898 case Qt::BottomRightCorner: |
|
1899 rect = QRect(rect.right() - sz.cx, rect.bottom() - sz.cy, sz.cx, sz.cy); |
|
1900 break; |
|
1901 case Qt::BottomLeftCorner: |
|
1902 rect = QRect(rect.left() + 1, rect.bottom() - sz.cy, sz.cx, sz.cy); |
|
1903 hMirrored = true; |
|
1904 break; |
|
1905 case Qt::TopRightCorner: |
|
1906 rect = QRect(rect.right() - sz.cx, rect.top() + 1, sz.cx, sz.cy); |
|
1907 vMirrored = true; |
|
1908 break; |
|
1909 case Qt::TopLeftCorner: |
|
1910 rect = QRect(rect.left() + 1, rect.top() + 1, sz.cx, sz.cy); |
|
1911 hMirrored = vMirrored = true; |
|
1912 } |
|
1913 } |
|
1914 } |
|
1915 break; |
|
1916 |
|
1917 case CE_HeaderSection: |
|
1918 name = QLatin1String("HEADER"); |
|
1919 partId = HP_HEADERITEM; |
|
1920 if (flags & State_Sunken) |
|
1921 stateId = HIS_PRESSED; |
|
1922 else if (flags & State_MouseOver) |
|
1923 stateId = HIS_HOT; |
|
1924 else |
|
1925 stateId = HIS_NORMAL; |
|
1926 break; |
|
1927 |
|
1928 case CE_Splitter: |
|
1929 p->eraseRect(option->rect); |
|
1930 return; |
|
1931 |
|
1932 case CE_PushButtonBevel: |
|
1933 if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) |
|
1934 { |
|
1935 name = QLatin1String("BUTTON"); |
|
1936 partId = BP_PUSHBUTTON; |
|
1937 bool justFlat = ((btn->features & QStyleOptionButton::Flat) && !(flags & (State_On|State_Sunken))) |
|
1938 || ((btn->features & QStyleOptionButton::CommandLinkButton) |
|
1939 && !(flags & State_MouseOver) |
|
1940 && !(btn->features & QStyleOptionButton::DefaultButton)); |
|
1941 if (!(flags & State_Enabled) && !(btn->features & QStyleOptionButton::Flat)) |
|
1942 stateId = PBS_DISABLED; |
|
1943 else if (justFlat) |
|
1944 ; |
|
1945 else if (flags & (State_Sunken | State_On)) |
|
1946 stateId = PBS_PRESSED; |
|
1947 else if (flags & State_MouseOver) |
|
1948 stateId = PBS_HOT; |
|
1949 else if (btn->features & QStyleOptionButton::DefaultButton) |
|
1950 stateId = PBS_DEFAULTED; |
|
1951 else |
|
1952 stateId = PBS_NORMAL; |
|
1953 |
|
1954 if (!justFlat) { |
|
1955 XPThemeData theme(widget, p, name, partId, stateId, rect); |
|
1956 d->drawBackground(theme); |
|
1957 } |
|
1958 |
|
1959 if (btn->features & QStyleOptionButton::HasMenu) { |
|
1960 int mbiw = 0, mbih = 0; |
|
1961 XPThemeData theme(widget, 0, QLatin1String("TOOLBAR"), TP_SPLITBUTTONDROPDOWN); |
|
1962 if (theme.isValid()) { |
|
1963 SIZE size; |
|
1964 pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); |
|
1965 mbiw = size.cx; |
|
1966 mbih = size.cy; |
|
1967 } |
|
1968 |
|
1969 QRect ir = btn->rect; |
|
1970 QStyleOptionButton newBtn = *btn; |
|
1971 newBtn.rect = QRect(ir.right() - mbiw - 1, 1 + (ir.height()/2) - (mbih/2), mbiw, mbih); |
|
1972 proxy()->drawPrimitive(PE_IndicatorArrowDown, &newBtn, p, widget); |
|
1973 } |
|
1974 return; |
|
1975 } |
|
1976 break; |
|
1977 case CE_TabBarTab: |
|
1978 if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(option)) |
|
1979 { |
|
1980 stateId = tab->state & State_Enabled ? TIS_NORMAL : TIS_DISABLED; |
|
1981 } |
|
1982 break; |
|
1983 |
|
1984 case CE_TabBarTabShape: |
|
1985 if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(option)) |
|
1986 { |
|
1987 name = QLatin1String("TAB"); |
|
1988 bool isDisabled = !(tab->state & State_Enabled); |
|
1989 bool hasFocus = tab->state & State_HasFocus; |
|
1990 bool isHot = tab->state & State_MouseOver; |
|
1991 bool selected = tab->state & State_Selected; |
|
1992 bool lastTab = tab->position == QStyleOptionTab::End; |
|
1993 bool firstTab = tab->position == QStyleOptionTab::Beginning; |
|
1994 bool onlyOne = tab->position == QStyleOptionTab::OnlyOneTab; |
|
1995 bool leftAligned = proxy()->styleHint(SH_TabBar_Alignment, tab, widget) == Qt::AlignLeft; |
|
1996 bool centerAligned = proxy()->styleHint(SH_TabBar_Alignment, tab, widget) == Qt::AlignCenter; |
|
1997 int borderThickness = proxy()->pixelMetric(PM_DefaultFrameWidth, option, widget); |
|
1998 int tabOverlap = proxy()->pixelMetric(PM_TabBarTabOverlap, option, widget); |
|
1999 |
|
2000 if (isDisabled) |
|
2001 stateId = TIS_DISABLED; |
|
2002 else if (selected) |
|
2003 stateId = TIS_SELECTED; |
|
2004 else if (hasFocus) |
|
2005 stateId = TIS_FOCUSED; |
|
2006 else if (isHot) |
|
2007 stateId = TIS_HOT; |
|
2008 else |
|
2009 stateId = TIS_NORMAL; |
|
2010 |
|
2011 // Selecting proper part depending on position |
|
2012 if (firstTab || onlyOne) { |
|
2013 if (leftAligned) { |
|
2014 partId = TABP_TABITEMLEFTEDGE; |
|
2015 } else if (centerAligned) { |
|
2016 partId = TABP_TABITEM; |
|
2017 } else { // rightAligned |
|
2018 partId = TABP_TABITEMRIGHTEDGE; |
|
2019 } |
|
2020 } else { |
|
2021 partId = TABP_TABITEM; |
|
2022 } |
|
2023 |
|
2024 if (tab->direction == Qt::RightToLeft |
|
2025 && (tab->shape == QTabBar::RoundedNorth |
|
2026 || tab->shape == QTabBar::RoundedSouth)) { |
|
2027 bool temp = firstTab; |
|
2028 firstTab = lastTab; |
|
2029 lastTab = temp; |
|
2030 } |
|
2031 bool begin = firstTab || onlyOne; |
|
2032 bool end = lastTab || onlyOne; |
|
2033 switch (tab->shape) { |
|
2034 case QTabBar::RoundedNorth: |
|
2035 if (selected) |
|
2036 rect.adjust(begin ? 0 : -tabOverlap, 0, end ? 0 : tabOverlap, borderThickness); |
|
2037 else |
|
2038 rect.adjust(begin? tabOverlap : 0, tabOverlap, end ? -tabOverlap : 0, 0); |
|
2039 break; |
|
2040 case QTabBar::RoundedSouth: |
|
2041 //vMirrored = true; |
|
2042 rotate = 180; // Not 100% correct, but works |
|
2043 if (selected) |
|
2044 rect.adjust(begin ? 0 : -tabOverlap , -borderThickness, end ? 0 : tabOverlap, 0); |
|
2045 else |
|
2046 rect.adjust(begin ? tabOverlap : 0, 0, end ? -tabOverlap : 0 , -tabOverlap); |
|
2047 break; |
|
2048 case QTabBar::RoundedEast: |
|
2049 rotate = 90; |
|
2050 if (selected) { |
|
2051 rect.adjust(-borderThickness, begin ? 0 : -tabOverlap, 0, end ? 0 : tabOverlap); |
|
2052 }else{ |
|
2053 rect.adjust(0, begin ? tabOverlap : 0, -tabOverlap, end ? -tabOverlap : 0); |
|
2054 } |
|
2055 break; |
|
2056 case QTabBar::RoundedWest: |
|
2057 hMirrored = true; |
|
2058 rotate = 90; |
|
2059 if (selected) { |
|
2060 rect.adjust(0, begin ? 0 : -tabOverlap, borderThickness, end ? 0 : tabOverlap); |
|
2061 }else{ |
|
2062 rect.adjust(tabOverlap, begin ? tabOverlap : 0, 0, end ? -tabOverlap : 0); |
|
2063 } |
|
2064 break; |
|
2065 default: |
|
2066 name = QLatin1String(""); // Do our own painting for triangular |
|
2067 break; |
|
2068 } |
|
2069 |
|
2070 if (!selected) { |
|
2071 switch (tab->shape) { |
|
2072 case QTabBar::RoundedNorth: |
|
2073 rect.adjust(0,0, 0,-1); |
|
2074 break; |
|
2075 case QTabBar::RoundedSouth: |
|
2076 rect.adjust(0,1, 0,0); |
|
2077 break; |
|
2078 case QTabBar::RoundedEast: |
|
2079 rect.adjust( 1,0, 0,0); |
|
2080 break; |
|
2081 case QTabBar::RoundedWest: |
|
2082 rect.adjust(0,0, -1,0); |
|
2083 break; |
|
2084 default: |
|
2085 break; |
|
2086 } |
|
2087 } |
|
2088 } |
|
2089 break; |
|
2090 |
|
2091 case CE_ProgressBarGroove: |
|
2092 { |
|
2093 Qt::Orientation orient = Qt::Horizontal; |
|
2094 if (const QStyleOptionProgressBarV2 *pb2 = qstyleoption_cast<const QStyleOptionProgressBarV2 *>(option)) |
|
2095 orient = pb2->orientation; |
|
2096 partId = (orient == Qt::Horizontal) ? PP_BAR : PP_BARVERT; |
|
2097 name = QLatin1String("PROGRESS"); |
|
2098 stateId = 1; |
|
2099 } |
|
2100 break; |
|
2101 |
|
2102 case CE_MenuEmptyArea: |
|
2103 case CE_MenuItem: |
|
2104 if (const QStyleOptionMenuItem *menuitem = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) |
|
2105 { |
|
2106 int tab = menuitem->tabWidth; |
|
2107 bool dis = !(menuitem->state & State_Enabled); |
|
2108 bool act = menuitem->state & State_Selected; |
|
2109 bool checkable = menuitem->menuHasCheckableItems; |
|
2110 bool checked = checkable ? menuitem->checked : false; |
|
2111 |
|
2112 // windows always has a check column, regardless whether we have an icon or not |
|
2113 int checkcol = qMax(menuitem->maxIconWidth, 12); |
|
2114 |
|
2115 int x, y, w, h; |
|
2116 rect.getRect(&x, &y, &w, &h); |
|
2117 |
|
2118 QBrush fill = menuitem->palette.brush(act ? QPalette::Highlight : QPalette::Button); |
|
2119 p->fillRect(rect, fill); |
|
2120 |
|
2121 if (element == CE_MenuEmptyArea) |
|
2122 break; |
|
2123 |
|
2124 // draw separator ------------------------------------------------- |
|
2125 if (menuitem->menuItemType == QStyleOptionMenuItem::Separator) { |
|
2126 int yoff = y-1 + h / 2; |
|
2127 p->setPen(menuitem->palette.dark().color()); |
|
2128 p->drawLine(x, yoff, x+w, yoff); |
|
2129 ++yoff; |
|
2130 p->setPen(menuitem->palette.light().color()); |
|
2131 p->drawLine(x, yoff, x+w, yoff); |
|
2132 return; |
|
2133 } |
|
2134 |
|
2135 int xpos = x; |
|
2136 |
|
2137 // draw icon ------------------------------------------------------ |
|
2138 if (!menuitem->icon.isNull()) { |
|
2139 QIcon::Mode mode = dis ? QIcon::Disabled : QIcon::Normal; |
|
2140 if (act && !dis) |
|
2141 mode = QIcon::Active; |
|
2142 QPixmap pixmap = checked ? |
|
2143 menuitem->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize, option, widget), mode, QIcon::On) : |
|
2144 menuitem->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize, option, widget), mode); |
|
2145 int pixw = pixmap.width(); |
|
2146 int pixh = pixmap.height(); |
|
2147 QRect iconRect(0, 0, pixw, pixh); |
|
2148 iconRect.moveCenter(QRect(xpos, y, checkcol, h).center()); |
|
2149 QRect vIconRect = visualRect(option->direction, option->rect, iconRect); |
|
2150 p->setPen(menuitem->palette.text().color()); |
|
2151 p->setBrush(Qt::NoBrush); |
|
2152 if (checked) |
|
2153 p->drawRect(vIconRect.adjusted(-1, -2, 1, 1)); |
|
2154 p->drawPixmap(vIconRect.topLeft(), pixmap); |
|
2155 |
|
2156 // draw checkmark ------------------------------------------------- |
|
2157 } else if (checked) { |
|
2158 QStyleOptionMenuItem newMi = *menuitem; |
|
2159 newMi.state = State_None; |
|
2160 if (!dis) |
|
2161 newMi.state |= State_Enabled; |
|
2162 if (act) |
|
2163 newMi.state |= State_On; |
|
2164 |
|
2165 QRect checkMarkRect = QRect(menuitem->rect.x() + windowsItemFrame, |
|
2166 menuitem->rect.y() + windowsItemFrame, |
|
2167 checkcol - 2 * windowsItemFrame, |
|
2168 menuitem->rect.height() - 2*windowsItemFrame); |
|
2169 newMi.rect = visualRect(option->direction, option->rect, checkMarkRect); |
|
2170 proxy()->drawPrimitive(PE_IndicatorMenuCheckMark, &newMi, p, widget); |
|
2171 } |
|
2172 |
|
2173 QColor textColor = dis ? menuitem->palette.text().color() : |
|
2174 act ? menuitem->palette.highlightedText().color() : menuitem->palette.buttonText().color(); |
|
2175 p->setPen(textColor); |
|
2176 |
|
2177 // draw text ------------------------------------------------------ |
|
2178 int xm = windowsItemFrame + checkcol + windowsItemHMargin; |
|
2179 xpos = menuitem->rect.x() + xm; |
|
2180 QRect textRect(xpos, y + windowsItemVMargin, w - xm - windowsRightBorder - tab + 1, h - 2 * windowsItemVMargin); |
|
2181 QRect vTextRect = visualRect(option->direction, option->rect, textRect); |
|
2182 QString s = menuitem->text; |
|
2183 if (!s.isEmpty()) { |
|
2184 p->save(); |
|
2185 int t = s.indexOf(QLatin1Char('\t')); |
|
2186 int text_flags = Qt::AlignVCenter|Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine | Qt::AlignLeft; |
|
2187 if (!proxy()->styleHint(SH_UnderlineShortcut, menuitem, widget)) |
|
2188 text_flags |= Qt::TextHideMnemonic; |
|
2189 // draw tab text ---------------- |
|
2190 if (t >= 0) { |
|
2191 QRect vShortcutRect = visualRect(option->direction, option->rect, QRect(textRect.topRight(), menuitem->rect.bottomRight())); |
|
2192 if (dis && !act && proxy()->styleHint(SH_EtchDisabledText, option, widget)) { |
|
2193 p->setPen(menuitem->palette.light().color()); |
|
2194 p->drawText(vShortcutRect.adjusted(1,1,1,1), text_flags, s.mid(t + 1)); |
|
2195 p->setPen(textColor); |
|
2196 } |
|
2197 p->drawText(vShortcutRect, text_flags, s.mid(t + 1)); |
|
2198 s = s.left(t); |
|
2199 } |
|
2200 QFont font = menuitem->font; |
|
2201 if (menuitem->menuItemType == QStyleOptionMenuItem::DefaultItem) |
|
2202 font.setBold(true); |
|
2203 p->setFont(font); |
|
2204 if (dis && !act && proxy()->styleHint(SH_EtchDisabledText, option, widget)) { |
|
2205 p->setPen(menuitem->palette.light().color()); |
|
2206 p->drawText(vTextRect.adjusted(1,1,1,1), text_flags, s.left(t)); |
|
2207 p->setPen(textColor); |
|
2208 } |
|
2209 p->drawText(vTextRect, text_flags, s); |
|
2210 p->restore(); |
|
2211 } |
|
2212 |
|
2213 // draw sub menu arrow -------------------------------------------- |
|
2214 if (menuitem->menuItemType == QStyleOptionMenuItem::SubMenu) { |
|
2215 int dim = (h - 2) / 2; |
|
2216 PrimitiveElement arrow; |
|
2217 arrow = (option->direction == Qt::RightToLeft) ? PE_IndicatorArrowLeft : PE_IndicatorArrowRight; |
|
2218 xpos = x + w - windowsArrowHMargin - windowsItemFrame - dim; |
|
2219 QRect vSubMenuRect = visualRect(option->direction, option->rect, QRect(xpos, y + h / 2 - dim / 2, dim, dim)); |
|
2220 QStyleOptionMenuItem newMI = *menuitem; |
|
2221 newMI.rect = vSubMenuRect; |
|
2222 newMI.state = dis ? State_None : State_Enabled; |
|
2223 if (act) |
|
2224 newMI.palette.setColor(QPalette::ButtonText, newMI.palette.highlightedText().color()); |
|
2225 proxy()->drawPrimitive(arrow, &newMI, p, widget); |
|
2226 } |
|
2227 } |
|
2228 return; |
|
2229 |
|
2230 case CE_MenuBarItem: |
|
2231 if (const QStyleOptionMenuItem *mbi = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) |
|
2232 { |
|
2233 if (mbi->menuItemType == QStyleOptionMenuItem::DefaultItem) |
|
2234 break; |
|
2235 |
|
2236 bool act = mbi->state & State_Selected; |
|
2237 bool dis = !(mbi->state & State_Enabled); |
|
2238 |
|
2239 QBrush fill = mbi->palette.brush(act ? QPalette::Highlight : QPalette::Button); |
|
2240 QPalette::ColorRole textRole = dis ? QPalette::Text: |
|
2241 act ? QPalette::HighlightedText : QPalette::ButtonText; |
|
2242 QPixmap pix = mbi->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize, option, widget), QIcon::Normal); |
|
2243 |
|
2244 uint alignment = Qt::AlignCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine; |
|
2245 if (!proxy()->styleHint(SH_UnderlineShortcut, mbi, widget)) |
|
2246 alignment |= Qt::TextHideMnemonic; |
|
2247 |
|
2248 p->fillRect(rect, fill); |
|
2249 if (!pix.isNull()) |
|
2250 drawItemPixmap(p, mbi->rect, alignment, pix); |
|
2251 else |
|
2252 drawItemText(p, mbi->rect, alignment, mbi->palette, mbi->state & State_Enabled, mbi->text, textRole); |
|
2253 } |
|
2254 return; |
|
2255 #ifndef QT_NO_DOCKWIDGET |
|
2256 case CE_DockWidgetTitle: |
|
2257 if (const QStyleOptionDockWidget *dwOpt = qstyleoption_cast<const QStyleOptionDockWidget *>(option)) |
|
2258 { |
|
2259 int buttonMargin = 4; |
|
2260 int mw = proxy()->pixelMetric(QStyle::PM_DockWidgetTitleMargin, dwOpt, widget); |
|
2261 int fw = proxy()->pixelMetric(PM_DockWidgetFrameWidth, dwOpt, widget); |
|
2262 bool isFloating = widget && widget->isWindow(); |
|
2263 bool isActive = dwOpt->state & State_Active; |
|
2264 |
|
2265 const QStyleOptionDockWidgetV2 *v2 |
|
2266 = qstyleoption_cast<const QStyleOptionDockWidgetV2*>(dwOpt); |
|
2267 bool verticalTitleBar = v2 == 0 ? false : v2->verticalTitleBar; |
|
2268 |
|
2269 if (verticalTitleBar) { |
|
2270 QSize s = rect.size(); |
|
2271 s.transpose(); |
|
2272 rect.setSize(s); |
|
2273 |
|
2274 p->translate(rect.left() - 1, rect.top() + rect.width()); |
|
2275 p->rotate(-90); |
|
2276 p->translate(-rect.left() + 1, -rect.top()); |
|
2277 } |
|
2278 QRect r = rect.adjusted(0, 2, -1, -3); |
|
2279 QRect titleRect = r; |
|
2280 |
|
2281 if (dwOpt->closable) { |
|
2282 QSize sz = proxy()->standardIcon(QStyle::SP_TitleBarCloseButton, dwOpt, widget).actualSize(QSize(10, 10)); |
|
2283 titleRect.adjust(0, 0, -sz.width() - mw - buttonMargin, 0); |
|
2284 } |
|
2285 |
|
2286 if (dwOpt->floatable) { |
|
2287 QSize sz = proxy()->standardIcon(QStyle::SP_TitleBarMaxButton, dwOpt, widget).actualSize(QSize(10, 10)); |
|
2288 titleRect.adjust(0, 0, -sz.width() - mw - buttonMargin, 0); |
|
2289 } |
|
2290 |
|
2291 if (isFloating) { |
|
2292 titleRect.adjust(0, -fw, 0, 0); |
|
2293 if (widget != 0 && widget->windowIcon().cacheKey() != QApplication::windowIcon().cacheKey()) |
|
2294 titleRect.adjust(titleRect.height() + mw, 0, 0, 0); |
|
2295 } else { |
|
2296 titleRect.adjust(mw, 0, 0, 0); |
|
2297 if (!dwOpt->floatable && !dwOpt->closable) |
|
2298 titleRect.adjust(0, 0, -mw, 0); |
|
2299 } |
|
2300 |
|
2301 if (!verticalTitleBar) |
|
2302 titleRect = visualRect(dwOpt->direction, r, titleRect); |
|
2303 |
|
2304 if (!isFloating) { |
|
2305 QPen oldPen = p->pen(); |
|
2306 QString titleText = p->fontMetrics().elidedText(dwOpt->title, Qt::ElideRight, titleRect.width()); |
|
2307 p->setPen(dwOpt->palette.color(QPalette::Dark)); |
|
2308 p->drawRect(r); |
|
2309 |
|
2310 if (!titleText.isEmpty()) { |
|
2311 drawItemText(p, titleRect, |
|
2312 Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic, dwOpt->palette, |
|
2313 dwOpt->state & State_Enabled, titleText, |
|
2314 QPalette::WindowText); |
|
2315 } |
|
2316 |
|
2317 p->setPen(oldPen); |
|
2318 } else { |
|
2319 name = QLatin1String("WINDOW"); |
|
2320 if (isActive) |
|
2321 stateId = CS_ACTIVE; |
|
2322 else |
|
2323 stateId = CS_INACTIVE; |
|
2324 |
|
2325 int titleHeight = rect.height() - 2; |
|
2326 rect = rect.adjusted(-fw, -fw, fw, 0); |
|
2327 |
|
2328 XPThemeData theme(widget, p, name, 0, stateId); |
|
2329 if (!theme.isValid()) |
|
2330 break; |
|
2331 |
|
2332 // Draw small type title bar |
|
2333 theme.rect = rect; |
|
2334 theme.partId = WP_SMALLCAPTION; |
|
2335 d->drawBackground(theme); |
|
2336 |
|
2337 // Figure out maximal button space on title bar |
|
2338 |
|
2339 QIcon ico = widget->windowIcon(); |
|
2340 bool hasIcon = (ico.cacheKey() != QApplication::windowIcon().cacheKey()); |
|
2341 if (hasIcon) { |
|
2342 QPixmap pxIco = ico.pixmap(titleHeight); |
|
2343 if (!verticalTitleBar && dwOpt->direction == Qt::RightToLeft) |
|
2344 p->drawPixmap(rect.width() - titleHeight - pxIco.width(), rect.bottom() - titleHeight - 2, pxIco); |
|
2345 else |
|
2346 p->drawPixmap(fw, rect.bottom() - titleHeight - 2, pxIco); |
|
2347 } |
|
2348 if (!dwOpt->title.isEmpty()) { |
|
2349 QPen oldPen = p->pen(); |
|
2350 QFont oldFont = p->font(); |
|
2351 QFont titleFont = oldFont; |
|
2352 titleFont.setBold(true); |
|
2353 p->setFont(titleFont); |
|
2354 QString titleText |
|
2355 = p->fontMetrics().elidedText(dwOpt->title, Qt::ElideRight, titleRect.width()); |
|
2356 |
|
2357 int result = TST_NONE; |
|
2358 pGetThemeEnumValue(theme.handle(), WP_SMALLCAPTION, isActive ? CS_ACTIVE : CS_INACTIVE, TMT_TEXTSHADOWTYPE, &result); |
|
2359 if (result != TST_NONE) { |
|
2360 COLORREF textShadowRef; |
|
2361 pGetThemeColor(theme.handle(), WP_SMALLCAPTION, isActive ? CS_ACTIVE : CS_INACTIVE, TMT_TEXTSHADOWCOLOR, &textShadowRef); |
|
2362 QColor textShadow = qRgb(GetRValue(textShadowRef), GetGValue(textShadowRef), GetBValue(textShadowRef)); |
|
2363 p->setPen(textShadow); |
|
2364 drawItemText(p, titleRect.adjusted(1, 1, 1, 1), |
|
2365 Qt::AlignLeft | Qt::AlignBottom, dwOpt->palette, |
|
2366 dwOpt->state & State_Enabled, titleText); |
|
2367 } |
|
2368 |
|
2369 COLORREF captionText = GetSysColor(isActive ? COLOR_CAPTIONTEXT : COLOR_INACTIVECAPTIONTEXT); |
|
2370 QColor textColor = qRgb(GetRValue(captionText), GetGValue(captionText), GetBValue(captionText)); |
|
2371 p->setPen(textColor); |
|
2372 drawItemText(p, titleRect, |
|
2373 Qt::AlignLeft | Qt::AlignBottom, dwOpt->palette, |
|
2374 dwOpt->state & State_Enabled, titleText); |
|
2375 p->setFont(oldFont); |
|
2376 p->setPen(oldPen); |
|
2377 } |
|
2378 |
|
2379 } |
|
2380 |
|
2381 return; |
|
2382 } |
|
2383 break; |
|
2384 #endif // QT_NO_DOCKWIDGET |
|
2385 #ifndef QT_NO_RUBBERBAND |
|
2386 case CE_RubberBand: |
|
2387 if (qstyleoption_cast<const QStyleOptionRubberBand *>(option)) { |
|
2388 QColor highlight = option->palette.color(QPalette::Active, QPalette::Highlight); |
|
2389 p->save(); |
|
2390 QRect r = option->rect; |
|
2391 p->setPen(highlight.darker(120)); |
|
2392 QColor dimHighlight(qMin(highlight.red()/2 + 110, 255), |
|
2393 qMin(highlight.green()/2 + 110, 255), |
|
2394 qMin(highlight.blue()/2 + 110, 255), |
|
2395 (widget && widget->isTopLevel())? 255 : 127); |
|
2396 p->setBrush(dimHighlight); |
|
2397 p->drawRect(option->rect.adjusted(0, 0, -1, -1)); |
|
2398 p->restore(); |
|
2399 return; |
|
2400 } |
|
2401 #endif // QT_NO_RUBBERBAND |
|
2402 case CE_HeaderEmptyArea: |
|
2403 if (option->state & State_Horizontal) |
|
2404 { |
|
2405 name = QLatin1String("HEADER"); |
|
2406 stateId = HIS_NORMAL; |
|
2407 } |
|
2408 else { |
|
2409 QWindowsStyle::drawControl(CE_HeaderEmptyArea, option, p, widget); |
|
2410 return; |
|
2411 } |
|
2412 break; |
|
2413 default: |
|
2414 break; |
|
2415 } |
|
2416 |
|
2417 XPThemeData theme(widget, p, name, partId, stateId, rect); |
|
2418 if (!theme.isValid()) { |
|
2419 QWindowsStyle::drawControl(element, option, p, widget); |
|
2420 return; |
|
2421 } |
|
2422 |
|
2423 theme.rotate = rotate; |
|
2424 theme.mirrorHorizontally = hMirrored; |
|
2425 theme.mirrorVertically = vMirrored; |
|
2426 d->drawBackground(theme); |
|
2427 } |
|
2428 |
|
2429 |
|
2430 /*! |
|
2431 \reimp |
|
2432 */ |
|
2433 void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex *option, |
|
2434 QPainter *p, const QWidget *widget) const |
|
2435 { |
|
2436 QWindowsXPStylePrivate *d = const_cast<QWindowsXPStylePrivate*>(d_func()); |
|
2437 |
|
2438 if (!QWindowsXPStylePrivate::useXP()) { |
|
2439 QWindowsStyle::drawComplexControl(cc, option, p, widget); |
|
2440 return; |
|
2441 } |
|
2442 |
|
2443 State flags = option->state; |
|
2444 SubControls sub = option->subControls; |
|
2445 QRect r = option->rect; |
|
2446 |
|
2447 int partId = 0; |
|
2448 int stateId = 0; |
|
2449 if (widget && widget->testAttribute(Qt::WA_UnderMouse) && widget->isActiveWindow()) |
|
2450 flags |= State_MouseOver; |
|
2451 |
|
2452 switch (cc) { |
|
2453 #ifndef QT_NO_SPINBOX |
|
2454 case CC_SpinBox: |
|
2455 if (const QStyleOptionSpinBox *sb = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) |
|
2456 { |
|
2457 XPThemeData theme(widget, p, QLatin1String("SPIN")); |
|
2458 |
|
2459 if (sb->frame && (sub & SC_SpinBoxFrame)) { |
|
2460 partId = EP_EDITTEXT; |
|
2461 if (!(flags & State_Enabled)) |
|
2462 stateId = ETS_DISABLED; |
|
2463 else if (flags & State_HasFocus) |
|
2464 stateId = ETS_FOCUSED; |
|
2465 else |
|
2466 stateId = ETS_NORMAL; |
|
2467 |
|
2468 XPThemeData ftheme(widget, p, QLatin1String("EDIT"), partId, stateId, r); |
|
2469 ftheme.noContent = true; |
|
2470 d->drawBackground(ftheme); |
|
2471 } |
|
2472 if (sub & SC_SpinBoxUp) { |
|
2473 theme.rect = proxy()->subControlRect(CC_SpinBox, option, SC_SpinBoxUp, widget); |
|
2474 partId = SPNP_UP; |
|
2475 if (!(sb->stepEnabled & QAbstractSpinBox::StepUpEnabled) || !(flags & State_Enabled)) |
|
2476 stateId = UPS_DISABLED; |
|
2477 else if (sb->activeSubControls == SC_SpinBoxUp && (sb->state & State_Sunken)) |
|
2478 stateId = UPS_PRESSED; |
|
2479 else if (sb->activeSubControls == SC_SpinBoxUp && (sb->state & State_MouseOver)) |
|
2480 stateId = UPS_HOT; |
|
2481 else |
|
2482 stateId = UPS_NORMAL; |
|
2483 theme.partId = partId; |
|
2484 theme.stateId = stateId; |
|
2485 d->drawBackground(theme); |
|
2486 } |
|
2487 if (sub & SC_SpinBoxDown) { |
|
2488 theme.rect = proxy()->subControlRect(CC_SpinBox, option, SC_SpinBoxDown, widget); |
|
2489 partId = SPNP_DOWN; |
|
2490 if (!(sb->stepEnabled & QAbstractSpinBox::StepDownEnabled) || !(flags & State_Enabled)) |
|
2491 stateId = DNS_DISABLED; |
|
2492 else if (sb->activeSubControls == SC_SpinBoxDown && (sb->state & State_Sunken)) |
|
2493 stateId = DNS_PRESSED; |
|
2494 else if (sb->activeSubControls == SC_SpinBoxDown && (sb->state & State_MouseOver)) |
|
2495 stateId = DNS_HOT; |
|
2496 else |
|
2497 stateId = DNS_NORMAL; |
|
2498 theme.partId = partId; |
|
2499 theme.stateId = stateId; |
|
2500 d->drawBackground(theme); |
|
2501 } |
|
2502 } |
|
2503 break; |
|
2504 #endif // QT_NO_SPINBOX |
|
2505 #ifndef QT_NO_COMBOBOX |
|
2506 case CC_ComboBox: |
|
2507 if (const QStyleOptionComboBox *cmb = qstyleoption_cast<const QStyleOptionComboBox *>(option)) |
|
2508 { |
|
2509 if (sub & SC_ComboBoxEditField) { |
|
2510 if (cmb->frame) { |
|
2511 partId = EP_EDITTEXT; |
|
2512 if (!(flags & State_Enabled)) |
|
2513 stateId = ETS_DISABLED; |
|
2514 else if (flags & State_HasFocus) |
|
2515 stateId = ETS_FOCUSED; |
|
2516 else |
|
2517 stateId = ETS_NORMAL; |
|
2518 XPThemeData theme(widget, p, QLatin1String("EDIT"), partId, stateId, r); |
|
2519 d->drawBackground(theme); |
|
2520 } else { |
|
2521 QBrush editBrush = cmb->palette.brush(QPalette::Base); |
|
2522 p->fillRect(option->rect, editBrush); |
|
2523 } |
|
2524 if (!cmb->editable) { |
|
2525 QRect re = proxy()->subControlRect(CC_ComboBox, option, SC_ComboBoxEditField, widget); |
|
2526 if (option->state & State_HasFocus) { |
|
2527 p->fillRect(re, option->palette.highlight()); |
|
2528 p->setPen(option->palette.highlightedText().color()); |
|
2529 p->setBackground(option->palette.highlight()); |
|
2530 } else { |
|
2531 p->fillRect(re, option->palette.base()); |
|
2532 p->setPen(option->palette.text().color()); |
|
2533 p->setBackground(option->palette.base()); |
|
2534 } |
|
2535 } |
|
2536 } |
|
2537 |
|
2538 if (sub & SC_ComboBoxArrow) { |
|
2539 XPThemeData theme(widget, p, QLatin1String("COMBOBOX")); |
|
2540 theme.rect = proxy()->subControlRect(CC_ComboBox, option, SC_ComboBoxArrow, widget); |
|
2541 partId = CP_DROPDOWNBUTTON; |
|
2542 if (!(flags & State_Enabled)) |
|
2543 stateId = CBXS_DISABLED; |
|
2544 else if (cmb->activeSubControls == SC_ComboBoxArrow && (cmb->state & State_Sunken)) |
|
2545 stateId = CBXS_PRESSED; |
|
2546 else if (cmb->activeSubControls == SC_ComboBoxArrow && (cmb->state & State_MouseOver)) |
|
2547 stateId = CBXS_HOT; |
|
2548 else |
|
2549 stateId = CBXS_NORMAL; |
|
2550 theme.partId = partId; |
|
2551 theme.stateId = stateId; |
|
2552 d->drawBackground(theme); |
|
2553 } |
|
2554 } |
|
2555 break; |
|
2556 #endif // QT_NO_COMBOBOX |
|
2557 case CC_ScrollBar: |
|
2558 if (const QStyleOptionSlider *scrollbar = qstyleoption_cast<const QStyleOptionSlider *>(option)) |
|
2559 { |
|
2560 XPThemeData theme(widget, p, QLatin1String("SCROLLBAR")); |
|
2561 bool maxedOut = (scrollbar->maximum == scrollbar->minimum); |
|
2562 if (maxedOut) |
|
2563 flags &= ~State_Enabled; |
|
2564 |
|
2565 bool isHorz = flags & State_Horizontal; |
|
2566 bool isRTL = option->direction == Qt::RightToLeft; |
|
2567 if (sub & SC_ScrollBarAddLine) { |
|
2568 theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarAddLine, widget); |
|
2569 partId = SBP_ARROWBTN; |
|
2570 if (!(flags & State_Enabled)) |
|
2571 stateId = (isHorz ? (isRTL ? ABS_LEFTDISABLED : ABS_RIGHTDISABLED) : ABS_DOWNDISABLED); |
|
2572 else if (scrollbar->activeSubControls & SC_ScrollBarAddLine && (scrollbar->state & State_Sunken)) |
|
2573 stateId = (isHorz ? (isRTL ? ABS_LEFTPRESSED : ABS_RIGHTPRESSED) : ABS_DOWNPRESSED); |
|
2574 else if (scrollbar->activeSubControls & SC_ScrollBarAddLine && (scrollbar->state & State_MouseOver)) |
|
2575 stateId = (isHorz ? (isRTL ? ABS_LEFTHOT : ABS_RIGHTHOT) : ABS_DOWNHOT); |
|
2576 else |
|
2577 stateId = (isHorz ? (isRTL ? ABS_LEFTNORMAL : ABS_RIGHTNORMAL) : ABS_DOWNNORMAL); |
|
2578 theme.partId = partId; |
|
2579 theme.stateId = stateId; |
|
2580 d->drawBackground(theme); |
|
2581 } |
|
2582 if (sub & SC_ScrollBarSubLine) { |
|
2583 theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSubLine, widget); |
|
2584 partId = SBP_ARROWBTN; |
|
2585 if (!(flags & State_Enabled)) |
|
2586 stateId = (isHorz ? (isRTL ? ABS_RIGHTDISABLED : ABS_LEFTDISABLED) : ABS_UPDISABLED); |
|
2587 else if (scrollbar->activeSubControls & SC_ScrollBarSubLine && (scrollbar->state & State_Sunken)) |
|
2588 stateId = (isHorz ? (isRTL ? ABS_RIGHTPRESSED : ABS_LEFTPRESSED) : ABS_UPPRESSED); |
|
2589 else if (scrollbar->activeSubControls & SC_ScrollBarSubLine && (scrollbar->state & State_MouseOver)) |
|
2590 stateId = (isHorz ? (isRTL ? ABS_RIGHTHOT : ABS_LEFTHOT) : ABS_UPHOT); |
|
2591 else |
|
2592 stateId = (isHorz ? (isRTL ? ABS_RIGHTNORMAL : ABS_LEFTNORMAL) : ABS_UPNORMAL); |
|
2593 theme.partId = partId; |
|
2594 theme.stateId = stateId; |
|
2595 d->drawBackground(theme); |
|
2596 } |
|
2597 if (maxedOut) { |
|
2598 theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget); |
|
2599 theme.rect = theme.rect.united(proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSubPage, widget)); |
|
2600 theme.rect = theme.rect.united(proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarAddPage, widget)); |
|
2601 partId = scrollbar->orientation == Qt::Horizontal ? SBP_LOWERTRACKHORZ : SBP_LOWERTRACKVERT; |
|
2602 stateId = SCRBS_DISABLED; |
|
2603 theme.partId = partId; |
|
2604 theme.stateId = stateId; |
|
2605 d->drawBackground(theme); |
|
2606 } else { |
|
2607 if (sub & SC_ScrollBarSubPage) { |
|
2608 theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSubPage, widget); |
|
2609 partId = flags & State_Horizontal ? SBP_UPPERTRACKHORZ : SBP_UPPERTRACKVERT; |
|
2610 if (!(flags & State_Enabled)) |
|
2611 stateId = SCRBS_DISABLED; |
|
2612 else if (scrollbar->activeSubControls & SC_ScrollBarSubPage && (scrollbar->state & State_Sunken)) |
|
2613 stateId = SCRBS_PRESSED; |
|
2614 else if (scrollbar->activeSubControls & SC_ScrollBarSubPage && (scrollbar->state & State_MouseOver)) |
|
2615 stateId = SCRBS_HOT; |
|
2616 else |
|
2617 stateId = SCRBS_NORMAL; |
|
2618 theme.partId = partId; |
|
2619 theme.stateId = stateId; |
|
2620 d->drawBackground(theme); |
|
2621 } |
|
2622 if (sub & SC_ScrollBarAddPage) { |
|
2623 theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarAddPage, widget); |
|
2624 partId = flags & State_Horizontal ? SBP_LOWERTRACKHORZ : SBP_LOWERTRACKVERT; |
|
2625 if (!(flags & State_Enabled)) |
|
2626 stateId = SCRBS_DISABLED; |
|
2627 else if (scrollbar->activeSubControls & SC_ScrollBarAddPage && (scrollbar->state & State_Sunken)) |
|
2628 stateId = SCRBS_PRESSED; |
|
2629 else if (scrollbar->activeSubControls & SC_ScrollBarAddPage && (scrollbar->state & State_MouseOver)) |
|
2630 stateId = SCRBS_HOT; |
|
2631 else |
|
2632 stateId = SCRBS_NORMAL; |
|
2633 theme.partId = partId; |
|
2634 theme.stateId = stateId; |
|
2635 d->drawBackground(theme); |
|
2636 } |
|
2637 if (sub & SC_ScrollBarSlider) { |
|
2638 theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget); |
|
2639 if (!(flags & State_Enabled)) |
|
2640 stateId = SCRBS_DISABLED; |
|
2641 else if (scrollbar->activeSubControls & SC_ScrollBarSlider && (scrollbar->state & State_Sunken)) |
|
2642 stateId = SCRBS_PRESSED; |
|
2643 else if (scrollbar->activeSubControls & SC_ScrollBarSlider && (scrollbar->state & State_MouseOver)) |
|
2644 stateId = SCRBS_HOT; |
|
2645 else |
|
2646 stateId = SCRBS_NORMAL; |
|
2647 |
|
2648 // Draw handle |
|
2649 theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget); |
|
2650 theme.partId = flags & State_Horizontal ? SBP_THUMBBTNHORZ : SBP_THUMBBTNVERT; |
|
2651 theme.stateId = stateId; |
|
2652 d->drawBackground(theme); |
|
2653 |
|
2654 // Calculate rect of gripper |
|
2655 const int swidth = theme.rect.width(); |
|
2656 const int sheight = theme.rect.height(); |
|
2657 |
|
2658 MARGINS contentsMargin; |
|
2659 RECT rect = theme.toRECT(theme.rect); |
|
2660 pGetThemeMargins(theme.handle(), 0, theme.partId, theme.stateId, TMT_SIZINGMARGINS, &rect, &contentsMargin); |
|
2661 |
|
2662 SIZE size; |
|
2663 theme.partId = flags & State_Horizontal ? SBP_GRIPPERHORZ : SBP_GRIPPERVERT; |
|
2664 pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); |
|
2665 int gw = size.cx, gh = size.cy; |
|
2666 |
|
2667 |
|
2668 QRect gripperBounds; |
|
2669 if (flags & State_Horizontal && ((swidth - contentsMargin.cxLeftWidth - contentsMargin.cxRightWidth) > gw)) { |
|
2670 gripperBounds.setLeft(theme.rect.left() + swidth/2 - gw/2); |
|
2671 gripperBounds.setTop(theme.rect.top() + sheight/2 - gh/2); |
|
2672 gripperBounds.setWidth(gw); |
|
2673 gripperBounds.setHeight(gh); |
|
2674 } else if ((sheight - contentsMargin.cyTopHeight - contentsMargin.cyBottomHeight) > gh) { |
|
2675 gripperBounds.setLeft(theme.rect.left() + swidth/2 - gw/2); |
|
2676 gripperBounds.setTop(theme.rect.top() + sheight/2 - gh/2); |
|
2677 gripperBounds.setWidth(gw); |
|
2678 gripperBounds.setHeight(gh); |
|
2679 } |
|
2680 |
|
2681 // Draw gripper if there is enough space |
|
2682 if (!gripperBounds.isEmpty()) { |
|
2683 p->save(); |
|
2684 theme.rect = gripperBounds; |
|
2685 p->setClipRegion(d->region(theme));// Only change inside the region of the gripper |
|
2686 d->drawBackground(theme); // Transparent gripper ontop of background |
|
2687 p->restore(); |
|
2688 } |
|
2689 } |
|
2690 } |
|
2691 } |
|
2692 break; |
|
2693 |
|
2694 #ifndef QT_NO_SLIDER |
|
2695 case CC_Slider: |
|
2696 if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(option)) |
|
2697 { |
|
2698 XPThemeData theme(widget, p, QLatin1String("TRACKBAR")); |
|
2699 QRect slrect = slider->rect; |
|
2700 QRegion tickreg = slrect; |
|
2701 if (sub & SC_SliderGroove) { |
|
2702 theme.rect = proxy()->subControlRect(CC_Slider, option, SC_SliderGroove, widget); |
|
2703 if (slider->orientation == Qt::Horizontal) { |
|
2704 partId = TKP_TRACK; |
|
2705 stateId = TRS_NORMAL; |
|
2706 theme.rect = QRect(slrect.left(), theme.rect.center().y() - 2, slrect.width(), 4); |
|
2707 } else { |
|
2708 partId = TKP_TRACKVERT; |
|
2709 stateId = TRVS_NORMAL; |
|
2710 theme.rect = QRect(theme.rect.center().x() - 2, slrect.top(), 4, slrect.height()); |
|
2711 } |
|
2712 theme.partId = partId; |
|
2713 theme.stateId = stateId; |
|
2714 d->drawBackground(theme); |
|
2715 tickreg -= theme.rect; |
|
2716 } |
|
2717 if (sub & SC_SliderTickmarks) { |
|
2718 int tickOffset = proxy()->pixelMetric(PM_SliderTickmarkOffset, slider, widget); |
|
2719 int ticks = slider->tickPosition; |
|
2720 int thickness = proxy()->pixelMetric(PM_SliderControlThickness, slider, widget); |
|
2721 int len = proxy()->pixelMetric(PM_SliderLength, slider, widget); |
|
2722 int available = proxy()->pixelMetric(PM_SliderSpaceAvailable, slider, widget); |
|
2723 int interval = slider->tickInterval; |
|
2724 if (interval <= 0) { |
|
2725 interval = slider->singleStep; |
|
2726 if (QStyle::sliderPositionFromValue(slider->minimum, slider->maximum, interval, |
|
2727 available) |
|
2728 - QStyle::sliderPositionFromValue(slider->minimum, slider->maximum, |
|
2729 0, available) < 3) |
|
2730 interval = slider->pageStep; |
|
2731 } |
|
2732 if (!interval) |
|
2733 interval = 1; |
|
2734 int fudge = len / 2; |
|
2735 int pos; |
|
2736 int bothOffset = (ticks & QSlider::TicksAbove && ticks & QSlider::TicksBelow) ? 1 : 0; |
|
2737 p->setPen(d->sliderTickColor); |
|
2738 QVarLengthArray<QLine, 32> lines; |
|
2739 int v = slider->minimum; |
|
2740 while (v <= slider->maximum + 1) { |
|
2741 if (v == slider->maximum + 1 && interval == 1) |
|
2742 break; |
|
2743 const int v_ = qMin(v, slider->maximum); |
|
2744 int tickLength = (v_ == slider->minimum || v_ >= slider->maximum) ? 4 : 3; |
|
2745 pos = QStyle::sliderPositionFromValue(slider->minimum, slider->maximum, |
|
2746 v_, available) + fudge; |
|
2747 if (slider->orientation == Qt::Horizontal) { |
|
2748 if (ticks & QSlider::TicksAbove) |
|
2749 lines.append(QLine(pos, tickOffset - 1 - bothOffset, |
|
2750 pos, tickOffset - 1 - bothOffset - tickLength)); |
|
2751 |
|
2752 if (ticks & QSlider::TicksBelow) |
|
2753 lines.append(QLine(pos, tickOffset + thickness + bothOffset, |
|
2754 pos, tickOffset + thickness + bothOffset + tickLength)); |
|
2755 } else { |
|
2756 if (ticks & QSlider::TicksAbove) |
|
2757 lines.append(QLine(tickOffset - 1 - bothOffset, pos, |
|
2758 tickOffset - 1 - bothOffset - tickLength, pos)); |
|
2759 |
|
2760 if (ticks & QSlider::TicksBelow) |
|
2761 lines.append(QLine(tickOffset + thickness + bothOffset, pos, |
|
2762 tickOffset + thickness + bothOffset + tickLength, pos)); |
|
2763 } |
|
2764 // in the case where maximum is max int |
|
2765 int nextInterval = v + interval; |
|
2766 if (nextInterval < v) |
|
2767 break; |
|
2768 v = nextInterval; |
|
2769 } |
|
2770 if (lines.size() > 0) { |
|
2771 p->save(); |
|
2772 p->translate(slrect.topLeft()); |
|
2773 p->drawLines(lines.constData(), lines.size()); |
|
2774 p->restore(); |
|
2775 } |
|
2776 } |
|
2777 if (sub & SC_SliderHandle) { |
|
2778 theme.rect = proxy()->subControlRect(CC_Slider, option, SC_SliderHandle, widget); |
|
2779 if (slider->orientation == Qt::Horizontal) { |
|
2780 if (slider->tickPosition == QSlider::TicksAbove) |
|
2781 partId = TKP_THUMBTOP; |
|
2782 else if (slider->tickPosition == QSlider::TicksBelow) |
|
2783 partId = TKP_THUMBBOTTOM; |
|
2784 else |
|
2785 partId = TKP_THUMB; |
|
2786 |
|
2787 if (!(slider->state & State_Enabled)) |
|
2788 stateId = TUS_DISABLED; |
|
2789 else if (slider->activeSubControls & SC_SliderHandle && (slider->state & State_Sunken)) |
|
2790 stateId = TUS_PRESSED; |
|
2791 else if (slider->activeSubControls & SC_SliderHandle && (slider->state & State_MouseOver)) |
|
2792 stateId = TUS_HOT; |
|
2793 else if (flags & State_HasFocus) |
|
2794 stateId = TUS_FOCUSED; |
|
2795 else |
|
2796 stateId = TUS_NORMAL; |
|
2797 } else { |
|
2798 if (slider->tickPosition == QSlider::TicksLeft) |
|
2799 partId = TKP_THUMBLEFT; |
|
2800 else if (slider->tickPosition == QSlider::TicksRight) |
|
2801 partId = TKP_THUMBRIGHT; |
|
2802 else |
|
2803 partId = TKP_THUMBVERT; |
|
2804 |
|
2805 if (!(slider->state & State_Enabled)) |
|
2806 stateId = TUVS_DISABLED; |
|
2807 else if (slider->activeSubControls & SC_SliderHandle && (slider->state & State_Sunken)) |
|
2808 stateId = TUVS_PRESSED; |
|
2809 else if (slider->activeSubControls & SC_SliderHandle && (slider->state & State_MouseOver)) |
|
2810 stateId = TUVS_HOT; |
|
2811 else if (flags & State_HasFocus) |
|
2812 stateId = TUVS_FOCUSED; |
|
2813 else |
|
2814 stateId = TUVS_NORMAL; |
|
2815 } |
|
2816 theme.partId = partId; |
|
2817 theme.stateId = stateId; |
|
2818 d->drawBackground(theme); |
|
2819 } |
|
2820 if (slider->state & State_HasFocus) { |
|
2821 QStyleOptionFocusRect fropt; |
|
2822 fropt.QStyleOption::operator=(*slider); |
|
2823 fropt.rect = subElementRect(SE_SliderFocusRect, slider, widget); |
|
2824 proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, p, widget); |
|
2825 } |
|
2826 } |
|
2827 break; |
|
2828 #endif |
|
2829 #ifndef QT_NO_TOOLBUTTON |
|
2830 case CC_ToolButton: |
|
2831 if (const QStyleOptionToolButton *toolbutton |
|
2832 = qstyleoption_cast<const QStyleOptionToolButton *>(option)) { |
|
2833 QRect button, menuarea; |
|
2834 button = proxy()->subControlRect(cc, toolbutton, SC_ToolButton, widget); |
|
2835 menuarea = proxy()->subControlRect(cc, toolbutton, SC_ToolButtonMenu, widget); |
|
2836 |
|
2837 State bflags = toolbutton->state & ~State_Sunken; |
|
2838 State mflags = bflags; |
|
2839 |
|
2840 if (bflags & State_AutoRaise) { |
|
2841 if (!(bflags & State_MouseOver) || !(bflags & State_Enabled)) { |
|
2842 bflags &= ~State_Raised; |
|
2843 } |
|
2844 } |
|
2845 |
|
2846 if (toolbutton->state & State_Sunken) { |
|
2847 if (toolbutton->activeSubControls & SC_ToolButton) { |
|
2848 bflags |= State_Sunken; |
|
2849 mflags |= State_MouseOver | State_Sunken; |
|
2850 } else if (toolbutton->activeSubControls & SC_ToolButtonMenu) { |
|
2851 mflags |= State_Sunken; |
|
2852 bflags |= State_MouseOver; |
|
2853 } |
|
2854 } |
|
2855 |
|
2856 QStyleOption tool(0); |
|
2857 tool.palette = toolbutton->palette; |
|
2858 if (toolbutton->subControls & SC_ToolButton) { |
|
2859 if (flags & (State_Sunken | State_On | State_Raised) || !(flags & State_AutoRaise)) { |
|
2860 if (toolbutton->features & QStyleOptionToolButton::MenuButtonPopup) { |
|
2861 XPThemeData theme(widget, p, QLatin1String("TOOLBAR")); |
|
2862 theme.partId = TP_SPLITBUTTON; |
|
2863 theme.rect = button; |
|
2864 if (!(bflags & State_Enabled)) |
|
2865 stateId = TS_DISABLED; |
|
2866 else if (bflags & State_Sunken) |
|
2867 stateId = TS_PRESSED; |
|
2868 else if (bflags & State_MouseOver || !(flags & State_AutoRaise)) |
|
2869 stateId = flags & State_On ? TS_HOTCHECKED : TS_HOT; |
|
2870 else if (bflags & State_On) |
|
2871 stateId = TS_CHECKED; |
|
2872 else |
|
2873 stateId = TS_NORMAL; |
|
2874 if (option->direction == Qt::RightToLeft) |
|
2875 theme.mirrorHorizontally = true; |
|
2876 theme.stateId = stateId; |
|
2877 d->drawBackground(theme); |
|
2878 } else { |
|
2879 tool.rect = button; |
|
2880 tool.state = bflags; |
|
2881 if (widget && !qobject_cast<QToolBar*>(widget->parentWidget()) |
|
2882 && !(bflags & State_AutoRaise)) |
|
2883 proxy()->drawPrimitive(PE_PanelButtonBevel, &tool, p, widget); |
|
2884 else |
|
2885 proxy()->drawPrimitive(PE_PanelButtonTool, &tool, p, widget); |
|
2886 } |
|
2887 } |
|
2888 } |
|
2889 |
|
2890 if (toolbutton->state & State_HasFocus) { |
|
2891 QStyleOptionFocusRect fr; |
|
2892 fr.QStyleOption::operator=(*toolbutton); |
|
2893 fr.rect.adjust(3, 3, -3, -3); |
|
2894 if (toolbutton->features & QStyleOptionToolButton::MenuButtonPopup) |
|
2895 fr.rect.adjust(0, 0, -proxy()->pixelMetric(QStyle::PM_MenuButtonIndicator, |
|
2896 toolbutton, widget), 0); |
|
2897 proxy()->drawPrimitive(PE_FrameFocusRect, &fr, p, widget); |
|
2898 } |
|
2899 QStyleOptionToolButton label = *toolbutton; |
|
2900 label.state = bflags; |
|
2901 int fw = 2; |
|
2902 label.rect = button.adjusted(fw, fw, -fw, -fw); |
|
2903 proxy()->drawControl(CE_ToolButtonLabel, &label, p, widget); |
|
2904 |
|
2905 if (toolbutton->subControls & SC_ToolButtonMenu) { |
|
2906 tool.rect = menuarea; |
|
2907 tool.state = mflags; |
|
2908 proxy()->drawPrimitive(PE_IndicatorButtonDropDown, &tool, p, widget); |
|
2909 } else if (toolbutton->features & QStyleOptionToolButton::HasMenu) { |
|
2910 int mbi = proxy()->pixelMetric(PM_MenuButtonIndicator, toolbutton, widget); |
|
2911 QRect ir = toolbutton->rect; |
|
2912 QStyleOptionToolButton newBtn = *toolbutton; |
|
2913 newBtn.rect = QRect(ir.right() + 4 - mbi, ir.height() - mbi + 4, mbi - 5, mbi - 5); |
|
2914 proxy()->drawPrimitive(PE_IndicatorArrowDown, &newBtn, p, widget); |
|
2915 } |
|
2916 } |
|
2917 break; |
|
2918 #endif // QT_NO_TOOLBUTTON |
|
2919 |
|
2920 case CC_TitleBar: |
|
2921 { |
|
2922 if (const QStyleOptionTitleBar *tb = qstyleoption_cast<const QStyleOptionTitleBar *>(option)) |
|
2923 { |
|
2924 bool isActive = tb->titleBarState & QStyle::State_Active; |
|
2925 XPThemeData theme(widget, p, QLatin1String("WINDOW")); |
|
2926 if (sub & SC_TitleBarLabel) { |
|
2927 |
|
2928 #ifdef QT3_SUPPORT |
|
2929 if (widget && widget->inherits("Q3DockWindowTitleBar")) { |
|
2930 partId = WP_SMALLCAPTION; |
|
2931 } else |
|
2932 #endif |
|
2933 partId = (tb->titleBarState & Qt::WindowMinimized) ? WP_MINCAPTION : WP_CAPTION; |
|
2934 theme.rect = option->rect; |
|
2935 if (widget && !widget->isEnabled()) |
|
2936 stateId = CS_DISABLED; |
|
2937 else if (isActive) |
|
2938 stateId = CS_ACTIVE; |
|
2939 else |
|
2940 stateId = CS_INACTIVE; |
|
2941 |
|
2942 theme.partId = partId; |
|
2943 theme.stateId = stateId; |
|
2944 d->drawBackground(theme); |
|
2945 |
|
2946 QRect ir = proxy()->subControlRect(CC_TitleBar, tb, SC_TitleBarLabel, widget); |
|
2947 |
|
2948 int result = TST_NONE; |
|
2949 pGetThemeEnumValue(theme.handle(), WP_CAPTION, isActive ? CS_ACTIVE : CS_INACTIVE, TMT_TEXTSHADOWTYPE, &result); |
|
2950 if (result != TST_NONE) { |
|
2951 COLORREF textShadowRef; |
|
2952 pGetThemeColor(theme.handle(), WP_CAPTION, isActive ? CS_ACTIVE : CS_INACTIVE, TMT_TEXTSHADOWCOLOR, &textShadowRef); |
|
2953 QColor textShadow = qRgb(GetRValue(textShadowRef), GetGValue(textShadowRef), GetBValue(textShadowRef)); |
|
2954 p->setPen(textShadow); |
|
2955 p->drawText(ir.x() + 3, ir.y() + 2, ir.width() - 1, ir.height(), |
|
2956 Qt::AlignLeft | Qt::AlignVCenter | Qt::TextSingleLine, tb->text); |
|
2957 } |
|
2958 COLORREF captionText = GetSysColor(isActive ? COLOR_CAPTIONTEXT : COLOR_INACTIVECAPTIONTEXT); |
|
2959 QColor textColor = qRgb(GetRValue(captionText), GetGValue(captionText), GetBValue(captionText)); |
|
2960 p->setPen(textColor); |
|
2961 p->drawText(ir.x() + 2, ir.y() + 1, ir.width() - 2, ir.height(), |
|
2962 Qt::AlignLeft | Qt::AlignVCenter | Qt::TextSingleLine, tb->text); |
|
2963 } |
|
2964 if (sub & SC_TitleBarSysMenu && tb->titleBarFlags & Qt::WindowSystemMenuHint) { |
|
2965 theme.rect = proxy()->subControlRect(CC_TitleBar, option, SC_TitleBarSysMenu, widget); |
|
2966 partId = WP_SYSBUTTON; |
|
2967 if ((widget && !widget->isEnabled()) || !isActive) |
|
2968 stateId = SBS_DISABLED; |
|
2969 else if (option->activeSubControls == SC_TitleBarSysMenu && (option->state & State_Sunken)) |
|
2970 stateId = SBS_PUSHED; |
|
2971 else if (option->activeSubControls == SC_TitleBarSysMenu && (option->state & State_MouseOver)) |
|
2972 stateId = SBS_HOT; |
|
2973 else |
|
2974 stateId = SBS_NORMAL; |
|
2975 if (!tb->icon.isNull()) { |
|
2976 tb->icon.paint(p, theme.rect); |
|
2977 } else { |
|
2978 theme.partId = partId; |
|
2979 theme.stateId = stateId; |
|
2980 SIZE sz; |
|
2981 pGetThemePartSize(theme.handle(), qt_win_display_dc(), theme.partId, theme.stateId, 0, TS_TRUE, &sz); |
|
2982 if (sz.cx == 0 || sz.cy == 0) { |
|
2983 int iconSize = proxy()->pixelMetric(PM_SmallIconSize, tb, widget); |
|
2984 QPixmap pm = proxy()->standardIcon(SP_TitleBarMenuButton, tb, widget).pixmap(iconSize, iconSize); |
|
2985 p->save(); |
|
2986 drawItemPixmap(p, theme.rect, Qt::AlignCenter, pm); |
|
2987 p->restore(); |
|
2988 } else { |
|
2989 d->drawBackground(theme); |
|
2990 } |
|
2991 } |
|
2992 } |
|
2993 |
|
2994 if (sub & SC_TitleBarMinButton && tb->titleBarFlags & Qt::WindowMinimizeButtonHint |
|
2995 && !(tb->titleBarState & Qt::WindowMinimized)) { |
|
2996 theme.rect = proxy()->subControlRect(CC_TitleBar, option, SC_TitleBarMinButton, widget); |
|
2997 partId = WP_MINBUTTON; |
|
2998 if (widget && !widget->isEnabled()) |
|
2999 stateId = MINBS_DISABLED; |
|
3000 else if (option->activeSubControls == SC_TitleBarMinButton && (option->state & State_Sunken)) |
|
3001 stateId = MINBS_PUSHED; |
|
3002 else if (option->activeSubControls == SC_TitleBarMinButton && (option->state & State_MouseOver)) |
|
3003 stateId = MINBS_HOT; |
|
3004 else if (!isActive) |
|
3005 stateId = MINBS_INACTIVE; |
|
3006 else |
|
3007 stateId = MINBS_NORMAL; |
|
3008 theme.partId = partId; |
|
3009 theme.stateId = stateId; |
|
3010 d->drawBackground(theme); |
|
3011 } |
|
3012 if (sub & SC_TitleBarMaxButton && tb->titleBarFlags & Qt::WindowMaximizeButtonHint |
|
3013 && !(tb->titleBarState & Qt::WindowMaximized)) { |
|
3014 theme.rect = proxy()->subControlRect(CC_TitleBar, option, SC_TitleBarMaxButton, widget); |
|
3015 partId = WP_MAXBUTTON; |
|
3016 if (widget && !widget->isEnabled()) |
|
3017 stateId = MAXBS_DISABLED; |
|
3018 else if (option->activeSubControls == SC_TitleBarMaxButton && (option->state & State_Sunken)) |
|
3019 stateId = MAXBS_PUSHED; |
|
3020 else if (option->activeSubControls == SC_TitleBarMaxButton && (option->state & State_MouseOver)) |
|
3021 stateId = MAXBS_HOT; |
|
3022 else if (!isActive) |
|
3023 stateId = MAXBS_INACTIVE; |
|
3024 else |
|
3025 stateId = MAXBS_NORMAL; |
|
3026 theme.partId = partId; |
|
3027 theme.stateId = stateId; |
|
3028 d->drawBackground(theme); |
|
3029 } |
|
3030 if (sub & SC_TitleBarContextHelpButton |
|
3031 && tb->titleBarFlags & Qt::WindowContextHelpButtonHint) { |
|
3032 theme.rect = proxy()->subControlRect(CC_TitleBar, option, SC_TitleBarContextHelpButton, widget); |
|
3033 partId = WP_HELPBUTTON; |
|
3034 if (widget && !widget->isEnabled()) |
|
3035 stateId = MINBS_DISABLED; |
|
3036 else if (option->activeSubControls == SC_TitleBarContextHelpButton && (option->state & State_Sunken)) |
|
3037 stateId = MINBS_PUSHED; |
|
3038 else if (option->activeSubControls == SC_TitleBarContextHelpButton && (option->state & State_MouseOver)) |
|
3039 stateId = MINBS_HOT; |
|
3040 else if (!isActive) |
|
3041 stateId = MINBS_INACTIVE; |
|
3042 else |
|
3043 stateId = MINBS_NORMAL; |
|
3044 theme.partId = partId; |
|
3045 theme.stateId = stateId; |
|
3046 d->drawBackground(theme); |
|
3047 } |
|
3048 bool drawNormalButton = (sub & SC_TitleBarNormalButton) |
|
3049 && (((tb->titleBarFlags & Qt::WindowMinimizeButtonHint) |
|
3050 && (tb->titleBarState & Qt::WindowMinimized)) |
|
3051 || ((tb->titleBarFlags & Qt::WindowMaximizeButtonHint) |
|
3052 && (tb->titleBarState & Qt::WindowMaximized))); |
|
3053 if (drawNormalButton) { |
|
3054 theme.rect = proxy()->subControlRect(CC_TitleBar, option, SC_TitleBarNormalButton, widget); |
|
3055 partId = WP_RESTOREBUTTON; |
|
3056 if (widget && !widget->isEnabled()) |
|
3057 stateId = RBS_DISABLED; |
|
3058 else if (option->activeSubControls == SC_TitleBarNormalButton && (option->state & State_Sunken)) |
|
3059 stateId = RBS_PUSHED; |
|
3060 else if (option->activeSubControls == SC_TitleBarNormalButton && (option->state & State_MouseOver)) |
|
3061 stateId = RBS_HOT; |
|
3062 else if (!isActive) |
|
3063 stateId = RBS_INACTIVE; |
|
3064 else |
|
3065 stateId = RBS_NORMAL; |
|
3066 theme.partId = partId; |
|
3067 theme.stateId = stateId; |
|
3068 d->drawBackground(theme); |
|
3069 } |
|
3070 if (sub & SC_TitleBarShadeButton && tb->titleBarFlags & Qt::WindowShadeButtonHint |
|
3071 && !(tb->titleBarState & Qt::WindowMinimized)) { |
|
3072 theme.rect = proxy()->subControlRect(CC_TitleBar, option, SC_TitleBarShadeButton, widget); |
|
3073 partId = WP_MINBUTTON; |
|
3074 if (widget && !widget->isEnabled()) |
|
3075 stateId = MINBS_DISABLED; |
|
3076 else if (option->activeSubControls == SC_TitleBarShadeButton && (option->state & State_Sunken)) |
|
3077 stateId = MINBS_PUSHED; |
|
3078 else if (option->activeSubControls == SC_TitleBarShadeButton && (option->state & State_MouseOver)) |
|
3079 stateId = MINBS_HOT; |
|
3080 else if (!isActive) |
|
3081 stateId = MINBS_INACTIVE; |
|
3082 else |
|
3083 stateId = MINBS_NORMAL; |
|
3084 theme.partId = partId; |
|
3085 theme.stateId = stateId; |
|
3086 d->drawBackground(theme); |
|
3087 } |
|
3088 if (sub & SC_TitleBarUnshadeButton && tb->titleBarFlags & Qt::WindowShadeButtonHint |
|
3089 && tb->titleBarState & Qt::WindowMinimized) { |
|
3090 theme.rect = proxy()->subControlRect(CC_TitleBar, option, SC_TitleBarUnshadeButton, widget); |
|
3091 partId = WP_RESTOREBUTTON; |
|
3092 if (widget && !widget->isEnabled()) |
|
3093 stateId = RBS_DISABLED; |
|
3094 else if (option->activeSubControls == SC_TitleBarUnshadeButton && (option->state & State_Sunken)) |
|
3095 stateId = RBS_PUSHED; |
|
3096 else if (option->activeSubControls == SC_TitleBarUnshadeButton && (option->state & State_MouseOver)) |
|
3097 stateId = RBS_HOT; |
|
3098 else if (!isActive) |
|
3099 stateId = RBS_INACTIVE; |
|
3100 else |
|
3101 stateId = RBS_NORMAL; |
|
3102 theme.partId = partId; |
|
3103 theme.stateId = stateId; |
|
3104 d->drawBackground(theme); |
|
3105 } |
|
3106 if (sub & SC_TitleBarCloseButton && tb->titleBarFlags & Qt::WindowSystemMenuHint) { |
|
3107 theme.rect = proxy()->subControlRect(CC_TitleBar, option, SC_TitleBarCloseButton, widget); |
|
3108 //partId = titlebar->testWFlags(Qt::WA_WState_Tool) ? WP_SMALLCLOSEBUTTON : WP_CLOSEBUTTON; |
|
3109 partId = WP_CLOSEBUTTON; |
|
3110 if (widget && !widget->isEnabled()) |
|
3111 stateId = CBS_DISABLED; |
|
3112 else if (option->activeSubControls == SC_TitleBarCloseButton && (option->state & State_Sunken)) |
|
3113 stateId = CBS_PUSHED; |
|
3114 else if (option->activeSubControls == SC_TitleBarCloseButton && (option->state & State_MouseOver)) |
|
3115 stateId = CBS_HOT; |
|
3116 else if (!isActive) |
|
3117 stateId = CBS_INACTIVE; |
|
3118 else |
|
3119 stateId = CBS_NORMAL; |
|
3120 theme.partId = partId; |
|
3121 theme.stateId = stateId; |
|
3122 d->drawBackground(theme); |
|
3123 } |
|
3124 } |
|
3125 } |
|
3126 break; |
|
3127 |
|
3128 #ifndef QT_NO_WORKSPACE |
|
3129 case CC_MdiControls: |
|
3130 { |
|
3131 QRect buttonRect; |
|
3132 XPThemeData theme(widget, p, QLatin1String("WINDOW"), WP_MDICLOSEBUTTON, CBS_NORMAL); |
|
3133 |
|
3134 if (option->subControls & SC_MdiCloseButton) { |
|
3135 buttonRect = proxy()->subControlRect(CC_MdiControls, option, SC_MdiCloseButton, widget); |
|
3136 if (theme.isValid()) { |
|
3137 theme.partId = WP_MDICLOSEBUTTON; |
|
3138 theme.rect = buttonRect; |
|
3139 if (!(flags & State_Enabled)) |
|
3140 theme.stateId = CBS_INACTIVE; |
|
3141 else if (flags & State_Sunken && (option->activeSubControls & SC_MdiCloseButton)) |
|
3142 theme.stateId = CBS_PUSHED; |
|
3143 else if (flags & State_MouseOver && (option->activeSubControls & SC_MdiCloseButton)) |
|
3144 theme.stateId = CBS_HOT; |
|
3145 else |
|
3146 theme.stateId = CBS_NORMAL; |
|
3147 d->drawBackground(theme); |
|
3148 } |
|
3149 } |
|
3150 if (option->subControls & SC_MdiNormalButton) { |
|
3151 buttonRect = proxy()->subControlRect(CC_MdiControls, option, SC_MdiNormalButton, widget); |
|
3152 if (theme.isValid()) { |
|
3153 theme.partId = WP_MDIRESTOREBUTTON; |
|
3154 theme.rect = buttonRect; |
|
3155 if (!(flags & State_Enabled)) |
|
3156 theme.stateId = CBS_INACTIVE; |
|
3157 else if (flags & State_Sunken && (option->activeSubControls & SC_MdiNormalButton)) |
|
3158 theme.stateId = CBS_PUSHED; |
|
3159 else if (flags & State_MouseOver && (option->activeSubControls & SC_MdiNormalButton)) |
|
3160 theme.stateId = CBS_HOT; |
|
3161 else |
|
3162 theme.stateId = CBS_NORMAL; |
|
3163 d->drawBackground(theme); |
|
3164 } |
|
3165 } |
|
3166 if (option->subControls & QStyle::SC_MdiMinButton) { |
|
3167 buttonRect = proxy()->subControlRect(CC_MdiControls, option, SC_MdiMinButton, widget); |
|
3168 if (theme.isValid()) { |
|
3169 theme.partId = WP_MDIMINBUTTON; |
|
3170 theme.rect = buttonRect; |
|
3171 if (!(flags & State_Enabled)) |
|
3172 theme.stateId = CBS_INACTIVE; |
|
3173 else if (flags & State_Sunken && (option->activeSubControls & SC_MdiMinButton)) |
|
3174 theme.stateId = CBS_PUSHED; |
|
3175 else if (flags & State_MouseOver && (option->activeSubControls & SC_MdiMinButton)) |
|
3176 theme.stateId = CBS_HOT; |
|
3177 else |
|
3178 theme.stateId = CBS_NORMAL; |
|
3179 d->drawBackground(theme); |
|
3180 } |
|
3181 } |
|
3182 } |
|
3183 break; |
|
3184 #endif //QT_NO_WORKSPACE |
|
3185 #ifndef QT_NO_DIAL |
|
3186 case CC_Dial: |
|
3187 if (const QStyleOptionSlider *dial = qstyleoption_cast<const QStyleOptionSlider *>(option)) |
|
3188 QStyleHelper::drawDial(dial, p); |
|
3189 break; |
|
3190 #endif // QT_NO_DIAL |
|
3191 default: |
|
3192 QWindowsStyle::drawComplexControl(cc, option, p, widget); |
|
3193 break; |
|
3194 } |
|
3195 } |
|
3196 |
|
3197 /*! \reimp */ |
|
3198 int QWindowsXPStyle::pixelMetric(PixelMetric pm, const QStyleOption *option, const QWidget *widget) const |
|
3199 { |
|
3200 if (!QWindowsXPStylePrivate::useXP()) |
|
3201 return QWindowsStyle::pixelMetric(pm, option, widget); |
|
3202 |
|
3203 int res = 0; |
|
3204 switch (pm) { |
|
3205 case PM_MenuBarPanelWidth: |
|
3206 res = 0; |
|
3207 break; |
|
3208 |
|
3209 case PM_DefaultFrameWidth: |
|
3210 if (qobject_cast<const QListView*>(widget)) |
|
3211 res = 2; |
|
3212 else |
|
3213 res = 1; |
|
3214 break; |
|
3215 case PM_MenuPanelWidth: |
|
3216 case PM_SpinBoxFrameWidth: |
|
3217 res = 1; |
|
3218 break; |
|
3219 |
|
3220 case PM_TabBarTabOverlap: |
|
3221 case PM_MenuHMargin: |
|
3222 case PM_MenuVMargin: |
|
3223 res = 2; |
|
3224 break; |
|
3225 |
|
3226 case PM_TabBarBaseOverlap: |
|
3227 if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(option)) { |
|
3228 switch (tab->shape) { |
|
3229 case QTabBar::RoundedNorth: |
|
3230 case QTabBar::TriangularNorth: |
|
3231 res = 1; |
|
3232 break; |
|
3233 case QTabBar::RoundedSouth: |
|
3234 case QTabBar::TriangularSouth: |
|
3235 res = 2; |
|
3236 break; |
|
3237 case QTabBar::RoundedEast: |
|
3238 case QTabBar::TriangularEast: |
|
3239 res = 3; |
|
3240 break; |
|
3241 case QTabBar::RoundedWest: |
|
3242 case QTabBar::TriangularWest: |
|
3243 res = 1; |
|
3244 break; |
|
3245 } |
|
3246 } |
|
3247 break; |
|
3248 |
|
3249 case PM_SplitterWidth: |
|
3250 res = qMax(int(QStyleHelper::dpiScaled(5.)), QApplication::globalStrut().width()); |
|
3251 break; |
|
3252 |
|
3253 case PM_IndicatorWidth: |
|
3254 case PM_IndicatorHeight: |
|
3255 { |
|
3256 XPThemeData theme(widget, 0, QLatin1String("BUTTON"), BP_CHECKBOX, CBS_UNCHECKEDNORMAL); |
|
3257 if (theme.isValid()) { |
|
3258 SIZE size; |
|
3259 pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); |
|
3260 res = (pm == PM_IndicatorWidth) ? size.cx : size.cy; |
|
3261 } |
|
3262 } |
|
3263 break; |
|
3264 |
|
3265 case PM_ExclusiveIndicatorWidth: |
|
3266 case PM_ExclusiveIndicatorHeight: |
|
3267 { |
|
3268 XPThemeData theme(widget, 0, QLatin1String("BUTTON"), BP_RADIOBUTTON, RBS_UNCHECKEDNORMAL); |
|
3269 if (theme.isValid()) { |
|
3270 SIZE size; |
|
3271 pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); |
|
3272 res = (pm == PM_ExclusiveIndicatorWidth) ? size.cx : size.cy; |
|
3273 } |
|
3274 } |
|
3275 break; |
|
3276 |
|
3277 case PM_ProgressBarChunkWidth: |
|
3278 { |
|
3279 Qt::Orientation orient = Qt::Horizontal; |
|
3280 if (const QStyleOptionProgressBarV2 *pb2 = qstyleoption_cast<const QStyleOptionProgressBarV2 *>(option)) |
|
3281 orient = pb2->orientation; |
|
3282 XPThemeData theme(widget, 0, QLatin1String("PROGRESS"), (orient == Qt::Horizontal) ? PP_CHUNK : PP_CHUNKVERT); |
|
3283 if (theme.isValid()) { |
|
3284 SIZE size; |
|
3285 pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); |
|
3286 res = (orient == Qt::Horizontal) ? size.cx : size.cy; |
|
3287 } |
|
3288 } |
|
3289 break; |
|
3290 |
|
3291 case PM_SliderThickness: |
|
3292 { |
|
3293 XPThemeData theme(widget, 0, QLatin1String("TRACKBAR"), TKP_THUMB); |
|
3294 if (theme.isValid()) { |
|
3295 SIZE size; |
|
3296 pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); |
|
3297 res = size.cy; |
|
3298 } |
|
3299 } |
|
3300 break; |
|
3301 |
|
3302 case PM_TitleBarHeight: |
|
3303 { |
|
3304 #ifdef QT3_SUPPORT |
|
3305 if (widget && widget->inherits("Q3DockWindowTitleBar")) { |
|
3306 res = GetSystemMetrics(SM_CYSMCAPTION) + GetSystemMetrics(SM_CXSIZEFRAME); |
|
3307 } else |
|
3308 #endif |
|
3309 if (widget && (widget->windowType() == Qt::Tool)) |
|
3310 res = GetSystemMetrics(SM_CYSMCAPTION) + GetSystemMetrics(SM_CXSIZEFRAME); |
|
3311 else |
|
3312 res = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CXSIZEFRAME); |
|
3313 } |
|
3314 break; |
|
3315 |
|
3316 case PM_MdiSubWindowFrameWidth: |
|
3317 { |
|
3318 XPThemeData theme(widget, 0, QLatin1String("WINDOW"), WP_FRAMELEFT, FS_ACTIVE); |
|
3319 if (theme.isValid()) { |
|
3320 SIZE size; |
|
3321 pGetThemePartSize(theme.handle(), 0, WP_FRAMELEFT, FS_ACTIVE, 0, TS_TRUE, &size); |
|
3322 res = size.cx-1; |
|
3323 } |
|
3324 } |
|
3325 break; |
|
3326 |
|
3327 case PM_MdiSubWindowMinimizedWidth: |
|
3328 res = 160; |
|
3329 break; |
|
3330 |
|
3331 #ifndef QT_NO_TOOLBAR |
|
3332 case PM_ToolBarHandleExtent: |
|
3333 res = int(QStyleHelper::dpiScaled(8.)); |
|
3334 break; |
|
3335 |
|
3336 #endif // QT_NO_TOOLBAR |
|
3337 case PM_DockWidgetFrameWidth: |
|
3338 { |
|
3339 XPThemeData theme(widget, 0, QLatin1String("WINDOW"), WP_SMALLFRAMERIGHT, FS_ACTIVE); |
|
3340 if (theme.isValid()) { |
|
3341 SIZE size; |
|
3342 pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); |
|
3343 res = size.cx; |
|
3344 } |
|
3345 } |
|
3346 break; |
|
3347 case PM_DockWidgetSeparatorExtent: |
|
3348 res = int(QStyleHelper::dpiScaled(4.)); |
|
3349 break; |
|
3350 case PM_DockWidgetTitleMargin: |
|
3351 res = int(QStyleHelper::dpiScaled(4.)); |
|
3352 break; |
|
3353 |
|
3354 case PM_ButtonShiftHorizontal: |
|
3355 case PM_ButtonShiftVertical: |
|
3356 if (qstyleoption_cast<const QStyleOptionToolButton *>(option)) |
|
3357 res = 1; |
|
3358 else |
|
3359 res = 0; |
|
3360 break; |
|
3361 |
|
3362 case PM_ButtonDefaultIndicator: |
|
3363 res = 0; |
|
3364 break; |
|
3365 |
|
3366 default: |
|
3367 res = QWindowsStyle::pixelMetric(pm, option, widget); |
|
3368 } |
|
3369 |
|
3370 return res; |
|
3371 } |
|
3372 |
|
3373 /* |
|
3374 This function is used by subControlRect to check if a button |
|
3375 should be drawn for the given subControl given a set of window flags. |
|
3376 */ |
|
3377 static bool buttonVisible(const QStyle::SubControl sc, const QStyleOptionTitleBar *tb){ |
|
3378 |
|
3379 bool isMinimized = tb->titleBarState & Qt::WindowMinimized; |
|
3380 bool isMaximized = tb->titleBarState & Qt::WindowMaximized; |
|
3381 const uint flags = tb->titleBarFlags; |
|
3382 bool retVal = false; |
|
3383 switch (sc) { |
|
3384 case QStyle::SC_TitleBarContextHelpButton: |
|
3385 if (flags & Qt::WindowContextHelpButtonHint) |
|
3386 retVal = true; |
|
3387 break; |
|
3388 case QStyle::SC_TitleBarMinButton: |
|
3389 if (!isMinimized && (flags & Qt::WindowMinimizeButtonHint)) |
|
3390 retVal = true; |
|
3391 break; |
|
3392 case QStyle::SC_TitleBarNormalButton: |
|
3393 if (isMinimized && (flags & Qt::WindowMinimizeButtonHint)) |
|
3394 retVal = true; |
|
3395 else if (isMaximized && (flags & Qt::WindowMaximizeButtonHint)) |
|
3396 retVal = true; |
|
3397 break; |
|
3398 case QStyle::SC_TitleBarMaxButton: |
|
3399 if (!isMaximized && (flags & Qt::WindowMaximizeButtonHint)) |
|
3400 retVal = true; |
|
3401 break; |
|
3402 case QStyle::SC_TitleBarShadeButton: |
|
3403 if (!isMinimized && flags & Qt::WindowShadeButtonHint) |
|
3404 retVal = true; |
|
3405 break; |
|
3406 case QStyle::SC_TitleBarUnshadeButton: |
|
3407 if (isMinimized && flags & Qt::WindowShadeButtonHint) |
|
3408 retVal = true; |
|
3409 break; |
|
3410 case QStyle::SC_TitleBarCloseButton: |
|
3411 if (flags & Qt::WindowSystemMenuHint) |
|
3412 retVal = true; |
|
3413 break; |
|
3414 case QStyle::SC_TitleBarSysMenu: |
|
3415 if (flags & Qt::WindowSystemMenuHint) |
|
3416 retVal = true; |
|
3417 break; |
|
3418 default : |
|
3419 retVal = true; |
|
3420 } |
|
3421 return retVal; |
|
3422 } |
|
3423 |
|
3424 /*! |
|
3425 \reimp |
|
3426 */ |
|
3427 QRect QWindowsXPStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *option, |
|
3428 SubControl subControl, const QWidget *widget) const |
|
3429 { |
|
3430 if (!QWindowsXPStylePrivate::useXP()) |
|
3431 return QWindowsStyle::subControlRect(cc, option, subControl, widget); |
|
3432 |
|
3433 QRect rect; |
|
3434 |
|
3435 switch (cc) { |
|
3436 case CC_TitleBar: |
|
3437 if (const QStyleOptionTitleBar *tb = qstyleoption_cast<const QStyleOptionTitleBar *>(option)) { |
|
3438 if (!buttonVisible(subControl, tb)) |
|
3439 return rect; |
|
3440 const bool isToolTitle = false; |
|
3441 const int height = tb->rect.height(); |
|
3442 const int width = tb->rect.width(); |
|
3443 int buttonHeight = GetSystemMetrics(SM_CYSIZE) - 4; |
|
3444 int buttonWidth = GetSystemMetrics(SM_CXSIZE) - 4; |
|
3445 const int delta = buttonWidth + 2; |
|
3446 int controlTop = option->rect.bottom() - buttonHeight - 2; |
|
3447 const int frameWidth = proxy()->pixelMetric(PM_MdiSubWindowFrameWidth, option, widget); |
|
3448 const bool sysmenuHint = (tb->titleBarFlags & Qt::WindowSystemMenuHint) != 0; |
|
3449 const bool minimizeHint = (tb->titleBarFlags & Qt::WindowMinimizeButtonHint) != 0; |
|
3450 const bool maximizeHint = (tb->titleBarFlags & Qt::WindowMaximizeButtonHint) != 0; |
|
3451 const bool contextHint = (tb->titleBarFlags & Qt::WindowContextHelpButtonHint) != 0; |
|
3452 const bool shadeHint = (tb->titleBarFlags & Qt::WindowShadeButtonHint) != 0; |
|
3453 bool isMinimized = tb->titleBarState & Qt::WindowMinimized; |
|
3454 bool isMaximized = tb->titleBarState & Qt::WindowMaximized; |
|
3455 int offset = 0; |
|
3456 |
|
3457 switch (subControl) { |
|
3458 case SC_TitleBarLabel: |
|
3459 rect = QRect(frameWidth, 0, width - (buttonWidth + frameWidth + 10), height); |
|
3460 if (isToolTitle) { |
|
3461 if (sysmenuHint) { |
|
3462 rect.adjust(0, 0, -buttonWidth - 3, 0); |
|
3463 } |
|
3464 if (minimizeHint || maximizeHint) |
|
3465 rect.adjust(0, 0, -buttonWidth - 2, 0); |
|
3466 } else { |
|
3467 if (sysmenuHint) { |
|
3468 const int leftOffset = height - 8; |
|
3469 rect.adjust(leftOffset, 0, 0, 0); |
|
3470 } |
|
3471 if (minimizeHint) |
|
3472 rect.adjust(0, 0, -buttonWidth - 2, 0); |
|
3473 if (maximizeHint) |
|
3474 rect.adjust(0, 0, -buttonWidth - 2, 0); |
|
3475 if (contextHint) |
|
3476 rect.adjust(0, 0, -buttonWidth - 2, 0); |
|
3477 if (shadeHint) |
|
3478 rect.adjust(0, 0, -buttonWidth - 2, 0); |
|
3479 } |
|
3480 break; |
|
3481 |
|
3482 case SC_TitleBarContextHelpButton: |
|
3483 if (tb->titleBarFlags & Qt::WindowContextHelpButtonHint) |
|
3484 offset += delta; |
|
3485 //fall through |
|
3486 case SC_TitleBarMinButton: |
|
3487 if (!isMinimized && (tb->titleBarFlags & Qt::WindowMinimizeButtonHint)) |
|
3488 offset += delta; |
|
3489 else if (subControl == SC_TitleBarMinButton) |
|
3490 break; |
|
3491 //fall through |
|
3492 case SC_TitleBarNormalButton: |
|
3493 if (isMinimized && (tb->titleBarFlags & Qt::WindowMinimizeButtonHint)) |
|
3494 offset += delta; |
|
3495 else if (isMaximized && (tb->titleBarFlags & Qt::WindowMaximizeButtonHint)) |
|
3496 offset += delta; |
|
3497 else if (subControl == SC_TitleBarNormalButton) |
|
3498 break; |
|
3499 //fall through |
|
3500 case SC_TitleBarMaxButton: |
|
3501 if (!isMaximized && (tb->titleBarFlags & Qt::WindowMaximizeButtonHint)) |
|
3502 offset += delta; |
|
3503 else if (subControl == SC_TitleBarMaxButton) |
|
3504 break; |
|
3505 //fall through |
|
3506 case SC_TitleBarShadeButton: |
|
3507 if (!isMinimized && (tb->titleBarFlags & Qt::WindowShadeButtonHint)) |
|
3508 offset += delta; |
|
3509 else if (subControl == SC_TitleBarShadeButton) |
|
3510 break; |
|
3511 //fall through |
|
3512 case SC_TitleBarUnshadeButton: |
|
3513 if (isMinimized && (tb->titleBarFlags & Qt::WindowShadeButtonHint)) |
|
3514 offset += delta; |
|
3515 else if (subControl == SC_TitleBarUnshadeButton) |
|
3516 break; |
|
3517 //fall through |
|
3518 case SC_TitleBarCloseButton: |
|
3519 if (tb->titleBarFlags & Qt::WindowSystemMenuHint) |
|
3520 offset += delta; |
|
3521 else if (subControl == SC_TitleBarCloseButton) |
|
3522 break; |
|
3523 |
|
3524 rect.setRect(width - offset - controlTop + 1, controlTop, |
|
3525 buttonWidth, buttonHeight); |
|
3526 break; |
|
3527 |
|
3528 case SC_TitleBarSysMenu: |
|
3529 { |
|
3530 const int controlTop = 6; |
|
3531 const int controlHeight = height - controlTop - 3; |
|
3532 const int iconExtent = proxy()->pixelMetric(PM_SmallIconSize); |
|
3533 QSize iconSize = tb->icon.actualSize(QSize(iconExtent, iconExtent)); |
|
3534 if (tb->icon.isNull()) |
|
3535 iconSize = QSize(controlHeight, controlHeight); |
|
3536 int hPad = (controlHeight - iconSize.height())/2; |
|
3537 int vPad = (controlHeight - iconSize.width())/2; |
|
3538 rect = QRect(frameWidth + hPad, controlTop + vPad, iconSize.width(), iconSize.height()); |
|
3539 } |
|
3540 break; |
|
3541 default: |
|
3542 break; |
|
3543 } |
|
3544 } |
|
3545 break; |
|
3546 |
|
3547 case CC_ComboBox: |
|
3548 if (const QStyleOptionComboBox *cmb = qstyleoption_cast<const QStyleOptionComboBox *>(option)) { |
|
3549 int x = cmb->rect.x(), y = cmb->rect.y(), wi = cmb->rect.width(), he = cmb->rect.height(); |
|
3550 int xpos = x; |
|
3551 xpos += wi - 1 - 16; |
|
3552 |
|
3553 switch (subControl) { |
|
3554 case SC_ComboBoxFrame: |
|
3555 rect = cmb->rect; |
|
3556 break; |
|
3557 |
|
3558 case SC_ComboBoxArrow: |
|
3559 rect = QRect(xpos, y+1, 16, he-2); |
|
3560 break; |
|
3561 |
|
3562 case SC_ComboBoxEditField: |
|
3563 rect = QRect(x+2, y+2, wi-3-16, he-4); |
|
3564 break; |
|
3565 |
|
3566 case SC_ComboBoxListBoxPopup: |
|
3567 rect = cmb->rect; |
|
3568 break; |
|
3569 |
|
3570 default: |
|
3571 break; |
|
3572 } |
|
3573 } |
|
3574 break; |
|
3575 #ifndef QT_NO_WORKSPACE |
|
3576 case CC_MdiControls: |
|
3577 { |
|
3578 int numSubControls = 0; |
|
3579 if (option->subControls & SC_MdiCloseButton) |
|
3580 ++numSubControls; |
|
3581 if (option->subControls & SC_MdiMinButton) |
|
3582 ++numSubControls; |
|
3583 if (option->subControls & SC_MdiNormalButton) |
|
3584 ++numSubControls; |
|
3585 if (numSubControls == 0) |
|
3586 break; |
|
3587 |
|
3588 int buttonWidth = option->rect.width()/ numSubControls; |
|
3589 int offset = 0; |
|
3590 switch (subControl) { |
|
3591 case SC_MdiCloseButton: |
|
3592 // Only one sub control, no offset needed. |
|
3593 if (numSubControls == 1) |
|
3594 break; |
|
3595 offset += buttonWidth; |
|
3596 //FALL THROUGH |
|
3597 case SC_MdiNormalButton: |
|
3598 // No offset needed if |
|
3599 // 1) There's only one sub control |
|
3600 // 2) We have a close button and a normal button (offset already added in SC_MdiClose) |
|
3601 if (numSubControls == 1 || (numSubControls == 2 && !(option->subControls & SC_MdiMinButton))) |
|
3602 break; |
|
3603 if (option->subControls & SC_MdiNormalButton) |
|
3604 offset += buttonWidth; |
|
3605 break; |
|
3606 default: |
|
3607 break; |
|
3608 } |
|
3609 rect = QRect(offset, 0, buttonWidth, option->rect.height()); |
|
3610 break; |
|
3611 } |
|
3612 #endif // QT_NO_WORKSPACE |
|
3613 |
|
3614 default: |
|
3615 rect = visualRect(option->direction, option->rect, |
|
3616 QWindowsStyle::subControlRect(cc, option, subControl, widget)); |
|
3617 break; |
|
3618 } |
|
3619 return visualRect(option->direction, option->rect, rect); |
|
3620 } |
|
3621 |
|
3622 /*! |
|
3623 \reimp |
|
3624 */ |
|
3625 QSize QWindowsXPStyle::sizeFromContents(ContentsType ct, const QStyleOption *option, |
|
3626 const QSize &contentsSize, const QWidget *widget) const |
|
3627 { |
|
3628 if (!QWindowsXPStylePrivate::useXP()) |
|
3629 return QWindowsStyle::sizeFromContents(ct, option, contentsSize, widget); |
|
3630 |
|
3631 QSize sz(contentsSize); |
|
3632 switch (ct) { |
|
3633 case CT_LineEdit: |
|
3634 case CT_ComboBox: |
|
3635 { |
|
3636 XPThemeData buttontheme(widget, 0, QLatin1String("Button")); |
|
3637 HTHEME theme = buttontheme.handle(); |
|
3638 MARGINS borderSize; |
|
3639 if (theme) { |
|
3640 int result = pGetThemeMargins(theme, |
|
3641 NULL, |
|
3642 BP_PUSHBUTTON, |
|
3643 PBS_NORMAL, |
|
3644 TMT_CONTENTMARGINS, |
|
3645 NULL, |
|
3646 &borderSize); |
|
3647 if (result == S_OK) { |
|
3648 sz += QSize(borderSize.cxLeftWidth + borderSize.cxRightWidth - 2, |
|
3649 borderSize.cyBottomHeight + borderSize.cyTopHeight - 2); |
|
3650 } |
|
3651 sz += QSize(23, 0); //arrow button |
|
3652 } |
|
3653 } |
|
3654 break; |
|
3655 case CT_SpinBox: |
|
3656 { |
|
3657 //Spinbox adds frame twice |
|
3658 sz = QWindowsStyle::sizeFromContents(ct, option, contentsSize, widget); |
|
3659 int border = proxy()->pixelMetric(PM_SpinBoxFrameWidth, option, widget); |
|
3660 sz -= QSize(2*border, 2*border); |
|
3661 } |
|
3662 break; |
|
3663 case CT_TabWidget: |
|
3664 sz += QSize(6, 6); |
|
3665 break; |
|
3666 case CT_Menu: |
|
3667 sz += QSize(1, 0); |
|
3668 break; |
|
3669 #ifndef QT_NO_MENUBAR |
|
3670 case CT_MenuBarItem: |
|
3671 if (!sz.isEmpty()) |
|
3672 sz += QSize(windowsItemHMargin * 5 + 1, 6); |
|
3673 break; |
|
3674 #endif |
|
3675 case CT_MenuItem: |
|
3676 if (const QStyleOptionMenuItem *menuitem = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) |
|
3677 { |
|
3678 if (menuitem->menuItemType != QStyleOptionMenuItem::Separator) { |
|
3679 sz = QWindowsStyle::sizeFromContents(ct, option, sz, widget); |
|
3680 sz.setHeight(sz.height() - 2); |
|
3681 return sz; |
|
3682 } |
|
3683 } |
|
3684 sz = QWindowsStyle::sizeFromContents(ct, option, sz, widget); |
|
3685 break; |
|
3686 |
|
3687 case CT_MdiControls: |
|
3688 if (const QStyleOptionComplex *styleOpt = qstyleoption_cast<const QStyleOptionComplex *>(option)) { |
|
3689 int width = 0; |
|
3690 if (styleOpt->subControls & SC_MdiMinButton) |
|
3691 width += 17 + 1; |
|
3692 if (styleOpt->subControls & SC_MdiNormalButton) |
|
3693 width += 17 + 1; |
|
3694 if (styleOpt->subControls & SC_MdiCloseButton) |
|
3695 width += 17 + 1; |
|
3696 sz = QSize(width, 19); |
|
3697 } else { |
|
3698 sz = QSize(54, 19); |
|
3699 } |
|
3700 break; |
|
3701 |
|
3702 default: |
|
3703 sz = QWindowsStyle::sizeFromContents(ct, option, sz, widget); |
|
3704 break; |
|
3705 } |
|
3706 |
|
3707 return sz; |
|
3708 } |
|
3709 |
|
3710 |
|
3711 /*! \reimp */ |
|
3712 int QWindowsXPStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget, |
|
3713 QStyleHintReturn *returnData) const |
|
3714 { |
|
3715 QWindowsXPStylePrivate *d = const_cast<QWindowsXPStylePrivate*>(d_func()); |
|
3716 if (!QWindowsXPStylePrivate::useXP()) |
|
3717 return QWindowsStyle::styleHint(hint, option, widget, returnData); |
|
3718 |
|
3719 int res = 0; |
|
3720 switch (hint) { |
|
3721 |
|
3722 case SH_EtchDisabledText: |
|
3723 res = (qobject_cast<const QLabel*>(widget) != 0); |
|
3724 break; |
|
3725 |
|
3726 case SH_SpinControls_DisableOnBounds: |
|
3727 res = 0; |
|
3728 break; |
|
3729 |
|
3730 case SH_TitleBar_AutoRaise: |
|
3731 case SH_TitleBar_NoBorder: |
|
3732 res = 1; |
|
3733 break; |
|
3734 |
|
3735 case SH_GroupBox_TextLabelColor: |
|
3736 if (!widget || (widget && widget->isEnabled())) |
|
3737 res = d->groupBoxTextColor; |
|
3738 else |
|
3739 res = d->groupBoxTextColorDisabled; |
|
3740 break; |
|
3741 |
|
3742 case SH_Table_GridLineColor: |
|
3743 res = 0xC0C0C0; |
|
3744 break; |
|
3745 |
|
3746 case SH_WindowFrame_Mask: |
|
3747 { |
|
3748 res = 1; |
|
3749 QStyleHintReturnMask *mask = qstyleoption_cast<QStyleHintReturnMask *>(returnData); |
|
3750 const QStyleOptionTitleBar *titlebar = qstyleoption_cast<const QStyleOptionTitleBar *>(option); |
|
3751 if (mask && titlebar) { |
|
3752 XPThemeData themeData; |
|
3753 if (titlebar->titleBarState & Qt::WindowMinimized) { |
|
3754 themeData = XPThemeData(widget, 0, QLatin1String("WINDOW"), WP_MINCAPTION, CS_ACTIVE, option->rect); |
|
3755 } else |
|
3756 themeData = XPThemeData(widget, 0, QLatin1String("WINDOW"), WP_CAPTION, CS_ACTIVE, option->rect); |
|
3757 mask->region = d->region(themeData); |
|
3758 } |
|
3759 } |
|
3760 break; |
|
3761 #ifndef QT_NO_RUBBERBAND |
|
3762 case SH_RubberBand_Mask: |
|
3763 if (qstyleoption_cast<const QStyleOptionRubberBand *>(option)) { |
|
3764 res = 0; |
|
3765 break; |
|
3766 } |
|
3767 #endif // QT_NO_RUBBERBAND |
|
3768 |
|
3769 case SH_ItemView_DrawDelegateFrame: |
|
3770 res = 1; |
|
3771 break; |
|
3772 |
|
3773 default: |
|
3774 res =QWindowsStyle::styleHint(hint, option, widget, returnData); |
|
3775 } |
|
3776 |
|
3777 return res; |
|
3778 } |
|
3779 |
|
3780 /*! \reimp */ |
|
3781 QPalette QWindowsXPStyle::standardPalette() const |
|
3782 { |
|
3783 if (QWindowsXPStylePrivate::useXP() && QApplicationPrivate::sys_pal) |
|
3784 return *QApplicationPrivate::sys_pal; |
|
3785 else |
|
3786 return QWindowsStyle::standardPalette(); |
|
3787 } |
|
3788 |
|
3789 /*! |
|
3790 \reimp |
|
3791 */ |
|
3792 QPixmap QWindowsXPStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *option, |
|
3793 const QWidget *widget) const |
|
3794 { |
|
3795 if (!QWindowsXPStylePrivate::useXP()) |
|
3796 return QWindowsStyle::standardPixmap(standardPixmap, option, widget); |
|
3797 |
|
3798 switch(standardPixmap) { |
|
3799 case SP_TitleBarMaxButton: |
|
3800 case SP_TitleBarCloseButton: |
|
3801 if (qstyleoption_cast<const QStyleOptionDockWidget *>(option)) |
|
3802 { |
|
3803 if (widget && widget->isWindow()) { |
|
3804 XPThemeData theme(widget, 0, QLatin1String("WINDOW"), WP_SMALLCLOSEBUTTON, CBS_NORMAL); |
|
3805 if (theme.isValid()) { |
|
3806 SIZE sz; |
|
3807 pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &sz); |
|
3808 return QIcon(QWindowsStyle::standardPixmap(standardPixmap, option, widget)).pixmap(QSize(sz.cx, sz.cy)); |
|
3809 } |
|
3810 } |
|
3811 } |
|
3812 break; |
|
3813 default: |
|
3814 break; |
|
3815 } |
|
3816 return QWindowsStyle::standardPixmap(standardPixmap, option, widget); |
|
3817 } |
|
3818 |
|
3819 /*! |
|
3820 \internal |
|
3821 */ |
|
3822 QIcon QWindowsXPStyle::standardIconImplementation(StandardPixmap standardIcon, |
|
3823 const QStyleOption *option, |
|
3824 const QWidget *widget) const |
|
3825 { |
|
3826 if (!QWindowsXPStylePrivate::useXP()) { |
|
3827 return QWindowsStyle::standardIconImplementation(standardIcon, option, widget); |
|
3828 } |
|
3829 |
|
3830 QWindowsXPStylePrivate *d = const_cast<QWindowsXPStylePrivate*>(d_func()); |
|
3831 switch(standardIcon) { |
|
3832 case SP_TitleBarMaxButton: |
|
3833 if (qstyleoption_cast<const QStyleOptionDockWidget *>(option)) |
|
3834 { |
|
3835 if (d->dockFloat.isNull()) { |
|
3836 XPThemeData themeSize(0, 0, QLatin1String("WINDOW"), WP_SMALLCLOSEBUTTON, CBS_NORMAL); |
|
3837 XPThemeData theme(0, 0, QLatin1String("WINDOW"), WP_MAXBUTTON, MAXBS_NORMAL); |
|
3838 if (theme.isValid()) { |
|
3839 SIZE size; |
|
3840 pGetThemePartSize(themeSize.handle(), 0, themeSize.partId, themeSize.stateId, 0, TS_TRUE, &size); |
|
3841 QPixmap pm = QPixmap(size.cx, size.cy); |
|
3842 pm.fill(Qt::transparent); |
|
3843 QPainter p(&pm); |
|
3844 theme.painter = &p; |
|
3845 theme.rect = QRect(0, 0, size.cx, size.cy); |
|
3846 d->drawBackground(theme); |
|
3847 d->dockFloat.addPixmap(pm, QIcon::Normal, QIcon::Off); // Normal |
|
3848 pm.fill(Qt::transparent); |
|
3849 theme.stateId = MAXBS_PUSHED; |
|
3850 d->drawBackground(theme); |
|
3851 d->dockFloat.addPixmap(pm, QIcon::Normal, QIcon::On); // Pressed |
|
3852 pm.fill(Qt::transparent); |
|
3853 theme.stateId = MAXBS_HOT; |
|
3854 d->drawBackground(theme); |
|
3855 d->dockFloat.addPixmap(pm, QIcon::Active, QIcon::Off); // Hover |
|
3856 pm.fill(Qt::transparent); |
|
3857 theme.stateId = MAXBS_INACTIVE; |
|
3858 d->drawBackground(theme); |
|
3859 d->dockFloat.addPixmap(pm, QIcon::Disabled, QIcon::Off); // Disabled |
|
3860 } |
|
3861 } |
|
3862 if (widget && widget->isWindow()) |
|
3863 return d->dockFloat; |
|
3864 |
|
3865 } |
|
3866 break; |
|
3867 case SP_TitleBarCloseButton: |
|
3868 if (qstyleoption_cast<const QStyleOptionDockWidget *>(option)) |
|
3869 { |
|
3870 if (d->dockClose.isNull()) { |
|
3871 XPThemeData theme(0, 0, QLatin1String("WINDOW"), WP_SMALLCLOSEBUTTON, CBS_NORMAL); |
|
3872 if (theme.isValid()) { |
|
3873 SIZE size; |
|
3874 pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); |
|
3875 QPixmap pm = QPixmap(size.cx, size.cy); |
|
3876 pm.fill(Qt::transparent); |
|
3877 QPainter p(&pm); |
|
3878 theme.painter = &p; |
|
3879 theme.partId = WP_CLOSEBUTTON; // #### |
|
3880 theme.rect = QRect(0, 0, size.cx, size.cy); |
|
3881 d->drawBackground(theme); |
|
3882 d->dockClose.addPixmap(pm, QIcon::Normal, QIcon::Off); // Normal |
|
3883 pm.fill(Qt::transparent); |
|
3884 theme.stateId = CBS_PUSHED; |
|
3885 d->drawBackground(theme); |
|
3886 d->dockClose.addPixmap(pm, QIcon::Normal, QIcon::On); // Pressed |
|
3887 pm.fill(Qt::transparent); |
|
3888 theme.stateId = CBS_HOT; |
|
3889 d->drawBackground(theme); |
|
3890 d->dockClose.addPixmap(pm, QIcon::Active, QIcon::Off); // Hover |
|
3891 pm.fill(Qt::transparent); |
|
3892 theme.stateId = CBS_INACTIVE; |
|
3893 d->drawBackground(theme); |
|
3894 d->dockClose.addPixmap(pm, QIcon::Disabled, QIcon::Off); // Disabled |
|
3895 } |
|
3896 } |
|
3897 if (widget && widget->isWindow()) |
|
3898 return d->dockClose; |
|
3899 } |
|
3900 break; |
|
3901 case SP_TitleBarNormalButton: |
|
3902 if (qstyleoption_cast<const QStyleOptionDockWidget *>(option)) |
|
3903 { |
|
3904 if (d->dockFloat.isNull()) { |
|
3905 XPThemeData themeSize(0, 0, QLatin1String("WINDOW"), WP_SMALLCLOSEBUTTON, CBS_NORMAL); |
|
3906 XPThemeData theme(0, 0, QLatin1String("WINDOW"), WP_RESTOREBUTTON, RBS_NORMAL); |
|
3907 if (theme.isValid()) { |
|
3908 SIZE size; |
|
3909 pGetThemePartSize(themeSize.handle(), 0, themeSize.partId, themeSize.stateId, 0, TS_TRUE, &size); |
|
3910 QPixmap pm = QPixmap(size.cx, size.cy); |
|
3911 pm.fill(Qt::transparent); |
|
3912 QPainter p(&pm); |
|
3913 theme.painter = &p; |
|
3914 theme.rect = QRect(0, 0, size.cx, size.cy); |
|
3915 d->drawBackground(theme); |
|
3916 d->dockFloat.addPixmap(pm, QIcon::Normal, QIcon::Off); // Normal |
|
3917 pm.fill(Qt::transparent); |
|
3918 theme.stateId = RBS_PUSHED; |
|
3919 d->drawBackground(theme); |
|
3920 d->dockFloat.addPixmap(pm, QIcon::Normal, QIcon::On); // Pressed |
|
3921 pm.fill(Qt::transparent); |
|
3922 theme.stateId = RBS_HOT; |
|
3923 d->drawBackground(theme); |
|
3924 d->dockFloat.addPixmap(pm, QIcon::Active, QIcon::Off); // Hover |
|
3925 pm.fill(Qt::transparent); |
|
3926 theme.stateId = RBS_INACTIVE; |
|
3927 d->drawBackground(theme); |
|
3928 d->dockFloat.addPixmap(pm, QIcon::Disabled, QIcon::Off); // Disabled |
|
3929 } |
|
3930 } |
|
3931 if (widget && widget->isWindow()) |
|
3932 return d->dockFloat; |
|
3933 |
|
3934 } |
|
3935 break; |
|
3936 default: |
|
3937 break; |
|
3938 } |
|
3939 |
|
3940 return QWindowsStyle::standardIconImplementation(standardIcon, option, widget); |
|
3941 } |
|
3942 |
|
3943 /*! |
|
3944 \internal |
|
3945 |
|
3946 Constructs a QWindowsXPStyle object. |
|
3947 */ |
|
3948 QWindowsXPStyle::QWindowsXPStyle(QWindowsXPStylePrivate &dd) : QWindowsStyle(dd) |
|
3949 { |
|
3950 } |
|
3951 |
|
3952 |
|
3953 // Debugging code ---------------------------------------------------------------------[ START ]--- |
|
3954 // The code for this point on is not compiled by default, but only used as assisting |
|
3955 // debugging code when you uncomment the DEBUG_XP_STYLE define at the top of the file. |
|
3956 |
|
3957 #ifdef DEBUG_XP_STYLE |
|
3958 // The schema file expects these to be defined by the user. |
|
3959 #define TMT_ENUMDEF 8 |
|
3960 #define TMT_ENUMVAL TEXT('A') |
|
3961 #define TMT_ENUM TEXT('B') |
|
3962 #define SCHEMA_STRINGS // For 2nd pass on schema file |
|
3963 QT_BEGIN_INCLUDE_NAMESPACE |
|
3964 #include <tmschema.h> |
|
3965 QT_END_INCLUDE_NAMESPACE |
|
3966 |
|
3967 // A property's value, type and name combo |
|
3968 struct PropPair { |
|
3969 int propValue; |
|
3970 int propType; |
|
3971 LPCWSTR propName; |
|
3972 }; |
|
3973 |
|
3974 // Operator for sorting of PropPairs |
|
3975 bool operator<(PropPair a, PropPair b) { |
|
3976 return wcscmp(a.propName, b.propName) < 0; |
|
3977 } |
|
3978 |
|
3979 // Our list of all possible properties |
|
3980 static QList<PropPair> all_props; |
|
3981 |
|
3982 |
|
3983 /*! \internal |
|
3984 Dumps a portion of the full native DIB section double buffer. |
|
3985 The DIB section double buffer is only used when doing special |
|
3986 transformations to the theme part, or when the real double |
|
3987 buffer in the paintengine does not have an HDC we may use |
|
3988 directly. |
|
3989 Since we cannot rely on the pixel data we get from Microsoft |
|
3990 when drawing into the DIB section, we use this function to |
|
3991 see the actual data we got, and can determin the appropriate |
|
3992 action. |
|
3993 */ |
|
3994 void QWindowsXPStylePrivate::dumpNativeDIB(int w, int h) |
|
3995 { |
|
3996 if (w && h) { |
|
3997 static int pCount = 0; |
|
3998 DWORD *bufPix = (DWORD*)bufferPixels; |
|
3999 |
|
4000 char *bufferDump = new char[bufferH * bufferW * 16]; |
|
4001 char *bufferPos = bufferDump; |
|
4002 |
|
4003 memset(bufferDump, 0, sizeof(bufferDump)); |
|
4004 bufferPos += sprintf(bufferPos, "const int pixelBufferW%d = %d;\n", pCount, w); |
|
4005 bufferPos += sprintf(bufferPos, "const int pixelBufferH%d = %d;\n", pCount, h); |
|
4006 bufferPos += sprintf(bufferPos, "const unsigned DWORD pixelBuffer%d[] = {", pCount); |
|
4007 for (int iy = 0; iy < h; ++iy) { |
|
4008 bufferPos += sprintf(bufferPos, "\n "); |
|
4009 bufPix = (DWORD*)(bufferPixels + (iy * bufferW * 4)); |
|
4010 for (int ix = 0; ix < w; ++ix) { |
|
4011 bufferPos += sprintf(bufferPos, "0x%08x, ", *bufPix); |
|
4012 ++bufPix; |
|
4013 } |
|
4014 } |
|
4015 bufferPos += sprintf(bufferPos, "\n};\n\n"); |
|
4016 printf(bufferDump); |
|
4017 |
|
4018 delete bufferDump; |
|
4019 ++pCount; |
|
4020 } |
|
4021 } |
|
4022 |
|
4023 /*! \internal |
|
4024 Shows the value of a given property for a part. |
|
4025 */ |
|
4026 static void showProperty(XPThemeData &themeData, const PropPair &prop) |
|
4027 { |
|
4028 PROPERTYORIGIN origin = PO_NOTFOUND; |
|
4029 pGetThemePropertyOrigin(themeData.handle(), themeData.partId, themeData.stateId, prop.propValue, &origin); |
|
4030 const char *originStr; |
|
4031 switch(origin) { |
|
4032 case PO_STATE: |
|
4033 originStr = "State "; |
|
4034 break; |
|
4035 case PO_PART: |
|
4036 originStr = "Part "; |
|
4037 break; |
|
4038 case PO_CLASS: |
|
4039 originStr = "Class "; |
|
4040 break; |
|
4041 case PO_GLOBAL: |
|
4042 originStr = "Globl "; |
|
4043 break; |
|
4044 case PO_NOTFOUND: |
|
4045 default: |
|
4046 originStr = "Unkwn "; |
|
4047 break; |
|
4048 } |
|
4049 |
|
4050 switch(prop.propType) { |
|
4051 case TMT_STRING: |
|
4052 { |
|
4053 wchar_t buffer[512]; |
|
4054 pGetThemeString(themeData.handle(), themeData.partId, themeData.stateId, prop.propValue, buffer, 512); |
|
4055 printf(" (%sString) %-20S: %S\n", originStr, prop.propName, buffer); |
|
4056 } |
|
4057 break; |
|
4058 case TMT_ENUM: |
|
4059 { |
|
4060 int result = -1; |
|
4061 pGetThemeEnumValue(themeData.handle(), themeData.partId, themeData.stateId, prop.propValue, &result); |
|
4062 printf(" (%sEnum) %-20S: %d\n", originStr, prop.propName, result); |
|
4063 } |
|
4064 break; |
|
4065 case TMT_INT: |
|
4066 { |
|
4067 int result = -1; |
|
4068 pGetThemeInt(themeData.handle(), themeData.partId, themeData.stateId, prop.propValue, &result); |
|
4069 printf(" (%sint) %-20S: %d\n", originStr, prop.propName, result); |
|
4070 } |
|
4071 break; |
|
4072 case TMT_BOOL: |
|
4073 { |
|
4074 BOOL result = false; |
|
4075 pGetThemeBool(themeData.handle(), themeData.partId, themeData.stateId, prop.propValue, &result); |
|
4076 printf(" (%sbool) %-20S: %d\n", originStr, prop.propName, result); |
|
4077 } |
|
4078 break; |
|
4079 case TMT_COLOR: |
|
4080 { |
|
4081 COLORREF result = 0; |
|
4082 pGetThemeColor(themeData.handle(), themeData.partId, themeData.stateId, prop.propValue, &result); |
|
4083 printf(" (%scolor) %-20S: 0x%08X\n", originStr, prop.propName, result); |
|
4084 } |
|
4085 break; |
|
4086 case TMT_MARGINS: |
|
4087 { |
|
4088 MARGINS result; |
|
4089 memset(&result, 0, sizeof(result)); |
|
4090 pGetThemeMargins(themeData.handle(), 0, themeData.partId, themeData.stateId, prop.propValue, 0, &result); |
|
4091 printf(" (%smargins) %-20S: (%d, %d, %d, %d)\n", originStr, |
|
4092 prop.propName, result.cxLeftWidth, result.cyTopHeight, result.cxRightWidth, result.cyBottomHeight); |
|
4093 } |
|
4094 break; |
|
4095 case TMT_FILENAME: |
|
4096 { |
|
4097 wchar_t buffer[512]; |
|
4098 pGetThemeFilename(themeData.handle(), themeData.partId, themeData.stateId, prop.propValue, buffer, 512); |
|
4099 printf(" (%sfilename)%-20S: %S\n", originStr, prop.propName, buffer); |
|
4100 } |
|
4101 break; |
|
4102 case TMT_SIZE: |
|
4103 { |
|
4104 SIZE result1; |
|
4105 SIZE result2; |
|
4106 SIZE result3; |
|
4107 memset(&result1, 0, sizeof(result1)); |
|
4108 memset(&result2, 0, sizeof(result2)); |
|
4109 memset(&result3, 0, sizeof(result3)); |
|
4110 pGetThemePartSize(themeData.handle(), 0, themeData.partId, themeData.stateId, 0, TS_MIN, &result1); |
|
4111 pGetThemePartSize(themeData.handle(), 0, themeData.partId, themeData.stateId, 0, TS_TRUE, &result2); |
|
4112 pGetThemePartSize(themeData.handle(), 0, themeData.partId, themeData.stateId, 0, TS_DRAW, &result3); |
|
4113 printf(" (%ssize) %-20S: Min (%d, %d), True(%d, %d), Draw(%d, %d)\n", originStr, prop.propName, |
|
4114 result1.cx, result1.cy, result2.cx, result2.cy, result3.cx, result3.cy); |
|
4115 } |
|
4116 break; |
|
4117 case TMT_POSITION: |
|
4118 { |
|
4119 POINT result; |
|
4120 memset(&result, 0, sizeof(result)); |
|
4121 pGetThemePosition(themeData.handle(), themeData.partId, themeData.stateId, prop.propValue, &result); |
|
4122 printf(" (%sPosition)%-20S: (%d, %d)\n", originStr, prop.propName, result.x, result.y); |
|
4123 } |
|
4124 break; |
|
4125 case TMT_RECT: |
|
4126 { |
|
4127 RECT result; |
|
4128 memset(&result, 0, sizeof(result)); |
|
4129 pGetThemeRect(themeData.handle(), themeData.partId, themeData.stateId, prop.propValue, &result); |
|
4130 printf(" (%sRect) %-20S: (%d, %d, %d, %d)\n", originStr, prop.propName, result.left, result.top, result.right, result.bottom); |
|
4131 } |
|
4132 break; |
|
4133 case TMT_FONT: |
|
4134 { |
|
4135 LOGFONT result; |
|
4136 memset(&result, 0, sizeof(result)); |
|
4137 pGetThemeFont(themeData.handle(), 0, themeData.partId, themeData.stateId, prop.propValue, &result); |
|
4138 printf(" (%sFont) %-20S: %S height(%d) width(%d) weight(%d)\n", originStr, prop.propName, |
|
4139 result.lfFaceName, result.lfHeight, result.lfWidth, result.lfWeight); |
|
4140 } |
|
4141 break; |
|
4142 case TMT_INTLIST: |
|
4143 { |
|
4144 INTLIST result; |
|
4145 memset(&result, 0, sizeof(result)); |
|
4146 pGetThemeIntList(themeData.handle(), themeData.partId, themeData.stateId, prop.propValue, &result); |
|
4147 printf(" (%sInt list)%-20S: { ", originStr, prop.propName); |
|
4148 for (int i = 0; i < result.iValueCount; ++i) |
|
4149 printf("%d ", result.iValues[i]); |
|
4150 printf("}\n"); |
|
4151 } |
|
4152 break; |
|
4153 default: |
|
4154 printf(" %s%S : Unknown property type (%d)!\n", originStr, prop.propName, prop.propType); |
|
4155 } |
|
4156 } |
|
4157 |
|
4158 /*! \internal |
|
4159 Dump all valid properties for a part. |
|
4160 If it's the first time this function is called, then the name, |
|
4161 enum value and documentation of all properties are shown, as |
|
4162 well as all global properties. |
|
4163 */ |
|
4164 void QWindowsXPStylePrivate::showProperties(XPThemeData &themeData) |
|
4165 { |
|
4166 if (!all_props.count()) { |
|
4167 const TMSCHEMAINFO *infoTable = GetSchemaInfo(); |
|
4168 for (int i = 0; i < infoTable->iPropCount; ++i) { |
|
4169 int propType = infoTable->pPropTable[i].bPrimVal; |
|
4170 int propValue = infoTable->pPropTable[i].sEnumVal; |
|
4171 LPCWSTR propName = infoTable->pPropTable[i].pszName; |
|
4172 |
|
4173 switch(propType) { |
|
4174 case TMT_ENUMDEF: |
|
4175 case TMT_ENUMVAL: |
|
4176 continue; |
|
4177 default: |
|
4178 if (propType != propValue) { |
|
4179 PropPair prop; |
|
4180 prop.propValue = propValue; |
|
4181 prop.propName = propName; |
|
4182 prop.propType = propType; |
|
4183 all_props.append(prop); |
|
4184 } |
|
4185 } |
|
4186 } |
|
4187 qSort(all_props); |
|
4188 |
|
4189 {// List all properties |
|
4190 printf("part properties count = %d:\n", all_props.count()); |
|
4191 printf(" Enum Property Name Description\n"); |
|
4192 printf("-----------------------------------------------------------\n"); |
|
4193 wchar_t themeName[256]; |
|
4194 pGetCurrentThemeName(themeName, 256, 0, 0, 0, 0); |
|
4195 for (int j = 0; j < all_props.count(); ++j) { |
|
4196 PropPair prop = all_props.at(j); |
|
4197 wchar_t buf[500]; |
|
4198 pGetThemeDocumentationProperty(themeName, prop.propName, buf, 500); |
|
4199 printf("%3d: (%4d) %-20S %S\n", j, prop.propValue, prop.propName, buf); |
|
4200 } |
|
4201 } |
|
4202 |
|
4203 {// Show Global values |
|
4204 printf("Global Properties:\n"); |
|
4205 for (int j = 0; j < all_props.count(); ++j) { |
|
4206 PropPair prop = all_props.at(j); |
|
4207 PROPERTYORIGIN origin = PO_NOTFOUND; |
|
4208 pGetThemePropertyOrigin(themeData.handle(), themeData.partId, themeData.stateId, prop.propValue, &origin); |
|
4209 if (origin == PO_GLOBAL) { |
|
4210 showProperty(themeData, prop); |
|
4211 } |
|
4212 } |
|
4213 } |
|
4214 } |
|
4215 |
|
4216 for (int j = 0; j < all_props.count(); ++j) { |
|
4217 PropPair prop = all_props.at(j); |
|
4218 PROPERTYORIGIN origin = PO_NOTFOUND; |
|
4219 pGetThemePropertyOrigin(themeData.handle(), themeData.partId, themeData.stateId, prop.propValue, &origin); |
|
4220 if (origin != PO_NOTFOUND) |
|
4221 { |
|
4222 showProperty(themeData, prop); |
|
4223 } |
|
4224 } |
|
4225 } |
|
4226 #endif |
|
4227 // Debugging code -----------------------------------------------------------------------[ END ]--- |
|
4228 |
|
4229 |
|
4230 QT_END_NAMESPACE |
|
4231 |
|
4232 #endif //QT_NO_WINDOWSXP |