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