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