src/gui/styles/qwindowsxpstyle.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     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