src/gui/styles/qstylesheetstyle.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 
       
    42 #include <qglobal.h>
       
    43 
       
    44 #ifndef QT_NO_STYLE_STYLESHEET
       
    45 
       
    46 #include "qstylesheetstyle_p.h"
       
    47 #include "private/qcssutil_p.h"
       
    48 #include <qdebug.h>
       
    49 #include <qapplication.h>
       
    50 #include <qmenu.h>
       
    51 #include <qmenubar.h>
       
    52 #include <qpainter.h>
       
    53 #include <qstyleoption.h>
       
    54 #include <qlineedit.h>
       
    55 #include <qwindowsstyle.h>
       
    56 #include <qcombobox.h>
       
    57 #include <qwindowsstyle.h>
       
    58 #include <qplastiquestyle.h>
       
    59 #include "private/qcssparser_p.h"
       
    60 #include "private/qmath_p.h"
       
    61 #include <qabstractscrollarea.h>
       
    62 #include "private/qabstractscrollarea_p.h"
       
    63 #include <qtooltip.h>
       
    64 #include <qshareddata.h>
       
    65 #include <qradiobutton.h>
       
    66 #include <qtoolbutton.h>
       
    67 #include <qscrollbar.h>
       
    68 #include <qstring.h>
       
    69 #include <qfile.h>
       
    70 #include <qcheckbox.h>
       
    71 #include <qstatusbar.h>
       
    72 #include <qheaderview.h>
       
    73 #include <qprogressbar.h>
       
    74 #include <private/qwindowsstyle_p.h>
       
    75 #include <qtabbar.h>
       
    76 #include <QMetaProperty>
       
    77 #include <qmainwindow.h>
       
    78 #include <qdockwidget.h>
       
    79 #include <qmdisubwindow.h>
       
    80 #include <qdialog.h>
       
    81 #include <private/qwidget_p.h>
       
    82 #include <QAbstractSpinBox>
       
    83 #include <QLabel>
       
    84 #include "qdrawutil.h"
       
    85 
       
    86 #include <limits.h>
       
    87 #include <QtGui/qtoolbar.h>
       
    88 
       
    89 QT_BEGIN_NAMESPACE
       
    90 
       
    91 using namespace QCss;
       
    92 
       
    93 
       
    94 class QStyleSheetStylePrivate : public QWindowsStylePrivate
       
    95 {
       
    96     Q_DECLARE_PUBLIC(QStyleSheetStyle)
       
    97 public:
       
    98     QStyleSheetStylePrivate() { }
       
    99 };
       
   100 
       
   101 
       
   102 static QHash<const QWidget *, QVector<StyleRule> > *styleRulesCache = 0;
       
   103 static QHash<const QWidget *, QHash<int, bool> > *hasStyleRuleCache = 0;
       
   104 typedef QHash<int, QHash<quint64, QRenderRule> > QRenderRules;
       
   105 static QHash<const QWidget *, QRenderRules> *renderRulesCache = 0;
       
   106 static QHash<const QWidget *, QPalette> *customPaletteWidgets = 0; // widgets whose palette we tampered
       
   107 static QHash<const void *, StyleSheet> *styleSheetCache = 0; // parsed style sheets
       
   108 static QSet<const QWidget *> *autoFillDisabledWidgets = 0;
       
   109 
       
   110 
       
   111 /* RECURSION_GUARD:
       
   112  * the QStyleSheetStyle is a proxy. If used with others proxy style, we may end up with something like:
       
   113  * QStyleSheetStyle -> ProxyStyle -> QStyleSheetStyle -> OriginalStyle
       
   114  * Recursion may happen if the style call the widget()->style() again.
       
   115  * Not to mention the performence penalty of having two lookup of rules.
       
   116  *
       
   117  * The first instance of QStyleSheetStyle will set globalStyleSheetStyle to itself. The second one
       
   118  * will notice the globalStyleSheetStyle is not istelf and call its base style directly.
       
   119  */
       
   120 static const QStyleSheetStyle *globalStyleSheetStyle = 0;
       
   121 class QStyleSheetStyleRecursionGuard
       
   122 {
       
   123     public:
       
   124         QStyleSheetStyleRecursionGuard(const QStyleSheetStyle *that)
       
   125             :  guarded(globalStyleSheetStyle == 0)
       
   126             {
       
   127                 if (guarded) globalStyleSheetStyle = that;
       
   128             }
       
   129         ~QStyleSheetStyleRecursionGuard() { if (guarded) globalStyleSheetStyle = 0; }
       
   130         bool guarded;
       
   131 };
       
   132 #define RECURSION_GUARD(RETURN) \
       
   133     if (globalStyleSheetStyle != 0 && globalStyleSheetStyle != this) { RETURN; } \
       
   134     QStyleSheetStyleRecursionGuard recursion_guard(this);
       
   135 
       
   136 #define ceil(x) ((int)(x) + ((x) > 0 && (x) != (int)(x)))
       
   137 
       
   138 enum PseudoElement {
       
   139     PseudoElement_None,
       
   140     PseudoElement_DownArrow,
       
   141     PseudoElement_UpArrow,
       
   142     PseudoElement_LeftArrow,
       
   143     PseudoElement_RightArrow,
       
   144     PseudoElement_Indicator,
       
   145     PseudoElement_ExclusiveIndicator,
       
   146     PseudoElement_PushButtonMenuIndicator,
       
   147     PseudoElement_ComboBoxDropDown,
       
   148     PseudoElement_ComboBoxArrow,
       
   149     PseudoElement_Item,
       
   150     PseudoElement_SpinBoxUpButton,
       
   151     PseudoElement_SpinBoxUpArrow,
       
   152     PseudoElement_SpinBoxDownButton,
       
   153     PseudoElement_SpinBoxDownArrow,
       
   154     PseudoElement_GroupBoxTitle,
       
   155     PseudoElement_GroupBoxIndicator,
       
   156     PseudoElement_ToolButtonMenu,
       
   157     PseudoElement_ToolButtonMenuArrow,
       
   158     PseudoElement_ToolButtonDownArrow,
       
   159     PseudoElement_ToolBoxTab,
       
   160     PseudoElement_ScrollBarSlider,
       
   161     PseudoElement_ScrollBarAddPage,
       
   162     PseudoElement_ScrollBarSubPage,
       
   163     PseudoElement_ScrollBarAddLine,
       
   164     PseudoElement_ScrollBarSubLine,
       
   165     PseudoElement_ScrollBarFirst,
       
   166     PseudoElement_ScrollBarLast,
       
   167     PseudoElement_ScrollBarUpArrow,
       
   168     PseudoElement_ScrollBarDownArrow,
       
   169     PseudoElement_ScrollBarLeftArrow,
       
   170     PseudoElement_ScrollBarRightArrow,
       
   171     PseudoElement_SplitterHandle,
       
   172     PseudoElement_ToolBarHandle,
       
   173     PseudoElement_ToolBarSeparator,
       
   174     PseudoElement_MenuScroller,
       
   175     PseudoElement_MenuTearoff,
       
   176     PseudoElement_MenuCheckMark,
       
   177     PseudoElement_MenuSeparator,
       
   178     PseudoElement_MenuIcon,
       
   179     PseudoElement_MenuRightArrow,
       
   180     PseudoElement_TreeViewBranch,
       
   181     PseudoElement_HeaderViewSection,
       
   182     PseudoElement_HeaderViewUpArrow,
       
   183     PseudoElement_HeaderViewDownArrow,
       
   184     PseudoElement_ProgressBarChunk,
       
   185     PseudoElement_TabBarTab,
       
   186     PseudoElement_TabBarScroller,
       
   187     PseudoElement_TabBarTear,
       
   188     PseudoElement_SliderGroove,
       
   189     PseudoElement_SliderHandle,
       
   190     PseudoElement_SliderAddPage,
       
   191     PseudoElement_SliderSubPage,
       
   192     PseudoElement_SliderTickmark,
       
   193     PseudoElement_TabWidgetPane,
       
   194     PseudoElement_TabWidgetTabBar,
       
   195     PseudoElement_TabWidgetLeftCorner,
       
   196     PseudoElement_TabWidgetRightCorner,
       
   197     PseudoElement_DockWidgetTitle,
       
   198     PseudoElement_DockWidgetCloseButton,
       
   199     PseudoElement_DockWidgetFloatButton,
       
   200     PseudoElement_DockWidgetSeparator,
       
   201     PseudoElement_MdiCloseButton,
       
   202     PseudoElement_MdiMinButton,
       
   203     PseudoElement_MdiNormalButton,
       
   204     PseudoElement_TitleBar,
       
   205     PseudoElement_TitleBarCloseButton,
       
   206     PseudoElement_TitleBarMinButton,
       
   207     PseudoElement_TitleBarMaxButton,
       
   208     PseudoElement_TitleBarShadeButton,
       
   209     PseudoElement_TitleBarUnshadeButton,
       
   210     PseudoElement_TitleBarNormalButton,
       
   211     PseudoElement_TitleBarContextHelpButton,
       
   212     PseudoElement_TitleBarSysMenu,
       
   213     PseudoElement_ViewItem,
       
   214     PseudoElement_ViewItemIcon,
       
   215     PseudoElement_ViewItemText,
       
   216     PseudoElement_ViewItemIndicator,
       
   217     PseudoElement_ScrollAreaCorner,
       
   218     PseudoElement_TabBarTabCloseButton,
       
   219     NumPseudoElements
       
   220 };
       
   221 
       
   222 struct PseudoElementInfo {
       
   223     QStyle::SubControl subControl;
       
   224     const char *name;
       
   225 };
       
   226 
       
   227 static const PseudoElementInfo knownPseudoElements[NumPseudoElements] = {
       
   228     { QStyle::SC_None, "" },
       
   229     { QStyle::SC_None, "down-arrow" },
       
   230     { QStyle::SC_None, "up-arrow" },
       
   231     { QStyle::SC_None, "left-arrow" },
       
   232     { QStyle::SC_None, "right-arrow" },
       
   233     { QStyle::SC_None, "indicator" },
       
   234     { QStyle::SC_None, "indicator" },
       
   235     { QStyle::SC_None, "menu-indicator" },
       
   236     { QStyle::SC_ComboBoxArrow, "drop-down" },
       
   237     { QStyle::SC_ComboBoxArrow, "down-arrow" },
       
   238     { QStyle::SC_None, "item" },
       
   239     { QStyle::SC_SpinBoxUp, "up-button" },
       
   240     { QStyle::SC_SpinBoxUp, "up-arrow" },
       
   241     { QStyle::SC_SpinBoxDown, "down-button" },
       
   242     { QStyle::SC_SpinBoxDown, "down-arrow" },
       
   243     { QStyle::SC_GroupBoxLabel, "title" },
       
   244     { QStyle::SC_GroupBoxCheckBox, "indicator" },
       
   245     { QStyle::SC_ToolButtonMenu, "menu-button" },
       
   246     { QStyle::SC_ToolButtonMenu, "menu-arrow" },
       
   247     { QStyle::SC_None, "menu-indicator" },
       
   248     { QStyle::SC_None, "tab" },
       
   249     { QStyle::SC_ScrollBarSlider, "handle" },
       
   250     { QStyle::SC_ScrollBarAddPage, "add-page" },
       
   251     { QStyle::SC_ScrollBarSubPage, "sub-page" },
       
   252     { QStyle::SC_ScrollBarAddLine, "add-line" },
       
   253     { QStyle::SC_ScrollBarSubLine, "sub-line" },
       
   254     { QStyle::SC_ScrollBarFirst, "first" },
       
   255     { QStyle::SC_ScrollBarLast, "last" },
       
   256     { QStyle::SC_ScrollBarSubLine, "up-arrow" },
       
   257     { QStyle::SC_ScrollBarAddLine, "down-arrow" },
       
   258     { QStyle::SC_ScrollBarSubLine, "left-arrow" },
       
   259     { QStyle::SC_ScrollBarAddLine, "right-arrow" },
       
   260     { QStyle::SC_None, "handle" },
       
   261     { QStyle::SC_None, "handle" },
       
   262     { QStyle::SC_None, "separator" },
       
   263     { QStyle::SC_None, "scroller" },
       
   264     { QStyle::SC_None, "tearoff" },
       
   265     { QStyle::SC_None, "indicator" },
       
   266     { QStyle::SC_None, "separator" },
       
   267     { QStyle::SC_None, "icon" },
       
   268     { QStyle::SC_None, "right-arrow" },
       
   269     { QStyle::SC_None, "branch" },
       
   270     { QStyle::SC_None, "section" },
       
   271     { QStyle::SC_None, "down-arrow" },
       
   272     { QStyle::SC_None, "up-arrow" },
       
   273     { QStyle::SC_None, "chunk" },
       
   274     { QStyle::SC_None, "tab" },
       
   275     { QStyle::SC_None, "scroller" },
       
   276     { QStyle::SC_None, "tear" },
       
   277     { QStyle::SC_SliderGroove, "groove" },
       
   278     { QStyle::SC_SliderHandle, "handle" },
       
   279     { QStyle::SC_None, "add-page" },
       
   280     { QStyle::SC_None, "sub-page"},
       
   281     { QStyle::SC_SliderTickmarks, "tick-mark" },
       
   282     { QStyle::SC_None, "pane" },
       
   283     { QStyle::SC_None, "tab-bar" },
       
   284     { QStyle::SC_None, "left-corner" },
       
   285     { QStyle::SC_None, "right-corner" },
       
   286     { QStyle::SC_None, "title" },
       
   287     { QStyle::SC_None, "close-button" },
       
   288     { QStyle::SC_None, "float-button" },
       
   289     { QStyle::SC_None, "separator" },
       
   290     { QStyle::SC_MdiCloseButton, "close-button" },
       
   291     { QStyle::SC_MdiMinButton, "minimize-button" },
       
   292     { QStyle::SC_MdiNormalButton, "normal-button" },
       
   293     { QStyle::SC_TitleBarLabel, "title" },
       
   294     { QStyle::SC_TitleBarCloseButton, "close-button" },
       
   295     { QStyle::SC_TitleBarMinButton, "minimize-button" },
       
   296     { QStyle::SC_TitleBarMaxButton, "maximize-button" },
       
   297     { QStyle::SC_TitleBarShadeButton, "shade-button" },
       
   298     { QStyle::SC_TitleBarUnshadeButton, "unshade-button" },
       
   299     { QStyle::SC_TitleBarNormalButton, "normal-button" },
       
   300     { QStyle::SC_TitleBarContextHelpButton, "contexthelp-button" },
       
   301     { QStyle::SC_TitleBarSysMenu, "sys-menu" },
       
   302     { QStyle::SC_None, "item" },
       
   303     { QStyle::SC_None, "icon" },
       
   304     { QStyle::SC_None, "text" },
       
   305     { QStyle::SC_None, "indicator" },
       
   306     { QStyle::SC_None, "corner" },
       
   307     { QStyle::SC_None, "close-button" },
       
   308 };
       
   309 
       
   310 
       
   311 struct QStyleSheetBorderImageData : public QSharedData
       
   312 {
       
   313     QStyleSheetBorderImageData()
       
   314         : horizStretch(QCss::TileMode_Unknown), vertStretch(QCss::TileMode_Unknown)
       
   315     {
       
   316         for (int i = 0; i < 4; i++)
       
   317             cuts[i] = -1;
       
   318     }
       
   319     int cuts[4];
       
   320     QPixmap pixmap;
       
   321     QImage image;
       
   322     QCss::TileMode horizStretch, vertStretch;
       
   323 };
       
   324 
       
   325 struct QStyleSheetBackgroundData : public QSharedData
       
   326 {
       
   327     QStyleSheetBackgroundData(const QBrush& b, const QPixmap& p, QCss::Repeat r,
       
   328                               Qt::Alignment a, QCss::Origin o, Attachment t, QCss::Origin c)
       
   329         : brush(b), pixmap(p), repeat(r), position(a), origin(o), attachment(t), clip(c) { }
       
   330 
       
   331     bool isTransparent() const {
       
   332         if (brush.style() != Qt::NoBrush)
       
   333             return !brush.isOpaque();
       
   334         return pixmap.isNull() ? false : pixmap.hasAlpha();
       
   335     }
       
   336     QBrush brush;
       
   337     QPixmap pixmap;
       
   338     QCss::Repeat repeat;
       
   339     Qt::Alignment position;
       
   340     QCss::Origin origin;
       
   341     QCss::Attachment attachment;
       
   342     QCss::Origin clip;
       
   343 };
       
   344 
       
   345 struct QStyleSheetBorderData : public QSharedData
       
   346 {
       
   347     QStyleSheetBorderData() : bi(0)
       
   348     {
       
   349         for (int i = 0; i < 4; i++) {
       
   350             borders[i] = 0;
       
   351             styles[i] = QCss::BorderStyle_None;
       
   352         }
       
   353     }
       
   354 
       
   355     QStyleSheetBorderData(int *b, QBrush *c, QCss::BorderStyle *s, QSize *r) : bi(0)
       
   356     {
       
   357         for (int i = 0; i < 4; i++) {
       
   358             borders[i] = b[i];
       
   359             styles[i] = s[i];
       
   360             colors[i] = c[i];
       
   361             radii[i] = r[i];
       
   362         }
       
   363     }
       
   364 
       
   365     int borders[4];
       
   366     QBrush colors[4];
       
   367     QCss::BorderStyle styles[4];
       
   368     QSize radii[4]; // topleft, topright, bottomleft, bottomright
       
   369 
       
   370     const QStyleSheetBorderImageData *borderImage() const
       
   371     { return bi; }
       
   372     bool hasBorderImage() const { return bi!=0; }
       
   373 
       
   374     QSharedDataPointer<QStyleSheetBorderImageData> bi;
       
   375 
       
   376     bool isOpaque() const
       
   377     {
       
   378         for (int i = 0; i < 4; i++) {
       
   379             if (styles[i] == QCss::BorderStyle_Native || styles[i] == QCss::BorderStyle_None)
       
   380                 continue;
       
   381             if (styles[i] >= QCss::BorderStyle_Dotted && styles[i] <= QCss::BorderStyle_DotDotDash
       
   382                 && styles[i] != BorderStyle_Solid)
       
   383                 return false;
       
   384             if (!colors[i].isOpaque())
       
   385                 return false;
       
   386             if (!radii[i].isEmpty())
       
   387                 return false;
       
   388         }
       
   389         if (bi != 0 && bi->pixmap.hasAlpha())
       
   390             return false;
       
   391         return true;
       
   392     }
       
   393 };
       
   394 
       
   395 
       
   396 struct QStyleSheetOutlineData : public QStyleSheetBorderData
       
   397 {
       
   398     QStyleSheetOutlineData()
       
   399     {
       
   400         for (int i = 0; i < 4; i++) {
       
   401             offsets[i] = 0;
       
   402         }
       
   403     }
       
   404 
       
   405     QStyleSheetOutlineData(int *b, QBrush *c, QCss::BorderStyle *s, QSize *r, int *o)
       
   406             : QStyleSheetBorderData(b, c, s, r)
       
   407     {
       
   408         for (int i = 0; i < 4; i++) {
       
   409             offsets[i] = o[i];
       
   410         }
       
   411     }
       
   412 
       
   413     int offsets[4];
       
   414 };
       
   415 
       
   416 struct QStyleSheetBoxData : public QSharedData
       
   417 {
       
   418     QStyleSheetBoxData(int *m, int *p, int s) : spacing(s)
       
   419     {
       
   420         for (int i = 0; i < 4; i++) {
       
   421             margins[i] = m[i];
       
   422             paddings[i] = p[i];
       
   423         }
       
   424     }
       
   425 
       
   426     int margins[4];
       
   427     int paddings[4];
       
   428 
       
   429     int spacing;
       
   430 };
       
   431 
       
   432 struct QStyleSheetPaletteData : public QSharedData
       
   433 {
       
   434     QStyleSheetPaletteData(const QBrush &fg, const QBrush &sfg, const QBrush &sbg,
       
   435                            const QBrush &abg)
       
   436         : foreground(fg), selectionForeground(sfg), selectionBackground(sbg),
       
   437           alternateBackground(abg) { }
       
   438 
       
   439     QBrush foreground;
       
   440     QBrush selectionForeground;
       
   441     QBrush selectionBackground;
       
   442     QBrush alternateBackground;
       
   443 };
       
   444 
       
   445 struct QStyleSheetGeometryData : public QSharedData
       
   446 {
       
   447     QStyleSheetGeometryData(int w, int h, int minw, int minh, int maxw, int maxh)
       
   448         : minWidth(minw), minHeight(minh), width(w), height(h), maxWidth(maxw), maxHeight(maxh) { }
       
   449 
       
   450     int minWidth, minHeight, width, height, maxWidth, maxHeight;
       
   451 };
       
   452 
       
   453 struct QStyleSheetPositionData : public QSharedData
       
   454 {
       
   455     QStyleSheetPositionData(int l, int t, int r, int b, Origin o, Qt::Alignment p, QCss::PositionMode m, Qt::Alignment a = 0)
       
   456         : left(l), top(t), bottom(b), right(r), origin(o), position(p), mode(m), textAlignment(a) { }
       
   457 
       
   458     int left, top, bottom, right;
       
   459     Origin origin;
       
   460     Qt::Alignment position;
       
   461     QCss::PositionMode mode;
       
   462     Qt::Alignment textAlignment;
       
   463 };
       
   464 
       
   465 struct QStyleSheetImageData : public QSharedData
       
   466 {
       
   467     QStyleSheetImageData(const QIcon &i, Qt::Alignment a, const QSize &sz)
       
   468         : icon(i), alignment(a), size(sz) { }
       
   469 
       
   470     QIcon icon;
       
   471     Qt::Alignment alignment;
       
   472     QSize size;
       
   473 };
       
   474 
       
   475 class QRenderRule
       
   476 {
       
   477 public:
       
   478     QRenderRule() : features(0), hasFont(false), pal(0), b(0), bg(0), bd(0), ou(0), geo(0), p(0), img(0), clipset(0) { }
       
   479     QRenderRule(const QVector<QCss::Declaration> &, const QWidget *);
       
   480     ~QRenderRule() { }
       
   481 
       
   482     QRect borderRect(const QRect &r) const;
       
   483     QRect outlineRect(const QRect &r) const;
       
   484     QRect paddingRect(const QRect &r) const;
       
   485     QRect contentsRect(const QRect &r) const;
       
   486 
       
   487     enum { Margin = 1, Border = 2, Padding = 4, All=Margin|Border|Padding };
       
   488     QRect boxRect(const QRect &r, int flags = All) const;
       
   489     QSize boxSize(const QSize &s, int flags = All) const;
       
   490     QRect originRect(const QRect &rect, Origin origin) const;
       
   491 
       
   492     QPainterPath borderClip(QRect rect);
       
   493     void drawBorder(QPainter *, const QRect&);
       
   494     void drawOutline(QPainter *, const QRect&);
       
   495     void drawBorderImage(QPainter *, const QRect&);
       
   496     void drawBackground(QPainter *, const QRect&, const QPoint& = QPoint(0, 0));
       
   497     void drawBackgroundImage(QPainter *, const QRect&, QPoint = QPoint(0, 0));
       
   498     void drawFrame(QPainter *, const QRect&);
       
   499     void drawImage(QPainter *p, const QRect &rect);
       
   500     void drawRule(QPainter *, const QRect&);
       
   501     void configurePalette(QPalette *, QPalette::ColorGroup, const QWidget *, bool);
       
   502     void configurePalette(QPalette *p, QPalette::ColorRole fr, QPalette::ColorRole br);
       
   503 
       
   504     const QStyleSheetPaletteData *palette() const { return pal; }
       
   505     const QStyleSheetBoxData *box() const { return b; }
       
   506     const QStyleSheetBackgroundData *background() const { return bg; }
       
   507     const QStyleSheetBorderData *border() const { return bd; }
       
   508     const QStyleSheetOutlineData *outline() const { return ou; }
       
   509     const QStyleSheetGeometryData *geometry() const { return geo; }
       
   510     const QStyleSheetPositionData *position() const { return p; }
       
   511 
       
   512     bool hasPalette() const { return pal != 0; }
       
   513     bool hasBackground() const { return bg != 0 && (!bg->pixmap.isNull() || bg->brush.style() != Qt::NoBrush); }
       
   514     bool hasGradientBackground() const { return bg && bg->brush.style() >= Qt::LinearGradientPattern
       
   515                                                    && bg->brush.style() <= Qt::ConicalGradientPattern; }
       
   516 
       
   517     bool hasNativeBorder() const {
       
   518         return bd == 0
       
   519                || (!bd->hasBorderImage() && bd->styles[0] == BorderStyle_Native);
       
   520     }
       
   521 
       
   522     bool hasNativeOutline() const {
       
   523         return (ou == 0
       
   524                 || (!ou->hasBorderImage() && ou->styles[0] == BorderStyle_Native));
       
   525     }
       
   526 
       
   527     bool baseStyleCanDraw() const {
       
   528         if (!hasBackground() || (background()->brush.style() == Qt::NoBrush && bg->pixmap.isNull()))
       
   529             return true;
       
   530         if (bg && !bg->pixmap.isNull())
       
   531             return false;
       
   532         if (hasGradientBackground())
       
   533             return features & StyleFeature_BackgroundGradient;
       
   534         return features & StyleFeature_BackgroundColor;
       
   535     }
       
   536 
       
   537     bool hasBox() const { return b != 0; }
       
   538     bool hasBorder() const { return bd != 0; }
       
   539     bool hasOutline() const { return ou != 0; }
       
   540     bool hasPosition() const { return p != 0; }
       
   541     bool hasGeometry() const { return geo != 0; }
       
   542     bool hasDrawable() const { return !hasNativeBorder() || hasBackground() || hasImage(); }
       
   543     bool hasImage() const { return img != 0; }
       
   544 
       
   545     QSize minimumContentsSize() const
       
   546     { return geo ? QSize(geo->minWidth, geo->minHeight) : QSize(0, 0); }
       
   547     QSize minimumSize() const
       
   548     { return boxSize(minimumContentsSize()); }
       
   549 
       
   550     QSize contentsSize() const
       
   551     { return geo ? QSize(geo->width, geo->height)
       
   552                  : ((img && img->size.isValid()) ? img->size : QSize()); }
       
   553     QSize contentsSize(const QSize &sz) const
       
   554     {
       
   555         QSize csz = contentsSize();
       
   556         if (csz.width() == -1) csz.setWidth(sz.width());
       
   557         if (csz.height() == -1) csz.setHeight(sz.height());
       
   558         return csz;
       
   559     }
       
   560     bool hasContentsSize() const
       
   561     { return (geo && (geo->width != -1 || geo->height != -1)) || (img && img->size.isValid()); }
       
   562 
       
   563     QSize size() const { return boxSize(contentsSize()); }
       
   564     QSize size(const QSize &sz) const { return boxSize(contentsSize(sz)); }
       
   565     QSize adjustSize(const QSize &sz)
       
   566     {
       
   567         if (!geo)
       
   568             return sz;
       
   569         QSize csz = contentsSize();
       
   570         if (csz.width() == -1) csz.setWidth(sz.width());
       
   571         if (csz.height() == -1) csz.setHeight(sz.height());
       
   572         if (geo->maxWidth != -1 && csz.width() > geo->maxWidth) csz.setWidth(geo->maxWidth);
       
   573         if (geo->maxHeight != -1 && csz.height() > geo->maxHeight) csz.setHeight(geo->maxHeight);
       
   574         csz=csz.expandedTo(QSize(geo->minWidth, geo->minHeight));
       
   575         return csz;
       
   576     }
       
   577 
       
   578     int features;
       
   579     QBrush defaultBackground;
       
   580     QFont font;
       
   581     bool hasFont;
       
   582 
       
   583     QHash<QString, QVariant> styleHints;
       
   584     bool hasStyleHint(const QString& sh) const { return styleHints.contains(sh); }
       
   585     QVariant styleHint(const QString& sh) const { return styleHints.value(sh); }
       
   586 
       
   587     void fixupBorder(int);
       
   588 
       
   589     QSharedDataPointer<QStyleSheetPaletteData> pal;
       
   590     QSharedDataPointer<QStyleSheetBoxData> b;
       
   591     QSharedDataPointer<QStyleSheetBackgroundData> bg;
       
   592     QSharedDataPointer<QStyleSheetBorderData> bd;
       
   593     QSharedDataPointer<QStyleSheetOutlineData> ou;
       
   594     QSharedDataPointer<QStyleSheetGeometryData> geo;
       
   595     QSharedDataPointer<QStyleSheetPositionData> p;
       
   596     QSharedDataPointer<QStyleSheetImageData> img;
       
   597 
       
   598     // Shouldn't be here
       
   599     void setClip(QPainter *p, const QRect &rect);
       
   600     void unsetClip(QPainter *);
       
   601     int clipset;
       
   602     QPainterPath clipPath;
       
   603 };
       
   604 
       
   605 ///////////////////////////////////////////////////////////////////////////////////////////
       
   606 static const char *knownStyleHints[] = {
       
   607     "activate-on-singleclick",
       
   608     "alignment",
       
   609     "arrow-keys-navigate-into-children",
       
   610     "backward-icon",
       
   611     "button-layout",
       
   612     "cd-icon",
       
   613     "combobox-list-mousetracking",
       
   614     "combobox-popup",
       
   615     "computer-icon",
       
   616     "desktop-icon",
       
   617     "dialog-apply-icon",
       
   618     "dialog-cancel-icon",
       
   619     "dialog-close-icon",
       
   620     "dialog-discard-icon",
       
   621     "dialog-help-icon",
       
   622     "dialog-no-icon",
       
   623     "dialog-ok-icon",
       
   624     "dialog-open-icon",
       
   625     "dialog-reset-icon",
       
   626     "dialog-save-icon",
       
   627     "dialog-yes-icon",
       
   628     "dialogbuttonbox-buttons-have-icons",
       
   629     "directory-closed-icon",
       
   630     "directory-icon",
       
   631     "directory-link-icon",
       
   632     "directory-open-icon",
       
   633     "dither-disable-text",
       
   634     "dockwidget-close-icon",
       
   635     "downarrow-icon",
       
   636     "dvd-icon",
       
   637     "etch-disabled-text",
       
   638     "file-icon",
       
   639     "file-link-icon",
       
   640     "filedialog-backward-icon", // unused
       
   641     "filedialog-contentsview-icon",
       
   642     "filedialog-detailedview-icon",
       
   643     "filedialog-end-icon",
       
   644     "filedialog-infoview-icon",
       
   645     "filedialog-listview-icon",
       
   646     "filedialog-new-directory-icon",
       
   647     "filedialog-parent-directory-icon",
       
   648     "filedialog-start-icon",
       
   649     "floppy-icon",
       
   650     "forward-icon",
       
   651     "gridline-color",
       
   652     "harddisk-icon",
       
   653     "home-icon",
       
   654     "icon-size",
       
   655     "leftarrow-icon",
       
   656     "lineedit-password-character",
       
   657     "mdi-fill-space-on-maximize",
       
   658     "menu-scrollable",
       
   659     "menubar-altkey-navigation",
       
   660     "menubar-separator",
       
   661     "messagebox-critical-icon",
       
   662     "messagebox-information-icon",
       
   663     "messagebox-question-icon",
       
   664     "messagebox-text-interaction-flags",
       
   665     "messagebox-warning-icon",
       
   666     "mouse-tracking",
       
   667     "network-icon",
       
   668     "opacity",
       
   669     "paint-alternating-row-colors-for-empty-area",
       
   670     "rightarrow-icon",
       
   671     "scrollbar-contextmenu",
       
   672     "scrollbar-leftclick-absolute-position",
       
   673     "scrollbar-middleclick-absolute-position",
       
   674     "scrollbar-roll-between-buttons",
       
   675     "scrollbar-scroll-when-pointer-leaves-control",
       
   676     "scrollview-frame-around-contents",
       
   677     "show-decoration-selected",
       
   678     "spinbox-click-autorepeat-rate",
       
   679     "spincontrol-disable-on-bounds",
       
   680     "tabbar-elide-mode",
       
   681     "tabbar-prefer-no-arrows",
       
   682     "titlebar-close-icon",
       
   683     "titlebar-contexthelp-icon",
       
   684     "titlebar-maximize-icon",
       
   685     "titlebar-menu-icon",
       
   686     "titlebar-minimize-icon",
       
   687     "titlebar-normal-icon",
       
   688     "titlebar-shade-icon",
       
   689     "titlebar-unshade-icon",
       
   690     "toolbutton-popup-delay",
       
   691     "trash-icon",
       
   692     "uparrow-icon"
       
   693 };
       
   694 
       
   695 static const int numKnownStyleHints = sizeof(knownStyleHints)/sizeof(knownStyleHints[0]);
       
   696 
       
   697 static QList<QVariant> subControlLayout(const QString& layout)
       
   698 {
       
   699     QList<QVariant> buttons;
       
   700     for (int i = 0; i < layout.count(); i++) {
       
   701         int button = layout[i].toAscii();
       
   702         switch (button) {
       
   703         case 'm':
       
   704             buttons.append(PseudoElement_MdiMinButton);
       
   705             buttons.append(PseudoElement_TitleBarMinButton);
       
   706             break;
       
   707         case 'M':
       
   708             buttons.append(PseudoElement_TitleBarMaxButton);
       
   709             break;
       
   710         case 'X':
       
   711             buttons.append(PseudoElement_MdiCloseButton);
       
   712             buttons.append(PseudoElement_TitleBarCloseButton);
       
   713             break;
       
   714         case 'N':
       
   715             buttons.append(PseudoElement_MdiNormalButton);
       
   716             buttons.append(PseudoElement_TitleBarNormalButton);
       
   717             break;
       
   718         case 'I':
       
   719             buttons.append(PseudoElement_TitleBarSysMenu);
       
   720             break;
       
   721         case 'T':
       
   722             buttons.append(PseudoElement_TitleBar);
       
   723             break;
       
   724         case 'H':
       
   725             buttons.append(PseudoElement_TitleBarContextHelpButton);
       
   726             break;
       
   727         case 'S':
       
   728             buttons.append(PseudoElement_TitleBarShadeButton);
       
   729             break;
       
   730         default:
       
   731             buttons.append(button);
       
   732             break;
       
   733         }
       
   734     }
       
   735     return buttons;
       
   736 }
       
   737 
       
   738 namespace {
       
   739     struct ButtonInfo {
       
   740         QRenderRule rule;
       
   741         int element;
       
   742         int offset;
       
   743         int where;
       
   744         int width;
       
   745     };
       
   746 }
       
   747 
       
   748 QHash<QStyle::SubControl, QRect> QStyleSheetStyle::titleBarLayout(const QWidget *w, const QStyleOptionTitleBar *tb) const
       
   749 {
       
   750     QHash<QStyle::SubControl, QRect> layoutRects;
       
   751     const bool isMinimized = tb->titleBarState & Qt::WindowMinimized;
       
   752     const bool isMaximized = tb->titleBarState & Qt::WindowMaximized;
       
   753     QRenderRule subRule = renderRule(w, tb);
       
   754     QRect cr = subRule.contentsRect(tb->rect);
       
   755     QList<QVariant> layout = subRule.styleHint(QLatin1String("button-layout")).toList();
       
   756     if (layout.isEmpty())
       
   757         layout = subControlLayout(QLatin1String("I(T)HSmMX"));
       
   758 
       
   759     int offsets[3] = { 0, 0, 0 };
       
   760     enum Where { Left, Right, Center, NoWhere } where = Left;
       
   761     QList<ButtonInfo> infos;
       
   762     for (int i = 0; i < layout.count(); i++) {
       
   763         ButtonInfo info;
       
   764         info.element = layout[i].toInt();
       
   765         if (info.element == '(') {
       
   766             where = Center;
       
   767         } else if (info.element == ')') {
       
   768             where = Right;
       
   769         } else {
       
   770             switch (info.element) {
       
   771             case PseudoElement_TitleBar:
       
   772                 if (!(tb->titleBarFlags & (Qt::WindowTitleHint | Qt::WindowSystemMenuHint)))
       
   773                     continue;
       
   774                 break;
       
   775             case PseudoElement_TitleBarContextHelpButton:
       
   776                 if (!(tb->titleBarFlags & Qt::WindowContextHelpButtonHint))
       
   777                     continue;
       
   778                 break;
       
   779             case PseudoElement_TitleBarMinButton:
       
   780                 if (!(tb->titleBarFlags & Qt::WindowMinimizeButtonHint))
       
   781                     continue;
       
   782                 if (isMinimized)
       
   783                     info.element = PseudoElement_TitleBarNormalButton;
       
   784                 break;
       
   785             case PseudoElement_TitleBarMaxButton:
       
   786                 if (!(tb->titleBarFlags & Qt::WindowMaximizeButtonHint))
       
   787                     continue;
       
   788                 if (isMaximized)
       
   789                     info.element = PseudoElement_TitleBarNormalButton;
       
   790                 break;
       
   791             case PseudoElement_TitleBarShadeButton:
       
   792                 if (!(tb->titleBarFlags & Qt::WindowShadeButtonHint))
       
   793                     continue;
       
   794                 if (isMinimized)
       
   795                     info.element = PseudoElement_TitleBarUnshadeButton;
       
   796                 break;
       
   797             case PseudoElement_TitleBarCloseButton:
       
   798             case PseudoElement_TitleBarSysMenu:
       
   799                 if (!(tb->titleBarFlags & Qt::WindowSystemMenuHint))
       
   800                     continue;
       
   801                 break;
       
   802             default:
       
   803                 continue;
       
   804             }
       
   805             if (info.element == PseudoElement_TitleBar) {
       
   806                 info.width = tb->fontMetrics.width(tb->text) + 6;
       
   807                 subRule.geo = new QStyleSheetGeometryData(info.width, tb->fontMetrics.height(), -1, -1, -1, -1);
       
   808             } else {
       
   809                 subRule = renderRule(w, tb, info.element);
       
   810                 info.width = subRule.size().width();
       
   811             }
       
   812             info.rule = subRule;
       
   813             info.offset = offsets[where];
       
   814             info.where = where;
       
   815             infos.append(info);
       
   816 
       
   817             offsets[where] += info.width;
       
   818         }
       
   819     }
       
   820 
       
   821     for (int i = 0; i < infos.count(); i++) {
       
   822         ButtonInfo info = infos[i];
       
   823         QRect lr = cr;
       
   824         switch (info.where) {
       
   825         case Center: {
       
   826             lr.setLeft(cr.left() + offsets[Left]);
       
   827             lr.setRight(cr.right() - offsets[Right]);
       
   828             QRect r(0, 0, offsets[Center], lr.height());
       
   829             r.moveCenter(lr.center());
       
   830             r.setLeft(r.left()+info.offset);
       
   831             r.setWidth(info.width);
       
   832             lr = r;
       
   833             break; }
       
   834         case Left:
       
   835             lr.translate(info.offset, 0);
       
   836             lr.setWidth(info.width);
       
   837             break;
       
   838         case Right:
       
   839             lr.moveLeft(cr.right() + 1 - offsets[Right] + info.offset);
       
   840             lr.setWidth(info.width);
       
   841             break;
       
   842         default:
       
   843             break;
       
   844         }
       
   845         QStyle::SubControl control = knownPseudoElements[info.element].subControl;
       
   846         layoutRects[control] = positionRect(w, info.rule, info.element, lr, tb->direction);
       
   847     }
       
   848 
       
   849     return layoutRects;
       
   850 }
       
   851 
       
   852 static QStyle::StandardPixmap subControlIcon(int pe)
       
   853 {
       
   854     switch (pe) {
       
   855     case PseudoElement_MdiCloseButton: return QStyle::SP_TitleBarCloseButton;
       
   856     case PseudoElement_MdiMinButton: return QStyle::SP_TitleBarMinButton;
       
   857     case PseudoElement_MdiNormalButton: return QStyle::SP_TitleBarNormalButton;
       
   858     case PseudoElement_TitleBarCloseButton: return QStyle::SP_TitleBarCloseButton;
       
   859     case PseudoElement_TitleBarMinButton: return QStyle::SP_TitleBarMinButton;
       
   860     case PseudoElement_TitleBarMaxButton: return QStyle::SP_TitleBarMaxButton;
       
   861     case PseudoElement_TitleBarShadeButton: return QStyle::SP_TitleBarShadeButton;
       
   862     case PseudoElement_TitleBarUnshadeButton: return QStyle::SP_TitleBarUnshadeButton;
       
   863     case PseudoElement_TitleBarNormalButton: return QStyle::SP_TitleBarNormalButton;
       
   864     case PseudoElement_TitleBarContextHelpButton: return QStyle::SP_TitleBarContextHelpButton;
       
   865     default: break;
       
   866     }
       
   867     return QStyle::SP_CustomBase;
       
   868 }
       
   869 
       
   870 QRenderRule::QRenderRule(const QVector<Declaration> &declarations, const QWidget *widget)
       
   871 : features(0), hasFont(false), pal(0), b(0), bg(0), bd(0), ou(0), geo(0), p(0), img(0), clipset(0)
       
   872 {
       
   873     QPalette palette = QApplication::palette(); // ###: ideally widget's palette
       
   874     ValueExtractor v(declarations, palette);
       
   875     features = v.extractStyleFeatures();
       
   876 
       
   877     int w = -1, h = -1, minw = -1, minh = -1, maxw = -1, maxh = -1;
       
   878     if (v.extractGeometry(&w, &h, &minw, &minh, &maxw, &maxh))
       
   879         geo = new QStyleSheetGeometryData(w, h, minw, minh, maxw, maxh);
       
   880 
       
   881     int left = 0, top = 0, right = 0, bottom = 0;
       
   882     Origin origin = Origin_Unknown;
       
   883     Qt::Alignment position = 0;
       
   884     QCss::PositionMode mode = PositionMode_Unknown;
       
   885     Qt::Alignment textAlignment = 0;
       
   886     if (v.extractPosition(&left, &top, &right, &bottom, &origin, &position, &mode, &textAlignment))
       
   887         p = new QStyleSheetPositionData(left, top, right, bottom, origin, position, mode, textAlignment);
       
   888 
       
   889     int margins[4], paddings[4], spacing = -1;
       
   890     for (int i = 0; i < 4; i++)
       
   891         margins[i] = paddings[i] = 0;
       
   892     if (v.extractBox(margins, paddings, &spacing))
       
   893         b = new QStyleSheetBoxData(margins, paddings, spacing);
       
   894 
       
   895     int borders[4];
       
   896     QBrush colors[4];
       
   897     QCss::BorderStyle styles[4];
       
   898     QSize radii[4];
       
   899     for (int i = 0; i < 4; i++) {
       
   900         borders[i] = 0;
       
   901         styles[i] = BorderStyle_None;
       
   902     }
       
   903     if (v.extractBorder(borders, colors, styles, radii))
       
   904         bd = new QStyleSheetBorderData(borders, colors, styles, radii);
       
   905 
       
   906     int offsets[4];
       
   907     for (int i = 0; i < 4; i++) {
       
   908         borders[i] = offsets[i] = 0;
       
   909         styles[i] = BorderStyle_None;
       
   910     }
       
   911     if (v.extractOutline(borders, colors, styles, radii, offsets))
       
   912         ou = new QStyleSheetOutlineData(borders, colors, styles, radii, offsets);
       
   913 
       
   914     QBrush brush;
       
   915     QString uri;
       
   916     Repeat repeat = Repeat_XY;
       
   917     Qt::Alignment alignment = Qt::AlignTop | Qt::AlignLeft;
       
   918     Attachment attachment = Attachment_Scroll;
       
   919     origin = Origin_Padding;
       
   920     Origin clip = Origin_Border;
       
   921     if (v.extractBackground(&brush, &uri, &repeat, &alignment, &origin, &attachment, &clip))
       
   922         bg = new QStyleSheetBackgroundData(brush, QPixmap(uri), repeat, alignment, origin, attachment, clip);
       
   923 
       
   924     QBrush sfg, fg;
       
   925     QBrush sbg, abg;
       
   926     if (v.extractPalette(&fg, &sfg, &sbg, &abg))
       
   927         pal = new QStyleSheetPaletteData(fg, sfg, sbg, abg);
       
   928 
       
   929     QIcon icon;
       
   930     alignment = Qt::AlignCenter;
       
   931     QSize size;
       
   932     if (v.extractImage(&icon, &alignment, &size))
       
   933         img = new QStyleSheetImageData(icon, alignment, size);
       
   934 
       
   935     int adj = -255;
       
   936     hasFont = v.extractFont(&font, &adj);
       
   937 
       
   938 #ifndef QT_NO_TOOLTIP
       
   939     if (widget && qstrcmp(widget->metaObject()->className(), "QTipLabel") == 0)
       
   940         palette = QToolTip::palette();
       
   941 #endif
       
   942 
       
   943     for (int i = 0; i < declarations.count(); i++) {
       
   944         const Declaration& decl = declarations.at(i);
       
   945         if (decl.d->propertyId == BorderImage) {
       
   946             QString uri;
       
   947             QCss::TileMode horizStretch, vertStretch;
       
   948             int cuts[4];
       
   949 
       
   950             decl.borderImageValue(&uri, cuts, &horizStretch, &vertStretch);
       
   951             if (uri.isEmpty() || uri == QLatin1String("none")) {
       
   952                 if (bd && bd->bi)
       
   953                     bd->bi->pixmap = QPixmap();
       
   954             } else {
       
   955                 if (!bd)
       
   956                     bd = new QStyleSheetBorderData;
       
   957                 if (!bd->bi)
       
   958                     bd->bi = new QStyleSheetBorderImageData;
       
   959 
       
   960                 QStyleSheetBorderImageData *bi = bd->bi;
       
   961                 bi->pixmap = QPixmap(uri);
       
   962                 for (int i = 0; i < 4; i++)
       
   963                     bi->cuts[i] = cuts[i];
       
   964                 bi->horizStretch = horizStretch;
       
   965                 bi->vertStretch = vertStretch;
       
   966             }
       
   967         } else if (decl.d->propertyId == QtBackgroundRole) {
       
   968             if (bg && bg->brush.style() != Qt::NoBrush)
       
   969                 continue;
       
   970             int role = decl.d->values.at(0).variant.toInt();
       
   971             if (role >= Value_FirstColorRole && role <= Value_LastColorRole)
       
   972                 defaultBackground = palette.color((QPalette::ColorRole)(role-Value_FirstColorRole));
       
   973         } else if (decl.d->property.startsWith(QLatin1String("qproperty-"), Qt::CaseInsensitive)) {
       
   974             // intentionally left blank...
       
   975         } else if (decl.d->propertyId == UnknownProperty) {
       
   976             bool knownStyleHint = false;
       
   977             for (int i = 0; i < numKnownStyleHints; i++) {
       
   978                 QLatin1String styleHint(knownStyleHints[i]);
       
   979                 if (decl.d->property.compare(styleHint) == 0) {
       
   980                    QString hintName = QString(styleHint);
       
   981                    QVariant hintValue;
       
   982                    if (hintName.endsWith(QLatin1String("alignment"))) {
       
   983                        hintValue = (int) decl.alignmentValue();
       
   984                    } else if (hintName.endsWith(QLatin1String("color"))) {
       
   985                        hintValue = (int) decl.colorValue().rgba();
       
   986                    } else if (hintName.endsWith(QLatin1String("size"))) {
       
   987                        hintValue = decl.sizeValue();
       
   988                    } else if (hintName.endsWith(QLatin1String("icon"))) {
       
   989                        hintValue = decl.iconValue();
       
   990                    } else if (hintName == QLatin1String("button-layout")
       
   991                               && decl.d->values.count() != 0 && decl.d->values.at(0).type == Value::String) {
       
   992                        hintValue = subControlLayout(decl.d->values.at(0).variant.toString());
       
   993                    } else {
       
   994                        int integer;
       
   995                        decl.intValue(&integer);
       
   996                        hintValue = integer;
       
   997                    }
       
   998                    styleHints[decl.d->property] = hintValue;
       
   999                    knownStyleHint = true;
       
  1000                    break;
       
  1001                 }
       
  1002             }
       
  1003             if (!knownStyleHint)
       
  1004                 qDebug("Unknown property %s", qPrintable(decl.d->property));
       
  1005         }
       
  1006     }
       
  1007 
       
  1008     if (widget) {
       
  1009         QStyleSheetStyle *style = const_cast<QStyleSheetStyle *>(globalStyleSheetStyle);
       
  1010         if (!style)
       
  1011            style = qobject_cast<QStyleSheetStyle *>(widget->style());
       
  1012         if (style)
       
  1013             fixupBorder(style->nativeFrameWidth(widget));
       
  1014 
       
  1015     }
       
  1016     if (hasBorder() && border()->hasBorderImage())
       
  1017         defaultBackground = QBrush();
       
  1018 }
       
  1019 
       
  1020 QRect QRenderRule::borderRect(const QRect& r) const
       
  1021 {
       
  1022     if (!hasBox())
       
  1023         return r;
       
  1024     const int* m = box()->margins;
       
  1025     return r.adjusted(m[LeftEdge], m[TopEdge], -m[RightEdge], -m[BottomEdge]);
       
  1026 }
       
  1027 
       
  1028 QRect QRenderRule::outlineRect(const QRect& r) const
       
  1029 {
       
  1030     QRect br = borderRect(r);
       
  1031     if (!hasOutline())
       
  1032         return br;
       
  1033     const int *b = outline()->borders;
       
  1034     return r.adjusted(b[LeftEdge], b[TopEdge], -b[RightEdge], -b[BottomEdge]);
       
  1035 }
       
  1036 
       
  1037 QRect QRenderRule::paddingRect(const QRect& r) const
       
  1038 {
       
  1039     QRect br = borderRect(r);
       
  1040     if (!hasBorder())
       
  1041         return br;
       
  1042     const int *b = border()->borders;
       
  1043     return br.adjusted(b[LeftEdge], b[TopEdge], -b[RightEdge], -b[BottomEdge]);
       
  1044 }
       
  1045 
       
  1046 QRect QRenderRule::contentsRect(const QRect& r) const
       
  1047 {
       
  1048     QRect pr = paddingRect(r);
       
  1049     if (!hasBox())
       
  1050         return pr;
       
  1051     const int *p = box()->paddings;
       
  1052     return pr.adjusted(p[LeftEdge], p[TopEdge], -p[RightEdge], -p[BottomEdge]);
       
  1053 }
       
  1054 
       
  1055 QRect QRenderRule::boxRect(const QRect& cr, int flags) const
       
  1056 {
       
  1057     QRect r = cr;
       
  1058     if (hasBox()) {
       
  1059         if (flags & Margin) {
       
  1060             const int *m = box()->margins;
       
  1061             r.adjust(-m[LeftEdge], -m[TopEdge], m[RightEdge], m[BottomEdge]);
       
  1062         }
       
  1063         if (flags & Padding) {
       
  1064             const int *p = box()->paddings;
       
  1065             r.adjust(-p[LeftEdge], -p[TopEdge], p[RightEdge], p[BottomEdge]);
       
  1066         }
       
  1067     }
       
  1068     if (!hasNativeBorder() && (flags & Border)) {
       
  1069         const int *b = border()->borders;
       
  1070         r.adjust(-b[LeftEdge], -b[TopEdge], b[RightEdge], b[BottomEdge]);
       
  1071     }
       
  1072     return r;
       
  1073 }
       
  1074 
       
  1075 QSize QRenderRule::boxSize(const QSize &cs, int flags) const
       
  1076 {
       
  1077     QSize bs = boxRect(QRect(QPoint(0, 0), cs), flags).size();
       
  1078     if (cs.width() < 0) bs.setWidth(-1);
       
  1079     if (cs.height() < 0) bs.setHeight(-1);
       
  1080     return bs;
       
  1081 }
       
  1082 
       
  1083 void QRenderRule::fixupBorder(int nativeWidth)
       
  1084 {
       
  1085     if (bd == 0)
       
  1086         return;
       
  1087 
       
  1088     if (!bd->hasBorderImage() || bd->bi->pixmap.isNull()) {
       
  1089         bd->bi = 0;
       
  1090         // ignore the color, border of edges that have none border-style
       
  1091         QBrush color = pal ? pal->foreground : QBrush();
       
  1092         const bool hasRadius = bd->radii[0].isValid() || bd->radii[1].isValid()
       
  1093                                || bd->radii[2].isValid() || bd->radii[3].isValid();
       
  1094         for (int i = 0; i < 4; i++) {
       
  1095             if ((bd->styles[i] == BorderStyle_Native) && hasRadius)
       
  1096                 bd->styles[i] = BorderStyle_None;
       
  1097 
       
  1098             switch (bd->styles[i]) {
       
  1099             case BorderStyle_None:
       
  1100                 // border-style: none forces width to be 0
       
  1101                 bd->colors[i] = QBrush();
       
  1102                 bd->borders[i] = 0;
       
  1103                 break;
       
  1104             case BorderStyle_Native:
       
  1105                 if (bd->borders[i] == 0)
       
  1106                     bd->borders[i] = nativeWidth;
       
  1107                 // intentional fall through
       
  1108             default:
       
  1109                 if (!bd->colors[i].style() != Qt::NoBrush) // auto-acquire 'color'
       
  1110                     bd->colors[i] = color;
       
  1111                 break;
       
  1112             }
       
  1113         }
       
  1114 
       
  1115         return;
       
  1116     }
       
  1117 
       
  1118     // inspect the border image
       
  1119     QStyleSheetBorderImageData *bi = bd->bi;
       
  1120     if (bi->cuts[0] == -1) {
       
  1121         for (int i = 0; i < 4; i++) // assume, cut = border
       
  1122             bi->cuts[i] = int(border()->borders[i]);
       
  1123     }
       
  1124 }
       
  1125 
       
  1126 void QRenderRule::drawBorderImage(QPainter *p, const QRect& rect)
       
  1127 {
       
  1128     static const Qt::TileRule tileMode2TileRule[] = {
       
  1129         Qt::StretchTile, Qt::RoundTile, Qt::StretchTile, Qt::RepeatTile, Qt::StretchTile };
       
  1130 
       
  1131     const QStyleSheetBorderImageData *borderImageData = border()->borderImage();
       
  1132     const int *targetBorders = border()->borders;
       
  1133     const int *sourceBorders = borderImageData->cuts;
       
  1134     QMargins sourceMargins(sourceBorders[LeftEdge], sourceBorders[TopEdge],
       
  1135                            sourceBorders[RightEdge], sourceBorders[BottomEdge]);
       
  1136     QMargins targetMargins(targetBorders[LeftEdge], targetBorders[TopEdge],
       
  1137                            targetBorders[RightEdge], targetBorders[BottomEdge]);
       
  1138 
       
  1139     bool wasSmoothPixmapTransform = p->renderHints() & QPainter::SmoothPixmapTransform;
       
  1140     p->setRenderHint(QPainter::SmoothPixmapTransform);
       
  1141     qDrawBorderPixmap(p, rect, targetMargins, borderImageData->pixmap,
       
  1142                       QRect(QPoint(), borderImageData->pixmap.size()), sourceMargins,
       
  1143                       QTileRules(tileMode2TileRule[borderImageData->horizStretch], tileMode2TileRule[borderImageData->vertStretch]));
       
  1144     p->setRenderHint(QPainter::SmoothPixmapTransform, wasSmoothPixmapTransform);
       
  1145 }
       
  1146 
       
  1147 QRect QRenderRule::originRect(const QRect &rect, Origin origin) const
       
  1148 {
       
  1149     switch (origin) {
       
  1150     case Origin_Padding:
       
  1151         return paddingRect(rect);
       
  1152     case Origin_Border:
       
  1153         return borderRect(rect);
       
  1154     case Origin_Content:
       
  1155         return contentsRect(rect);
       
  1156     case Origin_Margin:
       
  1157     default:
       
  1158         return rect;
       
  1159     }
       
  1160 }
       
  1161 
       
  1162 void QRenderRule::drawBackgroundImage(QPainter *p, const QRect &rect, QPoint off)
       
  1163 {
       
  1164     if (!hasBackground())
       
  1165         return;
       
  1166 
       
  1167     const QPixmap& bgp = background()->pixmap;
       
  1168     if (bgp.isNull())
       
  1169         return;
       
  1170 
       
  1171     setClip(p, borderRect(rect));
       
  1172 
       
  1173     if (background()->origin != background()->clip) {
       
  1174         p->save();
       
  1175         p->setClipRect(originRect(rect, background()->clip), Qt::IntersectClip);
       
  1176     }
       
  1177 
       
  1178     if (background()->attachment == Attachment_Fixed)
       
  1179         off = QPoint(0, 0);
       
  1180 
       
  1181     QRect r = originRect(rect, background()->origin);
       
  1182     QRect aligned = QStyle::alignedRect(Qt::LeftToRight, background()->position, bgp.size(), r);
       
  1183     QRect inter = aligned.intersected(r);
       
  1184 
       
  1185     switch (background()->repeat) {
       
  1186     case Repeat_Y:
       
  1187         p->drawTiledPixmap(inter.x(), r.y(), inter.width(), r.height(), bgp,
       
  1188                            inter.x() - aligned.x() + off.x(),
       
  1189                            bgp.height() - int(aligned.y() - r.y()) % bgp.height() + off.y());
       
  1190         break;
       
  1191     case Repeat_X:
       
  1192         p->drawTiledPixmap(r.x(), inter.y(), r.width(), inter.height(), bgp,
       
  1193                            bgp.width() - int(aligned.x() - r.x())%bgp.width() + off.x(),
       
  1194                            inter.y() - aligned.y() + off.y());
       
  1195         break;
       
  1196     case Repeat_XY:
       
  1197         p->drawTiledPixmap(r, bgp,
       
  1198                            QPoint(bgp.width() - int(aligned.x() - r.x())% bgp.width() + off.x(),
       
  1199                                   bgp.height() - int(aligned.y() - r.y())%bgp.height() + off.y()));
       
  1200         break;
       
  1201     case Repeat_None:
       
  1202     default:
       
  1203         p->drawPixmap(inter.x(), inter.y(), bgp, inter.x() - aligned.x() + off.x(),
       
  1204                       inter.y() - aligned.y() + off.y(), inter.width(), inter.height());
       
  1205         break;
       
  1206     }
       
  1207 
       
  1208 
       
  1209     if (background()->origin != background()->clip)
       
  1210         p->restore();
       
  1211 
       
  1212     unsetClip(p);
       
  1213 }
       
  1214 
       
  1215 void QRenderRule::drawOutline(QPainter *p, const QRect &rect)
       
  1216 {
       
  1217     if (!hasOutline())
       
  1218         return;
       
  1219 
       
  1220     bool wasAntialiased = p->renderHints() & QPainter::Antialiasing;
       
  1221     p->setRenderHint(QPainter::Antialiasing);
       
  1222     qDrawBorder(p, rect, ou->styles, ou->borders, ou->colors, ou->radii);
       
  1223     p->setRenderHint(QPainter::Antialiasing, wasAntialiased);
       
  1224 }
       
  1225 
       
  1226 void QRenderRule::drawBorder(QPainter *p, const QRect& rect)
       
  1227 {
       
  1228     if (!hasBorder())
       
  1229         return;
       
  1230 
       
  1231     if (border()->hasBorderImage()) {
       
  1232         drawBorderImage(p, rect);
       
  1233         return;
       
  1234     }
       
  1235 
       
  1236     bool wasAntialiased = p->renderHints() & QPainter::Antialiasing;
       
  1237     p->setRenderHint(QPainter::Antialiasing);
       
  1238     qDrawBorder(p, rect, bd->styles, bd->borders, bd->colors, bd->radii);
       
  1239     p->setRenderHint(QPainter::Antialiasing, wasAntialiased);
       
  1240 }
       
  1241 
       
  1242 QPainterPath QRenderRule::borderClip(QRect r)
       
  1243 {
       
  1244     if (!hasBorder())
       
  1245         return QPainterPath();
       
  1246 
       
  1247     QSize tlr, trr, blr, brr;
       
  1248     qNormalizeRadii(r, bd->radii, &tlr, &trr, &blr, &brr);
       
  1249     if (tlr.isNull() && trr.isNull() && blr.isNull() && brr.isNull())
       
  1250         return QPainterPath();
       
  1251 
       
  1252     const QRectF rect(r);
       
  1253     const int *borders = border()->borders;
       
  1254     QPainterPath path;
       
  1255     qreal curY = rect.y() + borders[TopEdge]/2.0;
       
  1256     path.moveTo(rect.x() + tlr.width(), curY);
       
  1257     path.lineTo(rect.right() - trr.width(), curY);
       
  1258     qreal curX = rect.right() - borders[RightEdge]/2.0;
       
  1259     path.arcTo(curX - 2*trr.width() + borders[RightEdge], curY,
       
  1260                trr.width()*2 - borders[RightEdge], trr.height()*2 - borders[TopEdge], 90, -90);
       
  1261 
       
  1262     path.lineTo(curX, rect.bottom() - brr.height());
       
  1263     curY = rect.bottom() - borders[BottomEdge]/2.0;
       
  1264     path.arcTo(curX - 2*brr.width() + borders[RightEdge], curY - 2*brr.height() + borders[BottomEdge],
       
  1265                brr.width()*2 - borders[RightEdge], brr.height()*2 - borders[BottomEdge], 0, -90);
       
  1266 
       
  1267     path.lineTo(rect.x() + blr.width(), curY);
       
  1268     curX = rect.left() + borders[LeftEdge]/2.0;
       
  1269     path.arcTo(curX, rect.bottom() - 2*blr.height() + borders[BottomEdge]/2,
       
  1270                blr.width()*2 - borders[LeftEdge], blr.height()*2 - borders[BottomEdge], 270, -90);
       
  1271 
       
  1272     path.lineTo(curX, rect.top() + tlr.height());
       
  1273     path.arcTo(curX, rect.top() + borders[TopEdge]/2,
       
  1274                tlr.width()*2 - borders[LeftEdge], tlr.height()*2 - borders[TopEdge], 180, -90);
       
  1275 
       
  1276     path.closeSubpath();
       
  1277     return path;
       
  1278 }
       
  1279 
       
  1280 /*! \internal
       
  1281   Clip the painter to the border (in case we are using radius border)
       
  1282  */
       
  1283 void QRenderRule::setClip(QPainter *p, const QRect &rect)
       
  1284 {
       
  1285     if (clipset++)
       
  1286         return;
       
  1287     clipPath = borderClip(rect);
       
  1288     if (!clipPath.isEmpty()) {
       
  1289         p->save();
       
  1290         p->setClipPath(clipPath, Qt::IntersectClip);
       
  1291     }
       
  1292 }
       
  1293 
       
  1294 void QRenderRule::unsetClip(QPainter *p)
       
  1295 {
       
  1296     if (--clipset)
       
  1297         return;
       
  1298     if (!clipPath.isEmpty())
       
  1299         p->restore();
       
  1300 }
       
  1301 
       
  1302 void QRenderRule::drawBackground(QPainter *p, const QRect& rect, const QPoint& off)
       
  1303 {
       
  1304     QBrush brush = hasBackground() ? background()->brush : QBrush();
       
  1305     if (brush.style() == Qt::NoBrush)
       
  1306         brush = defaultBackground;
       
  1307 
       
  1308     if (brush.style() != Qt::NoBrush) {
       
  1309         Origin origin = hasBackground() ? background()->clip : Origin_Border;
       
  1310         // ### fix for  gradients
       
  1311         const QPainterPath &borderPath = borderClip(originRect(rect, origin));
       
  1312         if (!borderPath.isEmpty()) {
       
  1313             // Drawn intead of being used as clipping path for better visual quality
       
  1314             bool wasAntialiased = p->renderHints() & QPainter::Antialiasing;
       
  1315             p->setRenderHint(QPainter::Antialiasing);
       
  1316             p->fillPath(borderPath, brush);
       
  1317             p->setRenderHint(QPainter::Antialiasing, wasAntialiased);
       
  1318         } else {
       
  1319             p->fillRect(originRect(rect, origin), brush);
       
  1320         }
       
  1321     }
       
  1322 
       
  1323     drawBackgroundImage(p, rect, off);
       
  1324 }
       
  1325 
       
  1326 void QRenderRule::drawFrame(QPainter *p, const QRect& rect)
       
  1327 {
       
  1328     drawBackground(p, rect);
       
  1329     if (hasBorder())
       
  1330         drawBorder(p, borderRect(rect));
       
  1331 }
       
  1332 
       
  1333 void QRenderRule::drawImage(QPainter *p, const QRect &rect)
       
  1334 {
       
  1335     if (!hasImage())
       
  1336         return;
       
  1337     img->icon.paint(p, rect, img->alignment);
       
  1338 }
       
  1339 
       
  1340 void QRenderRule::drawRule(QPainter *p, const QRect& rect)
       
  1341 {
       
  1342     drawFrame(p, rect);
       
  1343     drawImage(p, contentsRect(rect));
       
  1344 }
       
  1345 
       
  1346 // *shudder* , *horror*, *whoa* <-- what you might feel when you see the functions below
       
  1347 void QRenderRule::configurePalette(QPalette *p, QPalette::ColorRole fr, QPalette::ColorRole br)
       
  1348 {
       
  1349     if (bg && bg->brush.style() != Qt::NoBrush) {
       
  1350         if (br != QPalette::NoRole)
       
  1351             p->setBrush(br, bg->brush);
       
  1352         p->setBrush(QPalette::Window, bg->brush);
       
  1353     }
       
  1354 
       
  1355     if (!hasPalette())
       
  1356         return;
       
  1357 
       
  1358     if (pal->foreground.style() != Qt::NoBrush) {
       
  1359         if (fr != QPalette::NoRole)
       
  1360             p->setBrush(fr, pal->foreground);
       
  1361         p->setBrush(QPalette::WindowText, pal->foreground);
       
  1362         p->setBrush(QPalette::Text, pal->foreground);
       
  1363     }
       
  1364     if (pal->selectionBackground.style() != Qt::NoBrush)
       
  1365         p->setBrush(QPalette::Highlight, pal->selectionBackground);
       
  1366     if (pal->selectionForeground.style() != Qt::NoBrush)
       
  1367         p->setBrush(QPalette::HighlightedText, pal->selectionForeground);
       
  1368     if (pal->alternateBackground.style() != Qt::NoBrush)
       
  1369         p->setBrush(QPalette::AlternateBase, pal->alternateBackground);
       
  1370 }
       
  1371 
       
  1372 void QRenderRule::configurePalette(QPalette *p, QPalette::ColorGroup cg, const QWidget *w, bool embedded)
       
  1373 {
       
  1374     if (bg && bg->brush.style() != Qt::NoBrush) {
       
  1375         p->setBrush(cg, QPalette::Base, bg->brush); // for windows, windowxp
       
  1376         p->setBrush(cg, QPalette::Button, bg->brush); // for plastique
       
  1377         p->setBrush(cg, w->backgroundRole(), bg->brush);
       
  1378         p->setBrush(cg, QPalette::Window, bg->brush);
       
  1379     }
       
  1380 
       
  1381     if (embedded) {
       
  1382         /* For embedded widgets (ComboBox, SpinBox and ScrollArea) we want the embedded widget
       
  1383          * to be transparent when we have a transparent background or border image */
       
  1384         if ((hasBackground() && background()->isTransparent())
       
  1385             || (hasBorder() && border()->hasBorderImage() && !border()->borderImage()->pixmap.isNull()))
       
  1386             p->setBrush(cg, w->backgroundRole(), Qt::NoBrush);
       
  1387     }
       
  1388 
       
  1389     if (!hasPalette())
       
  1390         return;
       
  1391 
       
  1392     if (pal->foreground.style() != Qt::NoBrush) {
       
  1393         p->setBrush(cg, QPalette::ButtonText, pal->foreground);
       
  1394         p->setBrush(cg, w->foregroundRole(), pal->foreground);
       
  1395         p->setBrush(cg, QPalette::WindowText, pal->foreground);
       
  1396         p->setBrush(cg, QPalette::Text, pal->foreground);
       
  1397     }
       
  1398     if (pal->selectionBackground.style() != Qt::NoBrush)
       
  1399         p->setBrush(cg, QPalette::Highlight, pal->selectionBackground);
       
  1400     if (pal->selectionForeground.style() != Qt::NoBrush)
       
  1401         p->setBrush(cg, QPalette::HighlightedText, pal->selectionForeground);
       
  1402     if (pal->alternateBackground.style() != Qt::NoBrush)
       
  1403         p->setBrush(cg, QPalette::AlternateBase, pal->alternateBackground);
       
  1404 }
       
  1405 
       
  1406 ///////////////////////////////////////////////////////////////////////////////
       
  1407 // Style rules
       
  1408 #define WIDGET(x) (static_cast<QWidget *>(x.ptr))
       
  1409 
       
  1410 static inline QWidget *parentWidget(const QWidget *w)
       
  1411 {
       
  1412     if(qobject_cast<const QLabel *>(w) && qstrcmp(w->metaObject()->className(), "QTipLabel") == 0) {
       
  1413         QWidget *p = qvariant_cast<QWidget *>(w->property("_q_stylesheet_parent"));
       
  1414         if (p)
       
  1415             return p;
       
  1416     }
       
  1417     return w->parentWidget();
       
  1418 }
       
  1419 
       
  1420 class QStyleSheetStyleSelector : public StyleSelector
       
  1421 {
       
  1422 public:
       
  1423     QStyleSheetStyleSelector() { }
       
  1424 
       
  1425     QStringList nodeNames(NodePtr node) const
       
  1426     {
       
  1427         if (isNullNode(node))
       
  1428             return QStringList();
       
  1429         const QMetaObject *metaObject = WIDGET(node)->metaObject();
       
  1430 #ifndef QT_NO_TOOLTIP
       
  1431         if (qstrcmp(metaObject->className(), "QTipLabel") == 0)
       
  1432             return QStringList(QLatin1String("QToolTip"));
       
  1433 #endif
       
  1434         QStringList result;
       
  1435         do {
       
  1436             result += QString::fromLatin1(metaObject->className()).replace(QLatin1Char(':'), QLatin1Char('-'));
       
  1437             metaObject = metaObject->superClass();
       
  1438         } while (metaObject != 0);
       
  1439         return result;
       
  1440     }
       
  1441     QString attribute(NodePtr node, const QString& name) const
       
  1442     {
       
  1443         if (isNullNode(node))
       
  1444             return QString();
       
  1445 
       
  1446         QHash<QString, QString> &cache = m_attributeCache[WIDGET(node)];
       
  1447         QHash<QString, QString>::const_iterator cacheIt = cache.constFind(name);
       
  1448         if (cacheIt != cache.constEnd())
       
  1449             return cacheIt.value();
       
  1450 
       
  1451         QVariant value = WIDGET(node)->property(name.toLatin1());
       
  1452         if (!value.isValid()) {
       
  1453             if (name == QLatin1String("class")) {
       
  1454                 QString className = QString::fromLatin1(WIDGET(node)->metaObject()->className());
       
  1455                 if (className.contains(QLatin1Char(':')))
       
  1456                     className.replace(QLatin1Char(':'), QLatin1Char('-'));
       
  1457                 cache[name] = className;
       
  1458                 return className;
       
  1459             } else if (name == QLatin1String("style")) {
       
  1460                 QStyleSheetStyle *proxy = qobject_cast<QStyleSheetStyle *>(WIDGET(node)->style());
       
  1461                 if (proxy) {
       
  1462                     QString styleName = QString::fromLatin1(proxy->baseStyle()->metaObject()->className());
       
  1463                     cache[name] = styleName;
       
  1464                     return styleName;
       
  1465                 }
       
  1466             }
       
  1467         }
       
  1468         QString valueStr;
       
  1469         if(value.type() == QVariant::StringList || value.type() == QVariant::List)
       
  1470             valueStr = value.toStringList().join(QLatin1String(" "));
       
  1471         else
       
  1472             valueStr = value.toString();
       
  1473         cache[name] = valueStr;
       
  1474         return valueStr;
       
  1475     }
       
  1476     bool nodeNameEquals(NodePtr node, const QString& nodeName) const
       
  1477     {
       
  1478         if (isNullNode(node))
       
  1479             return false;
       
  1480         const QMetaObject *metaObject = WIDGET(node)->metaObject();
       
  1481 #ifndef QT_NO_TOOLTIP
       
  1482         if (qstrcmp(metaObject->className(), "QTipLabel") == 0)
       
  1483             return nodeName == QLatin1String("QToolTip");
       
  1484 #endif
       
  1485         do {
       
  1486             const ushort *uc = (const ushort *)nodeName.constData();
       
  1487             const ushort *e = uc + nodeName.length();
       
  1488             const uchar *c = (uchar *)metaObject->className();
       
  1489             while (*c && uc != e && (*uc == *c || (*c == ':' && *uc == '-'))) {
       
  1490                 ++uc;
       
  1491                 ++c;
       
  1492             }
       
  1493             if (uc == e && !*c)
       
  1494                 return true;
       
  1495             metaObject = metaObject->superClass();
       
  1496         } while (metaObject != 0);
       
  1497         return false;
       
  1498     }
       
  1499     bool hasAttributes(NodePtr) const
       
  1500     { return true; }
       
  1501     QStringList nodeIds(NodePtr node) const
       
  1502     { return isNullNode(node) ? QStringList() : QStringList(WIDGET(node)->objectName()); }
       
  1503     bool isNullNode(NodePtr node) const
       
  1504     { return node.ptr == 0; }
       
  1505     NodePtr parentNode(NodePtr node) const
       
  1506     { NodePtr n; n.ptr = isNullNode(node) ? 0 : parentWidget(WIDGET(node)); return n; }
       
  1507     NodePtr previousSiblingNode(NodePtr) const
       
  1508     { NodePtr n; n.ptr = 0; return n; }
       
  1509     NodePtr duplicateNode(NodePtr node) const
       
  1510     { return node; }
       
  1511     void freeNode(NodePtr) const
       
  1512     { }
       
  1513 
       
  1514 private:
       
  1515     mutable QHash<const QWidget *, QHash<QString, QString> > m_attributeCache;
       
  1516 };
       
  1517 
       
  1518 QVector<QCss::StyleRule> QStyleSheetStyle::styleRules(const QWidget *w) const
       
  1519 {
       
  1520     QHash<const QWidget *, QVector<StyleRule> >::const_iterator cacheIt = styleRulesCache->constFind(w);
       
  1521     if (cacheIt != styleRulesCache->constEnd())
       
  1522         return cacheIt.value();
       
  1523 
       
  1524     if (!initWidget(w)) {
       
  1525         return QVector<StyleRule>();
       
  1526     }
       
  1527 
       
  1528     QStyleSheetStyleSelector styleSelector;
       
  1529 
       
  1530     StyleSheet defaultSs;
       
  1531     QHash<const void *, StyleSheet>::const_iterator defaultCacheIt = styleSheetCache->constFind(baseStyle());
       
  1532     if (defaultCacheIt == styleSheetCache->constEnd()) {
       
  1533         defaultSs = getDefaultStyleSheet();
       
  1534         styleSheetCache->insert(baseStyle(), defaultSs);
       
  1535     } else {
       
  1536         defaultSs = defaultCacheIt.value();
       
  1537     }
       
  1538     styleSelector.styleSheets += defaultSs;
       
  1539 
       
  1540     if (!qApp->styleSheet().isEmpty()) {
       
  1541         StyleSheet appSs;
       
  1542         QHash<const void *, StyleSheet>::const_iterator appCacheIt = styleSheetCache->constFind(qApp);
       
  1543         if (appCacheIt == styleSheetCache->constEnd()) {
       
  1544             QString ss = qApp->styleSheet();
       
  1545             if (ss.startsWith(QLatin1String("file:///")))
       
  1546                 ss.remove(0, 8);
       
  1547             parser.init(ss, qApp->styleSheet() != ss);
       
  1548             if (!parser.parse(&appSs))
       
  1549                 qWarning("Could not parse application stylesheet");
       
  1550             appSs.origin = StyleSheetOrigin_Inline;
       
  1551             appSs.depth = 1;
       
  1552             styleSheetCache->insert(qApp, appSs);
       
  1553         } else {
       
  1554             appSs = appCacheIt.value();
       
  1555         }
       
  1556         styleSelector.styleSheets += appSs;
       
  1557     }
       
  1558 
       
  1559     QVector<QCss::StyleSheet> widgetSs;
       
  1560     for (const QWidget *wid = w; wid; wid = parentWidget(wid)) {
       
  1561         if (wid->styleSheet().isEmpty())
       
  1562             continue;
       
  1563         StyleSheet ss;
       
  1564         QHash<const void *, StyleSheet>::const_iterator widCacheIt = styleSheetCache->constFind(wid);
       
  1565         if (widCacheIt == styleSheetCache->constEnd()) {
       
  1566             parser.init(wid->styleSheet());
       
  1567             if (!parser.parse(&ss)) {
       
  1568                 parser.init(QLatin1String("* {") + wid->styleSheet() + QLatin1Char('}'));
       
  1569                 if (!parser.parse(&ss))
       
  1570                    qWarning("Could not parse stylesheet of widget %p", wid);
       
  1571             }
       
  1572             ss.origin = StyleSheetOrigin_Inline;
       
  1573             styleSheetCache->insert(wid, ss);
       
  1574         } else {
       
  1575             ss = widCacheIt.value();
       
  1576         }
       
  1577         widgetSs.append(ss);
       
  1578     }
       
  1579 
       
  1580     for (int i = 0; i < widgetSs.count(); i++)
       
  1581         widgetSs[i].depth = widgetSs.count() - i + 2;
       
  1582 
       
  1583     styleSelector.styleSheets += widgetSs;
       
  1584 
       
  1585     StyleSelector::NodePtr n;
       
  1586     n.ptr = (void *)w;
       
  1587     QVector<QCss::StyleRule> rules = styleSelector.styleRulesForNode(n);
       
  1588     styleRulesCache->insert(w, rules);
       
  1589     return rules;
       
  1590 }
       
  1591 
       
  1592 /////////////////////////////////////////////////////////////////////////////////////////
       
  1593 // Rendering rules
       
  1594 static QVector<Declaration> declarations(const QVector<StyleRule> &styleRules, const QString &part, quint64 pseudoClass = PseudoClass_Unspecified)
       
  1595 {
       
  1596     QVector<Declaration> decls;
       
  1597     for (int i = 0; i < styleRules.count(); i++) {
       
  1598         const Selector& selector = styleRules.at(i).selectors.at(0);
       
  1599         // Rules with pseudo elements don't cascade. This is an intentional
       
  1600         // diversion for CSS
       
  1601         if (part.compare(selector.pseudoElement(), Qt::CaseInsensitive) != 0)
       
  1602             continue;
       
  1603         quint64 negated = 0;
       
  1604         quint64 cssClass = selector.pseudoClass(&negated);
       
  1605         if ((pseudoClass == PseudoClass_Any) || (cssClass == PseudoClass_Unspecified)
       
  1606             || ((((cssClass & pseudoClass) == cssClass)) && ((negated & pseudoClass) == 0)))
       
  1607             decls += styleRules.at(i).declarations;
       
  1608     }
       
  1609     return decls;
       
  1610 }
       
  1611 
       
  1612 int QStyleSheetStyle::nativeFrameWidth(const QWidget *w)
       
  1613 {
       
  1614     QStyle *base = baseStyle();
       
  1615 
       
  1616 #ifndef QT_NO_SPINBOX
       
  1617     if (qobject_cast<const QAbstractSpinBox *>(w))
       
  1618         return base->pixelMetric(QStyle::PM_SpinBoxFrameWidth, 0, w);
       
  1619 #endif
       
  1620 
       
  1621 #ifndef QT_NO_COMBOBOX
       
  1622     if (qobject_cast<const QComboBox *>(w))
       
  1623         return base->pixelMetric(QStyle::PM_ComboBoxFrameWidth, 0, w);
       
  1624 #endif
       
  1625 
       
  1626 #ifndef QT_NO_MENU
       
  1627     if (qobject_cast<const QMenu *>(w))
       
  1628         return base->pixelMetric(QStyle::PM_MenuPanelWidth, 0, w);
       
  1629 #endif
       
  1630 
       
  1631 #ifndef QT_NO_MENUBAR
       
  1632     if (qobject_cast<const QMenuBar *>(w))
       
  1633         return base->pixelMetric(QStyle::PM_MenuBarPanelWidth, 0, w);
       
  1634 #endif
       
  1635 #ifndef QT_NO_FRAME
       
  1636     if (const QFrame *frame = qobject_cast<const QFrame *>(w)) {
       
  1637         if (frame->frameShape() == QFrame::NoFrame)
       
  1638             return 0;
       
  1639     }
       
  1640 #endif
       
  1641 
       
  1642     if (qstrcmp(w->metaObject()->className(), "QTipLabel") == 0)
       
  1643         return base->pixelMetric(QStyle::PM_ToolTipLabelFrameWidth, 0, w);
       
  1644 
       
  1645     return base->pixelMetric(QStyle::PM_DefaultFrameWidth, 0, w);
       
  1646 }
       
  1647 
       
  1648 static quint64 pseudoClass(QStyle::State state)
       
  1649 {
       
  1650     quint64 pc = 0;
       
  1651     if (state & QStyle::State_Enabled) {
       
  1652         pc |= PseudoClass_Enabled;
       
  1653         if (state & QStyle::State_MouseOver)
       
  1654             pc |= PseudoClass_Hover;
       
  1655     } else {
       
  1656         pc |= PseudoClass_Disabled;
       
  1657     }
       
  1658     if (state & QStyle::State_Active)
       
  1659         pc |= PseudoClass_Active;
       
  1660     if (state & QStyle::State_Window)
       
  1661         pc |= PseudoClass_Window;
       
  1662     if (state & QStyle::State_Sunken)
       
  1663         pc |= PseudoClass_Pressed;
       
  1664     if (state & QStyle::State_HasFocus)
       
  1665         pc |= PseudoClass_Focus;
       
  1666     if (state & QStyle::State_On)
       
  1667         pc |= (PseudoClass_On | PseudoClass_Checked);
       
  1668     if (state & QStyle::State_Off)
       
  1669         pc |= (PseudoClass_Off | PseudoClass_Unchecked);
       
  1670     if (state & QStyle::State_NoChange)
       
  1671         pc |= PseudoClass_Indeterminate;
       
  1672     if (state & QStyle::State_Selected)
       
  1673         pc |= PseudoClass_Selected;
       
  1674     if (state & QStyle::State_Horizontal)
       
  1675         pc |= PseudoClass_Horizontal;
       
  1676     else
       
  1677         pc |= PseudoClass_Vertical;
       
  1678     if (state & (QStyle::State_Open | QStyle::State_On | QStyle::State_Sunken))
       
  1679         pc |= PseudoClass_Open;
       
  1680     else
       
  1681         pc |= PseudoClass_Closed;
       
  1682     if (state & QStyle::State_Children)
       
  1683         pc |= PseudoClass_Children;
       
  1684     if (state & QStyle::State_Sibling)
       
  1685         pc |= PseudoClass_Sibling;
       
  1686     if (state & QStyle::State_ReadOnly)
       
  1687         pc |= PseudoClass_ReadOnly;
       
  1688     if (state & QStyle::State_Item)
       
  1689         pc |= PseudoClass_Item;
       
  1690 #ifdef QT_KEYPAD_NAVIGATION
       
  1691     if (state & QStyle::State_HasEditFocus)
       
  1692         pc |= PseudoClass_EditFocus;
       
  1693 #endif
       
  1694     return pc;
       
  1695 }
       
  1696 
       
  1697 static void qt_check_if_internal_widget(const QWidget **w, int *element)
       
  1698 {
       
  1699 #ifdef QT_NO_DOCKWIDGET
       
  1700     Q_UNUSED(w);
       
  1701     Q_UNUSED(element);
       
  1702 #else
       
  1703     if (*w && qstrcmp((*w)->metaObject()->className(), "QDockWidgetTitleButton") == 0) {
       
  1704         if ((*w)->objectName() == QLatin1String("qt_dockwidget_closebutton")) {
       
  1705             *element = PseudoElement_DockWidgetCloseButton;
       
  1706         } else if ((*w)->objectName() == QLatin1String("qt_dockwidget_floatbutton")) {
       
  1707             *element = PseudoElement_DockWidgetFloatButton;
       
  1708         }
       
  1709         *w = (*w)->parentWidget();
       
  1710     }
       
  1711 #endif
       
  1712 }
       
  1713 
       
  1714 QRenderRule QStyleSheetStyle::renderRule(const QWidget *w, int element, quint64 state) const
       
  1715 {
       
  1716     qt_check_if_internal_widget(&w, &element);
       
  1717     QHash<quint64, QRenderRule> &cache = (*renderRulesCache)[w][element];
       
  1718     QHash<quint64, QRenderRule>::const_iterator cacheIt = cache.constFind(state);
       
  1719     if (cacheIt != cache.constEnd())
       
  1720         return cacheIt.value();
       
  1721 
       
  1722     if (!initWidget(w))
       
  1723         return QRenderRule();
       
  1724 
       
  1725     quint64 stateMask = 0;
       
  1726     const QVector<StyleRule> rules = styleRules(w);
       
  1727     for (int i = 0; i < rules.count(); i++) {
       
  1728         const Selector& selector = rules.at(i).selectors.at(0);
       
  1729         quint64 negated = 0;
       
  1730         stateMask |= selector.pseudoClass(&negated);
       
  1731         stateMask |= negated;
       
  1732     }
       
  1733 
       
  1734     cacheIt = cache.constFind(state & stateMask);
       
  1735     if (cacheIt != cache.constEnd()) {
       
  1736         const QRenderRule &newRule = cacheIt.value();
       
  1737         cache[state] = newRule;
       
  1738         return newRule;
       
  1739     }
       
  1740 
       
  1741 
       
  1742     const QString part = QLatin1String(knownPseudoElements[element].name);
       
  1743     QVector<Declaration> decls = declarations(rules, part, state);
       
  1744     QRenderRule newRule(decls, w);
       
  1745     cache[state] = newRule;
       
  1746     if ((state & stateMask) != state)
       
  1747         cache[state&stateMask] = newRule;
       
  1748     return newRule;
       
  1749 }
       
  1750 
       
  1751 QRenderRule QStyleSheetStyle::renderRule(const QWidget *w, const QStyleOption *opt, int pseudoElement) const
       
  1752 {
       
  1753     quint64 extraClass = 0;
       
  1754     QStyle::State state = opt ? opt->state : QStyle::State(QStyle::State_None);
       
  1755 
       
  1756     if (const QStyleOptionComplex *complex = qstyleoption_cast<const QStyleOptionComplex *>(opt)) {
       
  1757         if (pseudoElement != PseudoElement_None) {
       
  1758             // if not an active subcontrol, just pass enabled/disabled
       
  1759             QStyle::SubControl subControl = knownPseudoElements[pseudoElement].subControl;
       
  1760 
       
  1761             if (!(complex->activeSubControls & subControl))
       
  1762                 state &= (QStyle::State_Enabled | QStyle::State_Horizontal | QStyle::State_HasFocus);
       
  1763         }
       
  1764 
       
  1765         switch (pseudoElement) {
       
  1766         case PseudoElement_ComboBoxDropDown:
       
  1767         case PseudoElement_ComboBoxArrow:
       
  1768             state |= (complex->state & (QStyle::State_On|QStyle::State_ReadOnly));
       
  1769             break;
       
  1770         case PseudoElement_SpinBoxUpButton:
       
  1771         case PseudoElement_SpinBoxDownButton:
       
  1772         case PseudoElement_SpinBoxUpArrow:
       
  1773         case PseudoElement_SpinBoxDownArrow:
       
  1774 #ifndef QT_NO_SPINBOX
       
  1775             if (const QStyleOptionSpinBox *sb = qstyleoption_cast<const QStyleOptionSpinBox *>(opt)) {
       
  1776                 bool on = false;
       
  1777                 bool up = pseudoElement == PseudoElement_SpinBoxUpButton
       
  1778                           || pseudoElement == PseudoElement_SpinBoxUpArrow;
       
  1779                 if ((sb->stepEnabled & QAbstractSpinBox::StepUpEnabled) && up)
       
  1780                     on = true;
       
  1781                 else if ((sb->stepEnabled & QAbstractSpinBox::StepDownEnabled) && !up)
       
  1782                     on = true;
       
  1783                 state |= (on ? QStyle::State_On : QStyle::State_Off);
       
  1784             }
       
  1785 #endif // QT_NO_SPINBOX
       
  1786             break;
       
  1787         case PseudoElement_GroupBoxTitle:
       
  1788             state |= (complex->state & (QStyle::State_MouseOver | QStyle::State_Sunken));
       
  1789             break;
       
  1790         case PseudoElement_ToolButtonMenu:
       
  1791         case PseudoElement_ToolButtonMenuArrow:
       
  1792         case PseudoElement_ToolButtonDownArrow:
       
  1793             state |= complex->state & QStyle::State_MouseOver;
       
  1794             if (complex->state & QStyle::State_Sunken ||
       
  1795                 complex->activeSubControls & QStyle::SC_ToolButtonMenu)
       
  1796                 state |= QStyle::State_Sunken;
       
  1797             break;
       
  1798         case PseudoElement_SliderGroove:
       
  1799             state |= complex->state & QStyle::State_MouseOver;
       
  1800             break;
       
  1801         default:
       
  1802             break;
       
  1803         }
       
  1804 
       
  1805         if (const QStyleOptionComboBox *combo = qstyleoption_cast<const QStyleOptionComboBox *>(opt)) {
       
  1806             // QStyle::State_On is set when the popup is being shown
       
  1807             // Propagate EditField Pressed state
       
  1808             if (pseudoElement == PseudoElement_None
       
  1809                 && (complex->activeSubControls & QStyle::SC_ComboBoxEditField)
       
  1810                 && (!(state & QStyle::State_MouseOver))) {
       
  1811                 state |= QStyle::State_Sunken;
       
  1812             }
       
  1813 
       
  1814             if (!combo->frame)
       
  1815                 extraClass |= PseudoClass_Frameless;
       
  1816             if (!combo->editable)
       
  1817                 extraClass |= PseudoClass_ReadOnly;
       
  1818             else
       
  1819                 extraClass |= PseudoClass_Editable;
       
  1820 #ifndef QT_NO_SPINBOX
       
  1821         } else if (const QStyleOptionSpinBox *spin = qstyleoption_cast<const QStyleOptionSpinBox *>(opt)) {
       
  1822             if (!spin->frame)
       
  1823                 extraClass |= PseudoClass_Frameless;
       
  1824 #endif // QT_NO_SPINBOX
       
  1825         } else if (const QStyleOptionGroupBox *gb = qstyleoption_cast<const QStyleOptionGroupBox *>(opt)) {
       
  1826             if (gb->features & QStyleOptionFrameV2::Flat)
       
  1827                 extraClass |= PseudoClass_Flat;
       
  1828             if (gb->lineWidth == 0)
       
  1829                 extraClass |= PseudoClass_Frameless;
       
  1830         } else if (const QStyleOptionTitleBar *tb = qstyleoption_cast<const QStyleOptionTitleBar *>(opt)) {
       
  1831             if (tb->titleBarState & Qt::WindowMinimized) {
       
  1832                 extraClass |= PseudoClass_Minimized;
       
  1833             }
       
  1834             else if (tb->titleBarState & Qt::WindowMaximized)
       
  1835                 extraClass |= PseudoClass_Maximized;
       
  1836         }
       
  1837     } else {
       
  1838         // handle simple style options
       
  1839         if (const QStyleOptionMenuItem *mi = qstyleoption_cast<const QStyleOptionMenuItem *>(opt)) {
       
  1840             if (mi->menuItemType == QStyleOptionMenuItem::DefaultItem)
       
  1841                 extraClass |= PseudoClass_Default;
       
  1842             if (mi->checkType == QStyleOptionMenuItem::Exclusive)
       
  1843                 extraClass |= PseudoClass_Exclusive;
       
  1844             else if (mi->checkType == QStyleOptionMenuItem::NonExclusive)
       
  1845                 extraClass |= PseudoClass_NonExclusive;
       
  1846             if (mi->checkType != QStyleOptionMenuItem::NotCheckable)
       
  1847                 extraClass |= (mi->checked) ? (PseudoClass_On|PseudoClass_Checked)
       
  1848                                             : (PseudoClass_Off|PseudoClass_Unchecked);
       
  1849         } else if (const QStyleOptionHeader *hdr = qstyleoption_cast<const QStyleOptionHeader *>(opt)) {
       
  1850             if (hdr->position == QStyleOptionHeader::OnlyOneSection)
       
  1851                 extraClass |= PseudoClass_OnlyOne;
       
  1852             else if (hdr->position == QStyleOptionHeader::Beginning)
       
  1853                 extraClass |= PseudoClass_First;
       
  1854             else if (hdr->position == QStyleOptionHeader::End)
       
  1855                 extraClass |= PseudoClass_Last;
       
  1856             else if (hdr->position == QStyleOptionHeader::Middle)
       
  1857                 extraClass |= PseudoClass_Middle;
       
  1858 
       
  1859             if (hdr->selectedPosition == QStyleOptionHeader::NextAndPreviousAreSelected)
       
  1860                 extraClass |= (PseudoClass_NextSelected | PseudoClass_PreviousSelected);
       
  1861             else if (hdr->selectedPosition == QStyleOptionHeader::NextIsSelected)
       
  1862                 extraClass |= PseudoClass_NextSelected;
       
  1863             else if (hdr->selectedPosition == QStyleOptionHeader::PreviousIsSelected)
       
  1864                 extraClass |= PseudoClass_PreviousSelected;
       
  1865 #ifndef QT_NO_TABWIDGET
       
  1866         } else if (const QStyleOptionTabWidgetFrame *tab = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(opt)) {
       
  1867             switch (tab->shape) {
       
  1868                 case QTabBar::RoundedNorth:
       
  1869                 case QTabBar::TriangularNorth:
       
  1870                     extraClass |= PseudoClass_Top;
       
  1871                     break;
       
  1872                 case QTabBar::RoundedSouth:
       
  1873                 case QTabBar::TriangularSouth:
       
  1874                     extraClass |= PseudoClass_Bottom;
       
  1875                     break;
       
  1876                 case QTabBar::RoundedEast:
       
  1877                 case QTabBar::TriangularEast:
       
  1878                     extraClass |= PseudoClass_Left;
       
  1879                     break;
       
  1880                 case QTabBar::RoundedWest:
       
  1881                 case QTabBar::TriangularWest:
       
  1882                     extraClass |= PseudoClass_Right;
       
  1883                     break;
       
  1884                 default:
       
  1885                     break;
       
  1886             }
       
  1887 #endif
       
  1888 #ifndef QT_NO_TABBAR
       
  1889         } else if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(opt)) {
       
  1890             if (tab->position == QStyleOptionTab::OnlyOneTab)
       
  1891                 extraClass |= PseudoClass_OnlyOne;
       
  1892             else if (tab->position == QStyleOptionTab::Beginning)
       
  1893                 extraClass |= PseudoClass_First;
       
  1894             else if (tab->position == QStyleOptionTab::End)
       
  1895                 extraClass |= PseudoClass_Last;
       
  1896             else if (tab->position == QStyleOptionTab::Middle)
       
  1897                 extraClass |= PseudoClass_Middle;
       
  1898 
       
  1899             if (tab->selectedPosition == QStyleOptionTab::NextIsSelected)
       
  1900                 extraClass |= PseudoClass_NextSelected;
       
  1901             else if (tab->selectedPosition == QStyleOptionTab::PreviousIsSelected)
       
  1902                 extraClass |= PseudoClass_PreviousSelected;
       
  1903 
       
  1904             switch (tab->shape) {
       
  1905                 case QTabBar::RoundedNorth:
       
  1906                 case QTabBar::TriangularNorth:
       
  1907                     extraClass |= PseudoClass_Top;
       
  1908                     break;
       
  1909                 case QTabBar::RoundedSouth:
       
  1910                 case QTabBar::TriangularSouth:
       
  1911                     extraClass |= PseudoClass_Bottom;
       
  1912                     break;
       
  1913                 case QTabBar::RoundedEast:
       
  1914                 case QTabBar::TriangularEast:
       
  1915                     extraClass |= PseudoClass_Left;
       
  1916                     break;
       
  1917                 case QTabBar::RoundedWest:
       
  1918                 case QTabBar::TriangularWest:
       
  1919                     extraClass |= PseudoClass_Right;
       
  1920                     break;
       
  1921                 default:
       
  1922                     break;
       
  1923             }
       
  1924 #endif // QT_NO_TABBAR
       
  1925         } else if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
       
  1926             if (btn->features & QStyleOptionButton::Flat)
       
  1927                 extraClass |= PseudoClass_Flat;
       
  1928             if (btn->features & QStyleOptionButton::DefaultButton)
       
  1929                 extraClass |= PseudoClass_Default;
       
  1930         } else if (const QStyleOptionFrame *frm = qstyleoption_cast<const QStyleOptionFrame *>(opt)) {
       
  1931             if (frm->lineWidth == 0)
       
  1932                 extraClass |= PseudoClass_Frameless;
       
  1933             if (const QStyleOptionFrameV2 *frame2 = qstyleoption_cast<const QStyleOptionFrameV2 *>(opt)) {
       
  1934                 if (frame2->features & QStyleOptionFrameV2::Flat)
       
  1935                     extraClass |= PseudoClass_Flat;
       
  1936             }
       
  1937         }
       
  1938 #ifndef QT_NO_TOOLBAR
       
  1939         else if (const QStyleOptionToolBar *tb = qstyleoption_cast<const QStyleOptionToolBar *>(opt)) {
       
  1940             if (tb->toolBarArea == Qt::LeftToolBarArea)
       
  1941                 extraClass |= PseudoClass_Left;
       
  1942             else if (tb->toolBarArea == Qt::RightToolBarArea)
       
  1943                 extraClass |= PseudoClass_Right;
       
  1944             else if (tb->toolBarArea == Qt::TopToolBarArea)
       
  1945                 extraClass |= PseudoClass_Top;
       
  1946             else if (tb->toolBarArea == Qt::BottomToolBarArea)
       
  1947                 extraClass |= PseudoClass_Bottom;
       
  1948 
       
  1949             if (tb->positionWithinLine == QStyleOptionToolBar::Beginning)
       
  1950                 extraClass |= PseudoClass_First;
       
  1951             else if (tb->positionWithinLine == QStyleOptionToolBar::Middle)
       
  1952                 extraClass |= PseudoClass_Middle;
       
  1953             else if (tb->positionWithinLine == QStyleOptionToolBar::End)
       
  1954                 extraClass |= PseudoClass_Last;
       
  1955             else if (tb->positionWithinLine == QStyleOptionToolBar::OnlyOne)
       
  1956                 extraClass |= PseudoClass_OnlyOne;
       
  1957         }
       
  1958 #endif // QT_NO_TOOLBAR
       
  1959 #ifndef QT_NO_TOOLBOX
       
  1960         else if (const QStyleOptionToolBoxV2 *tab = qstyleoption_cast<const QStyleOptionToolBoxV2 *>(opt)) {
       
  1961             if (tab->position == QStyleOptionToolBoxV2::OnlyOneTab)
       
  1962                 extraClass |= PseudoClass_OnlyOne;
       
  1963             else if (tab->position == QStyleOptionToolBoxV2::Beginning)
       
  1964                 extraClass |= PseudoClass_First;
       
  1965             else if (tab->position == QStyleOptionToolBoxV2::End)
       
  1966                 extraClass |= PseudoClass_Last;
       
  1967             else if (tab->position == QStyleOptionToolBoxV2::Middle)
       
  1968                 extraClass |= PseudoClass_Middle;
       
  1969 
       
  1970             if (tab->selectedPosition == QStyleOptionToolBoxV2::NextIsSelected)
       
  1971                 extraClass |= PseudoClass_NextSelected;
       
  1972             else if (tab->selectedPosition == QStyleOptionToolBoxV2::PreviousIsSelected)
       
  1973                 extraClass |= PseudoClass_PreviousSelected;
       
  1974         }
       
  1975 #endif // QT_NO_TOOLBOX
       
  1976 #ifndef QT_NO_DOCKWIDGET
       
  1977         else if (const QStyleOptionDockWidgetV2 *dw = qstyleoption_cast<const QStyleOptionDockWidgetV2 *>(opt)) {
       
  1978             if (dw->verticalTitleBar)
       
  1979                 extraClass |= PseudoClass_Vertical;
       
  1980             else
       
  1981                 extraClass |= PseudoClass_Horizontal;
       
  1982             if (dw->closable)
       
  1983                 extraClass |= PseudoClass_Closable;
       
  1984             if (dw->floatable)
       
  1985                 extraClass |= PseudoClass_Floatable;
       
  1986             if (dw->movable)
       
  1987                 extraClass |= PseudoClass_Movable;
       
  1988         }
       
  1989 #endif // QT_NO_DOCKWIDGET
       
  1990 #ifndef QT_NO_ITEMVIEWS
       
  1991         else if (const QStyleOptionViewItemV2 *v2 = qstyleoption_cast<const QStyleOptionViewItemV2 *>(opt)) {
       
  1992             if (v2->features & QStyleOptionViewItemV2::Alternate)
       
  1993                 extraClass |= PseudoClass_Alternate;
       
  1994             if (const QStyleOptionViewItemV4 *v4 = qstyleoption_cast<const QStyleOptionViewItemV4 *>(opt)) {
       
  1995                 if (v4->viewItemPosition == QStyleOptionViewItemV4::OnlyOne)
       
  1996                     extraClass |= PseudoClass_OnlyOne;
       
  1997                 else if (v4->viewItemPosition == QStyleOptionViewItemV4::Beginning)
       
  1998                     extraClass |= PseudoClass_First;
       
  1999                 else if (v4->viewItemPosition == QStyleOptionViewItemV4::End)
       
  2000                     extraClass |= PseudoClass_Last;
       
  2001                 else if (v4->viewItemPosition == QStyleOptionViewItemV4::Middle)
       
  2002                     extraClass |= PseudoClass_Middle;
       
  2003             }
       
  2004         }
       
  2005 #endif
       
  2006 #ifndef QT_NO_LINEEDIT
       
  2007         // LineEdit sets Sunken flag to indicate Sunken frame (argh)
       
  2008         if (const QLineEdit *lineEdit = qobject_cast<const QLineEdit *>(w)) {
       
  2009             state &= ~QStyle::State_Sunken;
       
  2010             if (lineEdit->hasFrame()) {
       
  2011                 extraClass &= ~PseudoClass_Frameless;
       
  2012             } else {
       
  2013                 extraClass |= PseudoClass_Frameless;
       
  2014             }
       
  2015         } else
       
  2016 #endif
       
  2017         if (const QFrame *frm = qobject_cast<const QFrame *>(w)) {
       
  2018             if (frm->lineWidth() == 0)
       
  2019                 extraClass |= PseudoClass_Frameless;
       
  2020         }
       
  2021     }
       
  2022 
       
  2023     return renderRule(w, pseudoElement, pseudoClass(state) | extraClass);
       
  2024 }
       
  2025 
       
  2026 bool QStyleSheetStyle::hasStyleRule(const QWidget *w, int part) const
       
  2027 {
       
  2028     QHash<int, bool> &cache = (*hasStyleRuleCache)[w];
       
  2029     QHash<int, bool>::const_iterator cacheIt = cache.constFind(part);
       
  2030     if (cacheIt != cache.constEnd())
       
  2031         return cacheIt.value();
       
  2032 
       
  2033     if (!initWidget(w))
       
  2034         return false;
       
  2035 
       
  2036 
       
  2037     const QVector<StyleRule> &rules = styleRules(w);
       
  2038     if (part == PseudoElement_None) {
       
  2039         bool result = w && !rules.isEmpty();
       
  2040         cache[part] = result;
       
  2041         return result;
       
  2042     }
       
  2043 
       
  2044     QString pseudoElement = QLatin1String(knownPseudoElements[part].name);
       
  2045     QVector<Declaration> declarations;
       
  2046     for (int i = 0; i < rules.count(); i++) {
       
  2047         const Selector& selector = rules.at(i).selectors.at(0);
       
  2048         if (pseudoElement.compare(selector.pseudoElement(), Qt::CaseInsensitive) == 0) {
       
  2049             cache[part] = true;
       
  2050             return true;
       
  2051         }
       
  2052     }
       
  2053 
       
  2054     cache[part] = false;
       
  2055     return false;
       
  2056 }
       
  2057 
       
  2058 static Origin defaultOrigin(int pe)
       
  2059 {
       
  2060     switch (pe) {
       
  2061     case PseudoElement_ScrollBarAddPage:
       
  2062     case PseudoElement_ScrollBarSubPage:
       
  2063     case PseudoElement_ScrollBarAddLine:
       
  2064     case PseudoElement_ScrollBarSubLine:
       
  2065     case PseudoElement_ScrollBarFirst:
       
  2066     case PseudoElement_ScrollBarLast:
       
  2067     case PseudoElement_GroupBoxTitle:
       
  2068     case PseudoElement_GroupBoxIndicator: // never used
       
  2069     case PseudoElement_ToolButtonMenu:
       
  2070     case PseudoElement_SliderAddPage:
       
  2071     case PseudoElement_SliderSubPage:
       
  2072         return Origin_Border;
       
  2073 
       
  2074     case PseudoElement_SpinBoxUpButton:
       
  2075     case PseudoElement_SpinBoxDownButton:
       
  2076     case PseudoElement_PushButtonMenuIndicator:
       
  2077     case PseudoElement_ComboBoxDropDown:
       
  2078     case PseudoElement_ToolButtonDownArrow:
       
  2079     case PseudoElement_MenuCheckMark:
       
  2080     case PseudoElement_MenuIcon:
       
  2081     case PseudoElement_MenuRightArrow:
       
  2082         return Origin_Padding;
       
  2083 
       
  2084     case PseudoElement_Indicator:
       
  2085     case PseudoElement_ExclusiveIndicator:
       
  2086     case PseudoElement_ComboBoxArrow:
       
  2087     case PseudoElement_ScrollBarSlider:
       
  2088     case PseudoElement_ScrollBarUpArrow:
       
  2089     case PseudoElement_ScrollBarDownArrow:
       
  2090     case PseudoElement_ScrollBarLeftArrow:
       
  2091     case PseudoElement_ScrollBarRightArrow:
       
  2092     case PseudoElement_SpinBoxUpArrow:
       
  2093     case PseudoElement_SpinBoxDownArrow:
       
  2094     case PseudoElement_ToolButtonMenuArrow:
       
  2095     case PseudoElement_HeaderViewUpArrow:
       
  2096     case PseudoElement_HeaderViewDownArrow:
       
  2097     case PseudoElement_SliderGroove:
       
  2098     case PseudoElement_SliderHandle:
       
  2099         return Origin_Content;
       
  2100 
       
  2101     default:
       
  2102         return Origin_Margin;
       
  2103     }
       
  2104 }
       
  2105 
       
  2106 static Qt::Alignment defaultPosition(int pe)
       
  2107 {
       
  2108     switch (pe) {
       
  2109     case PseudoElement_Indicator:
       
  2110     case PseudoElement_ExclusiveIndicator:
       
  2111     case PseudoElement_MenuCheckMark:
       
  2112     case PseudoElement_MenuIcon:
       
  2113         return Qt::AlignLeft | Qt::AlignVCenter;
       
  2114 
       
  2115     case PseudoElement_ScrollBarAddLine:
       
  2116     case PseudoElement_ScrollBarLast:
       
  2117     case PseudoElement_SpinBoxDownButton:
       
  2118     case PseudoElement_PushButtonMenuIndicator:
       
  2119     case PseudoElement_ToolButtonDownArrow:
       
  2120         return Qt::AlignRight | Qt::AlignBottom;
       
  2121 
       
  2122     case PseudoElement_ScrollBarSubLine:
       
  2123     case PseudoElement_ScrollBarFirst:
       
  2124     case PseudoElement_SpinBoxUpButton:
       
  2125     case PseudoElement_ComboBoxDropDown:
       
  2126     case PseudoElement_ToolButtonMenu:
       
  2127     case PseudoElement_DockWidgetCloseButton:
       
  2128     case PseudoElement_DockWidgetFloatButton:
       
  2129         return Qt::AlignRight | Qt::AlignTop;
       
  2130 
       
  2131     case PseudoElement_ScrollBarUpArrow:
       
  2132     case PseudoElement_ScrollBarDownArrow:
       
  2133     case PseudoElement_ScrollBarLeftArrow:
       
  2134     case PseudoElement_ScrollBarRightArrow:
       
  2135     case PseudoElement_SpinBoxUpArrow:
       
  2136     case PseudoElement_SpinBoxDownArrow:
       
  2137     case PseudoElement_ComboBoxArrow:
       
  2138     case PseudoElement_DownArrow:
       
  2139     case PseudoElement_ToolButtonMenuArrow:
       
  2140     case PseudoElement_SliderGroove:
       
  2141         return Qt::AlignCenter;
       
  2142 
       
  2143     case PseudoElement_GroupBoxTitle:
       
  2144     case PseudoElement_GroupBoxIndicator: // never used
       
  2145         return Qt::AlignLeft | Qt::AlignTop;
       
  2146 
       
  2147     case PseudoElement_HeaderViewUpArrow:
       
  2148     case PseudoElement_HeaderViewDownArrow:
       
  2149     case PseudoElement_MenuRightArrow:
       
  2150         return Qt::AlignRight | Qt::AlignVCenter;
       
  2151 
       
  2152     default:
       
  2153         return 0;
       
  2154     }
       
  2155 }
       
  2156 
       
  2157 QSize QStyleSheetStyle::defaultSize(const QWidget *w, QSize sz, const QRect& rect, int pe) const
       
  2158 {
       
  2159     QStyle *base = baseStyle();
       
  2160 
       
  2161     switch (pe) {
       
  2162     case PseudoElement_Indicator:
       
  2163     case PseudoElement_MenuCheckMark:
       
  2164         if (sz.width() == -1)
       
  2165             sz.setWidth(base->pixelMetric(PM_IndicatorWidth, 0, w));
       
  2166         if (sz.height() == -1)
       
  2167             sz.setHeight(base->pixelMetric(PM_IndicatorHeight, 0, w));
       
  2168         break;
       
  2169 
       
  2170     case PseudoElement_ExclusiveIndicator:
       
  2171     case PseudoElement_GroupBoxIndicator:
       
  2172         if (sz.width() == -1)
       
  2173             sz.setWidth(base->pixelMetric(PM_ExclusiveIndicatorWidth, 0, w));
       
  2174         if (sz.height() == -1)
       
  2175             sz.setHeight(base->pixelMetric(PM_ExclusiveIndicatorHeight, 0, w));
       
  2176         break;
       
  2177 
       
  2178     case PseudoElement_PushButtonMenuIndicator: {
       
  2179         int pm = base->pixelMetric(PM_MenuButtonIndicator, 0, w);
       
  2180         if (sz.width() == -1)
       
  2181             sz.setWidth(pm);
       
  2182         if (sz.height() == -1)
       
  2183             sz.setHeight(pm);
       
  2184                                       }
       
  2185         break;
       
  2186 
       
  2187     case PseudoElement_ComboBoxDropDown:
       
  2188         if (sz.width() == -1)
       
  2189             sz.setWidth(16);
       
  2190         break;
       
  2191 
       
  2192     case PseudoElement_ComboBoxArrow:
       
  2193     case PseudoElement_DownArrow:
       
  2194     case PseudoElement_ToolButtonMenuArrow:
       
  2195     case PseudoElement_ToolButtonDownArrow:
       
  2196     case PseudoElement_MenuRightArrow:
       
  2197         if (sz.width() == -1)
       
  2198             sz.setWidth(13);
       
  2199         if (sz.height() == -1)
       
  2200             sz.setHeight(13);
       
  2201         break;
       
  2202 
       
  2203     case PseudoElement_SpinBoxUpButton:
       
  2204     case PseudoElement_SpinBoxDownButton:
       
  2205         if (sz.width() == -1)
       
  2206             sz.setWidth(16);
       
  2207         if (sz.height() == -1)
       
  2208             sz.setHeight(rect.height()/2);
       
  2209         break;
       
  2210 
       
  2211     case PseudoElement_ToolButtonMenu:
       
  2212         if (sz.width() == -1)
       
  2213             sz.setWidth(base->pixelMetric(PM_MenuButtonIndicator, 0, w));
       
  2214         break;
       
  2215 
       
  2216     case PseudoElement_HeaderViewUpArrow:
       
  2217     case PseudoElement_HeaderViewDownArrow: {
       
  2218         int pm = base->pixelMetric(PM_HeaderMargin, 0, w);
       
  2219         if (sz.width() == -1)
       
  2220             sz.setWidth(pm);
       
  2221         if (sz.height() == 1)
       
  2222             sz.setHeight(pm);
       
  2223         break;
       
  2224                                             }
       
  2225 
       
  2226     case PseudoElement_ScrollBarFirst:
       
  2227     case PseudoElement_ScrollBarLast:
       
  2228     case PseudoElement_ScrollBarAddLine:
       
  2229     case PseudoElement_ScrollBarSubLine:
       
  2230     case PseudoElement_ScrollBarSlider: {
       
  2231         int pm = pixelMetric(QStyle::PM_ScrollBarExtent, 0, w);
       
  2232         if (sz.width() == -1)
       
  2233             sz.setWidth(pm);
       
  2234         if (sz.height() == -1)
       
  2235             sz.setHeight(pm);
       
  2236         break;
       
  2237                                         }
       
  2238 
       
  2239     case PseudoElement_DockWidgetCloseButton:
       
  2240     case PseudoElement_DockWidgetFloatButton: {
       
  2241         int iconSize = pixelMetric(PM_SmallIconSize, 0, w);
       
  2242         return QSize(iconSize, iconSize);
       
  2243                                               }
       
  2244 
       
  2245     default:
       
  2246         break;
       
  2247     }
       
  2248 
       
  2249     // expand to rectangle
       
  2250     if (sz.height() == -1)
       
  2251         sz.setHeight(rect.height());
       
  2252     if (sz.width() == -1)
       
  2253         sz.setWidth(rect.width());
       
  2254 
       
  2255     return sz;
       
  2256 }
       
  2257 
       
  2258 static PositionMode defaultPositionMode(int pe)
       
  2259 {
       
  2260     switch (pe) {
       
  2261     case PseudoElement_ScrollBarFirst:
       
  2262     case PseudoElement_ScrollBarLast:
       
  2263     case PseudoElement_ScrollBarAddLine:
       
  2264     case PseudoElement_ScrollBarSubLine:
       
  2265     case PseudoElement_ScrollBarAddPage:
       
  2266     case PseudoElement_ScrollBarSubPage:
       
  2267     case PseudoElement_ScrollBarSlider:
       
  2268     case PseudoElement_SliderGroove:
       
  2269     case PseudoElement_SliderHandle:
       
  2270     case PseudoElement_TabWidgetPane:
       
  2271         return PositionMode_Absolute;
       
  2272     default:
       
  2273         return PositionMode_Static;
       
  2274     }
       
  2275 }
       
  2276 
       
  2277 QRect QStyleSheetStyle::positionRect(const QWidget *w, const QRenderRule &rule2, int pe,
       
  2278                                      const QRect &originRect, Qt::LayoutDirection dir) const
       
  2279 {
       
  2280     const QStyleSheetPositionData *p = rule2.position();
       
  2281     PositionMode mode = (p && p->mode != PositionMode_Unknown) ? p->mode : defaultPositionMode(pe);
       
  2282     Qt::Alignment position = (p && p->position != 0) ? p->position : defaultPosition(pe);
       
  2283     QRect r;
       
  2284 
       
  2285     if (mode != PositionMode_Absolute) {
       
  2286         QSize sz = defaultSize(w, rule2.size(), originRect, pe);
       
  2287         sz = sz.expandedTo(rule2.minimumContentsSize());
       
  2288         r = QStyle::alignedRect(dir, position, sz, originRect);
       
  2289         if (p) {
       
  2290             int left = p->left ? p->left : -p->right;
       
  2291             int top = p->top ? p->top : -p->bottom;
       
  2292             r.translate(dir == Qt::LeftToRight ? left : -left, top);
       
  2293         }
       
  2294     } else {
       
  2295         r = p ? originRect.adjusted(dir == Qt::LeftToRight ? p->left : p->right, p->top,
       
  2296                                    dir == Qt::LeftToRight ? -p->right : -p->left, -p->bottom)
       
  2297               : originRect;
       
  2298         if (rule2.hasContentsSize()) {
       
  2299             QSize sz = rule2.size().expandedTo(rule2.minimumContentsSize());
       
  2300             if (sz.width() == -1) sz.setWidth(r.width());
       
  2301             if (sz.height() == -1) sz.setHeight(r.height());
       
  2302             r = QStyle::alignedRect(dir, position, sz, r);
       
  2303         }
       
  2304     }
       
  2305     return r;
       
  2306 }
       
  2307 
       
  2308 QRect QStyleSheetStyle::positionRect(const QWidget *w, const QRenderRule& rule1, const QRenderRule& rule2, int pe,
       
  2309                                      const QRect& rect, Qt::LayoutDirection dir) const
       
  2310 {
       
  2311     const QStyleSheetPositionData *p = rule2.position();
       
  2312     Origin origin = (p && p->origin != Origin_Unknown) ? p->origin : defaultOrigin(pe);
       
  2313     QRect originRect = rule1.originRect(rect, origin);
       
  2314     return positionRect(w, rule2, pe, originRect, dir);
       
  2315 }
       
  2316 
       
  2317 
       
  2318 /** \internal
       
  2319    For widget that have an embedded widget (such as combobox) return that embedded widget.
       
  2320    otherwise return the widget itself
       
  2321  */
       
  2322 static QWidget *embeddedWidget(QWidget *w)
       
  2323 {
       
  2324 #ifndef QT_NO_COMBOBOX
       
  2325     if (QComboBox *cmb = qobject_cast<QComboBox *>(w)) {
       
  2326         if (cmb->isEditable())
       
  2327             return cmb->lineEdit();
       
  2328         else
       
  2329             return cmb;
       
  2330     }
       
  2331 #endif
       
  2332 
       
  2333 #ifndef QT_NO_SPINBOX
       
  2334     if (QAbstractSpinBox *sb = qobject_cast<QAbstractSpinBox *>(w))
       
  2335         return qFindChild<QLineEdit *>(sb);
       
  2336 #endif
       
  2337 
       
  2338 #ifndef QT_NO_SCROLLAREA
       
  2339     if (QAbstractScrollArea *sa = qobject_cast<QAbstractScrollArea *>(w))
       
  2340         return sa->viewport();
       
  2341 #endif
       
  2342 
       
  2343     return w;
       
  2344 }
       
  2345 
       
  2346 /** \internal
       
  2347   in case w is an embedded widget, return the container widget
       
  2348   (i.e, the widget for which the rules actualy apply)
       
  2349   (exemple, if w is a lineedit embedded in a combobox, return the combobox)
       
  2350 
       
  2351   if w is not embedded, return w itself
       
  2352 */
       
  2353 static QWidget *containerWidget(const QWidget *w)
       
  2354 {
       
  2355 #ifndef QT_NO_LINEEDIT
       
  2356     if (qobject_cast<const QLineEdit *>(w)) {
       
  2357         //if the QLineEdit is an embeddedWidget, we need the rule of the real widget
       
  2358 #ifndef QT_NO_COMBOBOX
       
  2359         if (qobject_cast<const QComboBox *>(w->parentWidget()))
       
  2360             return w->parentWidget();
       
  2361 #endif
       
  2362 #ifndef QT_NO_SPINBOX
       
  2363         if (qobject_cast<const QAbstractSpinBox *>(w->parentWidget()))
       
  2364             return w->parentWidget();
       
  2365 #endif
       
  2366     }
       
  2367 #endif // QT_NO_LINEEDIT
       
  2368 
       
  2369 #ifndef QT_NO_SCROLLAREA
       
  2370     if (const QAbstractScrollArea *sa = qobject_cast<const QAbstractScrollArea *>(w->parentWidget())) {
       
  2371         if (sa->viewport() == w)
       
  2372             return w->parentWidget();
       
  2373     }
       
  2374 #endif
       
  2375 
       
  2376     return const_cast<QWidget *>(w);
       
  2377 }
       
  2378 
       
  2379 /** \internal
       
  2380     returns true if the widget can NOT be styled directly
       
  2381  */
       
  2382 static bool unstylable(const QWidget *w)
       
  2383 {
       
  2384     if (w->windowType() == Qt::Desktop)
       
  2385         return true;
       
  2386 
       
  2387     if (!w->styleSheet().isEmpty())
       
  2388         return false;
       
  2389 
       
  2390     if (containerWidget(w) != w)
       
  2391         return true;
       
  2392 
       
  2393 #ifndef QT_NO_FRAME
       
  2394     // detect QComboBoxPrivateContainer
       
  2395     else if (qobject_cast<const QFrame *>(w)) {
       
  2396         if (0
       
  2397 #ifndef QT_NO_COMBOBOX
       
  2398             || qobject_cast<const QComboBox *>(w->parentWidget())
       
  2399 #endif
       
  2400            )
       
  2401             return true;
       
  2402     }
       
  2403 #endif
       
  2404     return false;
       
  2405 }
       
  2406 
       
  2407 static quint64 extendedPseudoClass(const QWidget *w)
       
  2408 {
       
  2409     quint64 pc = w->isWindow() ? quint64(PseudoClass_Window) : 0;
       
  2410     if (const QAbstractSlider *slider = qobject_cast<const QAbstractSlider *>(w)) {
       
  2411         pc |= ((slider->orientation() == Qt::Vertical) ? PseudoClass_Vertical : PseudoClass_Horizontal);
       
  2412     } else
       
  2413 #ifndef QT_NO_COMBOBOX
       
  2414     if (const QComboBox *combo = qobject_cast<const QComboBox *>(w)) {
       
  2415         if (combo->isEditable())
       
  2416         pc |= (combo->isEditable() ? PseudoClass_Editable : PseudoClass_ReadOnly);
       
  2417     } else
       
  2418 #endif
       
  2419 #ifndef QT_NO_LINEEDIT
       
  2420     if (const QLineEdit *edit = qobject_cast<const QLineEdit *>(w)) {
       
  2421         pc |= (edit->isReadOnly() ? PseudoClass_ReadOnly : PseudoClass_Editable);
       
  2422     } else
       
  2423 #endif
       
  2424     { } // required for the above ifdef'ery to work
       
  2425     return pc;
       
  2426 }
       
  2427 
       
  2428 // sets up the geometry of the widget. We set a dynamic property when
       
  2429 // we modify the min/max size of the widget. The min/max size is restored
       
  2430 // to their original value when a new stylesheet that does not contain
       
  2431 // the CSS properties is set and when the widget has this dynamic property set.
       
  2432 // This way we don't trample on users who had setup a min/max size in code and
       
  2433 // don't use stylesheets at all.
       
  2434 void QStyleSheetStyle::setGeometry(QWidget *w)
       
  2435 {
       
  2436     QRenderRule rule = renderRule(w, PseudoElement_None, PseudoClass_Enabled | extendedPseudoClass(w));
       
  2437     const QStyleSheetGeometryData *geo = rule.geometry();
       
  2438     if (w->property("_q_stylesheet_minw").toBool()
       
  2439         && ((!rule.hasGeometry() || geo->minWidth == -1))) {
       
  2440             w->setMinimumWidth(0);
       
  2441             w->setProperty("_q_stylesheet_minw", QVariant());
       
  2442     }
       
  2443     if (w->property("_q_stylesheet_minh").toBool()
       
  2444         && ((!rule.hasGeometry() || geo->minHeight == -1))) {
       
  2445             w->setMinimumHeight(0);
       
  2446             w->setProperty("_q_stylesheet_minh", QVariant());
       
  2447     }
       
  2448     if (w->property("_q_stylesheet_maxw").toBool()
       
  2449         && ((!rule.hasGeometry() || geo->maxWidth == -1))) {
       
  2450             w->setMaximumWidth(QWIDGETSIZE_MAX);
       
  2451             w->setProperty("_q_stylesheet_maxw", QVariant());
       
  2452     }
       
  2453    if (w->property("_q_stylesheet_maxh").toBool()
       
  2454         && ((!rule.hasGeometry() || geo->maxHeight == -1))) {
       
  2455             w->setMaximumHeight(QWIDGETSIZE_MAX);
       
  2456             w->setProperty("_q_stylesheet_maxh", QVariant());
       
  2457     }
       
  2458 
       
  2459 
       
  2460     if (rule.hasGeometry()) {
       
  2461         if (geo->minWidth != -1) {
       
  2462             w->setProperty("_q_stylesheet_minw", true);
       
  2463             w->setMinimumWidth(rule.boxSize(QSize(qMax(geo->width, geo->minWidth), 0)).width());
       
  2464         }
       
  2465         if (geo->minHeight != -1) {
       
  2466             w->setProperty("_q_stylesheet_minh", true);
       
  2467             w->setMinimumHeight(rule.boxSize(QSize(0, qMax(geo->height, geo->minHeight))).height());
       
  2468         }
       
  2469         if (geo->maxWidth != -1) {
       
  2470             w->setProperty("_q_stylesheet_maxw", true);
       
  2471             w->setMaximumWidth(rule.boxSize(QSize(qMin(geo->width == -1 ? QWIDGETSIZE_MAX : geo->width,
       
  2472                                                        geo->maxWidth == -1 ? QWIDGETSIZE_MAX : geo->maxWidth), 0)).width());
       
  2473         }
       
  2474         if (geo->maxHeight != -1) {
       
  2475             w->setProperty("_q_stylesheet_maxh", true);
       
  2476             w->setMaximumHeight(rule.boxSize(QSize(0, qMin(geo->height == -1 ? QWIDGETSIZE_MAX : geo->height,
       
  2477                                                        geo->maxHeight == -1 ? QWIDGETSIZE_MAX : geo->maxHeight))).height());
       
  2478         }
       
  2479     }
       
  2480 }
       
  2481 
       
  2482 void QStyleSheetStyle::setProperties(QWidget *w)
       
  2483 {
       
  2484     QHash<QString, QVariant> propertyHash;
       
  2485     QVector<Declaration> decls = declarations(styleRules(w), QString());
       
  2486 
       
  2487     // run through the declarations in order
       
  2488     for (int i = 0; i < decls.count(); i++) {
       
  2489         const Declaration &decl = decls.at(i);
       
  2490         QString property = decl.d->property;
       
  2491         if (!property.startsWith(QLatin1String("qproperty-"), Qt::CaseInsensitive))
       
  2492             continue;
       
  2493         property.remove(0, 10); // strip "qproperty-"
       
  2494         const QVariant value = w->property(property.toLatin1());
       
  2495         const QMetaObject *metaObject = w->metaObject();
       
  2496         int index = metaObject->indexOfProperty(property.toLatin1());
       
  2497         if (index == -1) {
       
  2498             qWarning() << w << " does not have a property named " << property;
       
  2499             continue;
       
  2500         }
       
  2501         QMetaProperty metaProperty = metaObject->property(index);
       
  2502         if (!metaProperty.isWritable() || !metaProperty.isDesignable()) {
       
  2503             qWarning() << w << " cannot design property named " << property;
       
  2504             continue;
       
  2505         }
       
  2506         QVariant v;
       
  2507         switch (value.type()) {
       
  2508         case QVariant::Icon: v = decl.iconValue(); break;
       
  2509         case QVariant::Image: v = QImage(decl.uriValue()); break;
       
  2510         case QVariant::Pixmap: v = QPixmap(decl.uriValue()); break;
       
  2511         case QVariant::Rect: v = decl.rectValue(); break;
       
  2512         case QVariant::Size: v = decl.sizeValue(); break;
       
  2513         case QVariant::Color: v = decl.colorValue(); break;
       
  2514         case QVariant::Brush: v = decl.brushValue(); break;
       
  2515 #ifndef QT_NO_SHORTCUT
       
  2516         case QVariant::KeySequence: v = QKeySequence(decl.d->values.at(0).variant.toString()); break;
       
  2517 #endif
       
  2518         default: v = decl.d->values.at(0).variant; break;
       
  2519         }
       
  2520         propertyHash[property] = v;
       
  2521     }
       
  2522     // apply the values
       
  2523     const QList<QString> properties = propertyHash.keys();
       
  2524     for (int i = 0; i < properties.count(); i++) {
       
  2525         const QString &property = properties.at(i);
       
  2526         w->setProperty(property.toLatin1(), propertyHash[property]);
       
  2527     }
       
  2528 }
       
  2529 
       
  2530 void QStyleSheetStyle::setPalette(QWidget *w)
       
  2531 {
       
  2532     struct RuleRoleMap {
       
  2533         int state;
       
  2534         QPalette::ColorGroup group;
       
  2535     } map[3] = {
       
  2536         { PseudoClass_Active | PseudoClass_Enabled, QPalette::Active },
       
  2537         { PseudoClass_Disabled, QPalette::Disabled },
       
  2538         { PseudoClass_Enabled, QPalette::Inactive }
       
  2539     };
       
  2540 
       
  2541     QPalette p = w->palette();
       
  2542     QWidget *ew = embeddedWidget(w);
       
  2543 
       
  2544     for (int i = 0; i < 3; i++) {
       
  2545         QRenderRule rule = renderRule(w, PseudoElement_None, map[i].state | extendedPseudoClass(w));
       
  2546         if (i == 0) {
       
  2547             if (!w->property("_q_styleSheetWidgetFont").isValid()) {
       
  2548                 saveWidgetFont(w, w->font());
       
  2549             }
       
  2550             updateStyleSheetFont(w);
       
  2551             if (ew != w)
       
  2552                 updateStyleSheetFont(ew);
       
  2553         }
       
  2554 
       
  2555         rule.configurePalette(&p, map[i].group, ew, ew != w);
       
  2556     }
       
  2557 
       
  2558     customPaletteWidgets->insert(w, w->palette());
       
  2559     w->setPalette(p);
       
  2560     if (ew != w)
       
  2561         ew->setPalette(p);
       
  2562 }
       
  2563 
       
  2564 void QStyleSheetStyle::unsetPalette(QWidget *w)
       
  2565 {
       
  2566     if (customPaletteWidgets->contains(w)) {
       
  2567         QPalette p = customPaletteWidgets->value(w);
       
  2568         w->setPalette(p);
       
  2569         QWidget *ew = embeddedWidget(w);
       
  2570         if (ew != w)
       
  2571             ew->setPalette(p);
       
  2572         customPaletteWidgets->remove(w);
       
  2573     }
       
  2574     QVariant oldFont = w->property("_q_styleSheetWidgetFont");
       
  2575     if (oldFont.isValid()) {
       
  2576         w->setFont(qVariantValue<QFont>(oldFont));
       
  2577     }
       
  2578     if (autoFillDisabledWidgets->contains(w)) {
       
  2579         embeddedWidget(w)->setAutoFillBackground(true);
       
  2580         autoFillDisabledWidgets->remove(w);
       
  2581     }
       
  2582 }
       
  2583 
       
  2584 static void updateWidgets(const QList<const QWidget *>& widgets)
       
  2585 {
       
  2586     if (!styleRulesCache->isEmpty() || !hasStyleRuleCache->isEmpty() || !renderRulesCache->isEmpty()) {
       
  2587         for (int i = 0; i < widgets.size(); ++i) {
       
  2588             const QWidget *widget = widgets.at(i);
       
  2589             styleRulesCache->remove(widget);
       
  2590             hasStyleRuleCache->remove(widget);
       
  2591             renderRulesCache->remove(widget);
       
  2592         }
       
  2593     }
       
  2594     for (int i = 0; i < widgets.size(); ++i) {
       
  2595         QWidget *widget = const_cast<QWidget *>(widgets.at(i));
       
  2596         if (widget == 0)
       
  2597             continue;
       
  2598         widget->style()->polish(widget);
       
  2599         QEvent event(QEvent::StyleChange);
       
  2600         QApplication::sendEvent(widget, &event);
       
  2601         widget->update();
       
  2602         widget->updateGeometry();
       
  2603     }
       
  2604 }
       
  2605 
       
  2606 /////////////////////////////////////////////////////////////////////////////////////////
       
  2607 // The stylesheet style
       
  2608 int QStyleSheetStyle::numinstances = 0;
       
  2609 
       
  2610 QStyleSheetStyle::QStyleSheetStyle(QStyle *base)
       
  2611     : QWindowsStyle(*new QStyleSheetStylePrivate), base(base), refcount(1)
       
  2612 {
       
  2613     ++numinstances;
       
  2614     if (numinstances == 1) {
       
  2615         styleRulesCache = new QHash<const QWidget *, QVector<StyleRule> >;
       
  2616         hasStyleRuleCache = new QHash<const QWidget *, QHash<int, bool> >;
       
  2617         renderRulesCache = new QHash<const QWidget *, QRenderRules>;
       
  2618         customPaletteWidgets = new QHash<const QWidget *, QPalette>;
       
  2619         styleSheetCache = new QHash<const void *, StyleSheet>;
       
  2620         autoFillDisabledWidgets = new QSet<const QWidget *>;
       
  2621     }
       
  2622 }
       
  2623 
       
  2624 QStyleSheetStyle::~QStyleSheetStyle()
       
  2625 {
       
  2626     --numinstances;
       
  2627     if (numinstances == 0) {
       
  2628         delete styleRulesCache;
       
  2629         styleRulesCache = 0;
       
  2630         delete hasStyleRuleCache;
       
  2631         hasStyleRuleCache = 0;
       
  2632         delete renderRulesCache;
       
  2633         renderRulesCache = 0;
       
  2634         delete customPaletteWidgets;
       
  2635         customPaletteWidgets = 0;
       
  2636         delete styleSheetCache;
       
  2637         styleSheetCache = 0;
       
  2638         delete autoFillDisabledWidgets;
       
  2639         autoFillDisabledWidgets = 0;
       
  2640     }
       
  2641 }
       
  2642 QStyle *QStyleSheetStyle::baseStyle() const
       
  2643 {
       
  2644     if (base)
       
  2645         return base;
       
  2646     if (QStyleSheetStyle *me = qobject_cast<QStyleSheetStyle *>(QApplication::style()))
       
  2647         return me->base;
       
  2648     return QApplication::style();
       
  2649 }
       
  2650 
       
  2651 void QStyleSheetStyle::widgetDestroyed(QObject *o)
       
  2652 {
       
  2653     styleRulesCache->remove((const QWidget *)o);
       
  2654     hasStyleRuleCache->remove((const QWidget *)o);
       
  2655     renderRulesCache->remove((const QWidget *)o);
       
  2656     customPaletteWidgets->remove((const QWidget *)o);
       
  2657     styleSheetCache->remove((const QWidget *)o);
       
  2658     autoFillDisabledWidgets->remove((const QWidget *)o);
       
  2659 }
       
  2660 
       
  2661 /*!
       
  2662  *  Make sure that the cache will be clean by connecting destroyed if needed.
       
  2663  *  return false if the widget is not stylable;
       
  2664  */
       
  2665 bool QStyleSheetStyle::initWidget(const QWidget *w) const
       
  2666 {
       
  2667     if (!w)
       
  2668         return false;
       
  2669     if(w->testAttribute(Qt::WA_StyleSheet))
       
  2670         return true;
       
  2671 
       
  2672     if(unstylable(w))
       
  2673         return false;
       
  2674 
       
  2675     const_cast<QWidget *>(w)->setAttribute(Qt::WA_StyleSheet, true);
       
  2676     QObject::connect(w, SIGNAL(destroyed(QObject*)), this, SLOT(widgetDestroyed(QObject*)));
       
  2677     return true;
       
  2678 }
       
  2679 
       
  2680 void QStyleSheetStyle::polish(QWidget *w)
       
  2681 {
       
  2682     baseStyle()->polish(w);
       
  2683     RECURSION_GUARD(return)
       
  2684 
       
  2685     if (!initWidget(w))
       
  2686         return;
       
  2687 
       
  2688     if (styleRulesCache->contains(w)) {
       
  2689         // the widget accessed its style pointer before polish (or repolish)
       
  2690         // (exemple: the QAbstractSpinBox constructor ask for the stylehint)
       
  2691         styleRulesCache->remove(w);
       
  2692         hasStyleRuleCache->remove(w);
       
  2693         renderRulesCache->remove(w);
       
  2694     }
       
  2695     setGeometry(w);
       
  2696     setProperties(w);
       
  2697     unsetPalette(w);
       
  2698     setPalette(w);
       
  2699 
       
  2700     //set the WA_Hover attribute if one of the selector depends of the hover state
       
  2701     QVector<StyleRule> rules = styleRules(w);
       
  2702     for (int i = 0; i < rules.count(); i++) {
       
  2703         const Selector& selector = rules.at(i).selectors.at(0);
       
  2704         quint64 negated = 0;
       
  2705         quint64 cssClass = selector.pseudoClass(&negated);
       
  2706         if ( cssClass & PseudoClass_Hover || negated & PseudoClass_Hover) {
       
  2707             w->setAttribute(Qt::WA_Hover);
       
  2708             embeddedWidget(w)->setAttribute(Qt::WA_Hover);
       
  2709         }
       
  2710     }
       
  2711 
       
  2712 
       
  2713 #ifndef QT_NO_SCROLLAREA
       
  2714     if (QAbstractScrollArea *sa = qobject_cast<QAbstractScrollArea *>(w)) {
       
  2715         QRenderRule rule = renderRule(sa, PseudoElement_None, PseudoClass_Enabled);
       
  2716         if ((rule.hasBorder() && rule.border()->hasBorderImage())
       
  2717             || (rule.hasBackground() && !rule.background()->pixmap.isNull())) {
       
  2718             QObject::connect(sa->horizontalScrollBar(), SIGNAL(valueChanged(int)),
       
  2719                              sa, SLOT(update()), Qt::UniqueConnection);
       
  2720             QObject::connect(sa->verticalScrollBar(), SIGNAL(valueChanged(int)),
       
  2721                              sa, SLOT(update()), Qt::UniqueConnection);
       
  2722         }
       
  2723     }
       
  2724 #endif
       
  2725 
       
  2726 #ifndef QT_NO_PROGRESSBAR
       
  2727     if (QProgressBar *pb = qobject_cast<QProgressBar *>(w)) {
       
  2728         QWindowsStyle::polish(pb);
       
  2729     }
       
  2730 #endif
       
  2731 
       
  2732     QRenderRule rule = renderRule(w, PseudoElement_None, PseudoClass_Any);
       
  2733     if (rule.hasDrawable() || rule.hasBox()) {
       
  2734         if (w->metaObject() == &QWidget::staticMetaObject
       
  2735 #ifndef QT_NO_ITEMVIEWS
       
  2736               || qobject_cast<QHeaderView *>(w)
       
  2737 #endif
       
  2738 #ifndef QT_NO_TABBAR
       
  2739               || qobject_cast<QTabBar *>(w)
       
  2740 #endif
       
  2741 #ifndef QT_NO_FRAME
       
  2742               || qobject_cast<QFrame *>(w)
       
  2743 #endif
       
  2744 #ifndef QT_NO_MAINWINDOW
       
  2745               || qobject_cast<QMainWindow *>(w)
       
  2746 #endif
       
  2747 #ifndef QT_NO_MDIAREA
       
  2748               || qobject_cast<QMdiSubWindow *>(w)
       
  2749 #endif
       
  2750 #ifndef QT_NO_MENUBAR
       
  2751               || qobject_cast<QMenuBar *>(w)
       
  2752 #endif
       
  2753               || qobject_cast<QDialog *>(w)) {
       
  2754             w->setAttribute(Qt::WA_StyledBackground, true);
       
  2755         }
       
  2756         QWidget *ew = embeddedWidget(w);
       
  2757         if (ew->autoFillBackground()) {
       
  2758             ew->setAutoFillBackground(false);
       
  2759             autoFillDisabledWidgets->insert(w);
       
  2760             if (ew != w) { //eg. viewport of a scrollarea
       
  2761                 //(in order to draw the background anyway in case we don't.)
       
  2762                 ew->setAttribute(Qt::WA_StyledBackground, true);
       
  2763             }
       
  2764         }
       
  2765         if (!rule.hasBackground() || rule.background()->isTransparent() || rule.hasBox()
       
  2766             || (!rule.hasNativeBorder() && !rule.border()->isOpaque()))
       
  2767             w->setAttribute(Qt::WA_OpaquePaintEvent, false);
       
  2768     }
       
  2769 }
       
  2770 
       
  2771 void QStyleSheetStyle::polish(QApplication *app)
       
  2772 {
       
  2773     baseStyle()->polish(app);
       
  2774 }
       
  2775 
       
  2776 void QStyleSheetStyle::polish(QPalette &pal)
       
  2777 {
       
  2778     baseStyle()->polish(pal);
       
  2779 }
       
  2780 
       
  2781 void QStyleSheetStyle::repolish(QWidget *w)
       
  2782 {
       
  2783     QList<const QWidget *> children = qFindChildren<const QWidget *>(w, QString());
       
  2784     children.append(w);
       
  2785     styleSheetCache->remove(w);
       
  2786     updateWidgets(children);
       
  2787 }
       
  2788 
       
  2789 void QStyleSheetStyle::repolish(QApplication *app)
       
  2790 {
       
  2791     Q_UNUSED(app);
       
  2792     const QList<const QWidget*> allWidgets = styleRulesCache->keys();
       
  2793     styleSheetCache->remove(qApp);
       
  2794     styleRulesCache->clear();
       
  2795     hasStyleRuleCache->clear();
       
  2796     renderRulesCache->clear();
       
  2797     updateWidgets(allWidgets);
       
  2798 }
       
  2799 
       
  2800 void QStyleSheetStyle::unpolish(QWidget *w)
       
  2801 {
       
  2802     if (!w || !w->testAttribute(Qt::WA_StyleSheet)) {
       
  2803         baseStyle()->unpolish(w);
       
  2804         return;
       
  2805     }
       
  2806 
       
  2807     styleRulesCache->remove(w);
       
  2808     hasStyleRuleCache->remove(w);
       
  2809     renderRulesCache->remove(w);
       
  2810     styleSheetCache->remove(w);
       
  2811     unsetPalette(w);
       
  2812     w->setProperty("_q_stylesheet_minw", QVariant());
       
  2813     w->setProperty("_q_stylesheet_minh", QVariant());
       
  2814     w->setProperty("_q_stylesheet_maxw", QVariant());
       
  2815     w->setProperty("_q_stylesheet_maxh", QVariant());
       
  2816     w->setAttribute(Qt::WA_StyleSheet, false);
       
  2817     QObject::disconnect(w, 0, this, 0);
       
  2818 #ifndef QT_NO_SCROLLAREA
       
  2819     if (QAbstractScrollArea *sa = qobject_cast<QAbstractScrollArea *>(w)) {
       
  2820         QObject::disconnect(sa->horizontalScrollBar(), SIGNAL(valueChanged(int)),
       
  2821                             sa, SLOT(update()));
       
  2822         QObject::disconnect(sa->verticalScrollBar(), SIGNAL(valueChanged(int)),
       
  2823                             sa, SLOT(update()));
       
  2824     }
       
  2825 #endif
       
  2826 #ifndef QT_NO_PROGRESSBAR
       
  2827     if (QProgressBar *pb = qobject_cast<QProgressBar *>(w))
       
  2828         QWindowsStyle::unpolish(pb);
       
  2829 #endif
       
  2830     baseStyle()->unpolish(w);
       
  2831 }
       
  2832 
       
  2833 void QStyleSheetStyle::unpolish(QApplication *app)
       
  2834 {
       
  2835     baseStyle()->unpolish(app);
       
  2836     RECURSION_GUARD(return)
       
  2837     styleRulesCache->clear();
       
  2838     hasStyleRuleCache->clear();
       
  2839     renderRulesCache->clear();
       
  2840     styleSheetCache->remove(qApp);
       
  2841 }
       
  2842 
       
  2843 #ifndef QT_NO_TABBAR
       
  2844 inline static bool verticalTabs(QTabBar::Shape shape)
       
  2845 {
       
  2846     return shape == QTabBar::RoundedWest
       
  2847            || shape == QTabBar::RoundedEast
       
  2848            || shape == QTabBar::TriangularWest
       
  2849            || shape == QTabBar::TriangularEast;
       
  2850 }
       
  2851 #endif // QT_NO_TABBAR
       
  2852 
       
  2853 void QStyleSheetStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, QPainter *p,
       
  2854                                           const QWidget *w) const
       
  2855 {
       
  2856     RECURSION_GUARD(baseStyle()->drawComplexControl(cc, opt, p, w); return)
       
  2857 
       
  2858     QRenderRule rule = renderRule(w, opt);
       
  2859 
       
  2860     switch (cc) {
       
  2861     case CC_ComboBox:
       
  2862         if (const QStyleOptionComboBox *cmb = qstyleoption_cast<const QStyleOptionComboBox *>(opt)) {
       
  2863             QStyleOptionComboBox cmbOpt(*cmb);
       
  2864             cmbOpt.rect = rule.borderRect(opt->rect);
       
  2865             if (rule.hasNativeBorder()) {
       
  2866                 rule.drawBackgroundImage(p, cmbOpt.rect);
       
  2867                 rule.configurePalette(&cmbOpt.palette, QPalette::ButtonText, QPalette::Button);
       
  2868                 bool customDropDown = (opt->subControls & QStyle::SC_ComboBoxArrow)
       
  2869                                 && (hasStyleRule(w, PseudoElement_ComboBoxDropDown) || hasStyleRule(w, PseudoElement_ComboBoxArrow));
       
  2870                 if (customDropDown)
       
  2871                     cmbOpt.subControls &= ~QStyle::SC_ComboBoxArrow;
       
  2872                 if (rule.baseStyleCanDraw()) {
       
  2873                     baseStyle()->drawComplexControl(cc, &cmbOpt, p, w);
       
  2874                 } else {
       
  2875                     QWindowsStyle::drawComplexControl(cc, &cmbOpt, p, w);
       
  2876                 }
       
  2877                 if (!customDropDown)
       
  2878                     return;
       
  2879             } else {
       
  2880                 rule.drawRule(p, opt->rect);
       
  2881             }
       
  2882 
       
  2883             if (opt->subControls & QStyle::SC_ComboBoxArrow) {
       
  2884                 QRenderRule subRule = renderRule(w, opt, PseudoElement_ComboBoxDropDown);
       
  2885                 if (subRule.hasDrawable()) {
       
  2886                     QRect r = subControlRect(CC_ComboBox, opt, SC_ComboBoxArrow, w);
       
  2887                     subRule.drawRule(p, r);
       
  2888                     QRenderRule subRule2 = renderRule(w, opt, PseudoElement_ComboBoxArrow);
       
  2889                     r = positionRect(w, subRule, subRule2, PseudoElement_ComboBoxArrow, r, opt->direction);
       
  2890                     subRule2.drawRule(p, r);
       
  2891                 } else {
       
  2892                     cmbOpt.subControls = QStyle::SC_ComboBoxArrow;
       
  2893                     QWindowsStyle::drawComplexControl(cc, &cmbOpt, p, w);
       
  2894                 }
       
  2895             }
       
  2896 
       
  2897             return;
       
  2898         }
       
  2899         break;
       
  2900 
       
  2901 #ifndef QT_NO_SPINBOX
       
  2902     case CC_SpinBox:
       
  2903         if (const QStyleOptionSpinBox *spin = qstyleoption_cast<const QStyleOptionSpinBox *>(opt)) {
       
  2904             QStyleOptionSpinBox spinOpt(*spin);
       
  2905             rule.configurePalette(&spinOpt.palette, QPalette::ButtonText, QPalette::Button);
       
  2906             rule.configurePalette(&spinOpt.palette, QPalette::Text, QPalette::Base);
       
  2907             spinOpt.rect = rule.borderRect(opt->rect);
       
  2908             bool customUp = true, customDown = true;
       
  2909             QRenderRule upRule = renderRule(w, opt, PseudoElement_SpinBoxUpButton);
       
  2910             QRenderRule downRule = renderRule(w, opt, PseudoElement_SpinBoxDownButton);
       
  2911             bool upRuleMatch = upRule.hasGeometry() || upRule.hasPosition();
       
  2912             bool downRuleMatch = downRule.hasGeometry() || downRule.hasPosition();
       
  2913             if (rule.hasNativeBorder() && !upRuleMatch && !downRuleMatch) {
       
  2914                 rule.drawBackgroundImage(p, spinOpt.rect);
       
  2915                 customUp = (opt->subControls & QStyle::SC_SpinBoxUp)
       
  2916                         && (hasStyleRule(w, PseudoElement_SpinBoxUpButton) || hasStyleRule(w, PseudoElement_UpArrow));
       
  2917                 if (customUp)
       
  2918                     spinOpt.subControls &= ~QStyle::SC_SpinBoxUp;
       
  2919                 customDown = (opt->subControls & QStyle::SC_SpinBoxDown)
       
  2920                         && (hasStyleRule(w, PseudoElement_SpinBoxDownButton) || hasStyleRule(w, PseudoElement_DownArrow));
       
  2921                 if (customDown)
       
  2922                     spinOpt.subControls &= ~QStyle::SC_SpinBoxDown;
       
  2923                 if (rule.baseStyleCanDraw()) {
       
  2924                     baseStyle()->drawComplexControl(cc, &spinOpt, p, w);
       
  2925                 } else {
       
  2926                     QWindowsStyle::drawComplexControl(cc, &spinOpt, p, w);
       
  2927                 }
       
  2928                 if (!customUp && !customDown)
       
  2929                     return;
       
  2930             } else {
       
  2931                 rule.drawRule(p, opt->rect);
       
  2932             }
       
  2933 
       
  2934             if ((opt->subControls & QStyle::SC_SpinBoxUp) && customUp) {
       
  2935                 QRenderRule subRule = renderRule(w, opt, PseudoElement_SpinBoxUpButton);
       
  2936                 if (subRule.hasDrawable()) {
       
  2937                     QRect r = subControlRect(CC_SpinBox, opt, SC_SpinBoxUp, w);
       
  2938                     subRule.drawRule(p, r);
       
  2939                     QRenderRule subRule2 = renderRule(w, opt, PseudoElement_SpinBoxUpArrow);
       
  2940                     r = positionRect(w, subRule, subRule2, PseudoElement_SpinBoxUpArrow, r, opt->direction);
       
  2941                     subRule2.drawRule(p, r);
       
  2942                 } else {
       
  2943                     spinOpt.subControls = QStyle::SC_SpinBoxUp;
       
  2944                     QWindowsStyle::drawComplexControl(cc, &spinOpt, p, w);
       
  2945                 }
       
  2946             }
       
  2947 
       
  2948             if ((opt->subControls & QStyle::SC_SpinBoxDown) && customDown) {
       
  2949                 QRenderRule subRule = renderRule(w, opt, PseudoElement_SpinBoxDownButton);
       
  2950                 if (subRule.hasDrawable()) {
       
  2951                     QRect r = subControlRect(CC_SpinBox, opt, SC_SpinBoxDown, w);
       
  2952                     subRule.drawRule(p, r);
       
  2953                     QRenderRule subRule2 = renderRule(w, opt, PseudoElement_SpinBoxDownArrow);
       
  2954                     r = positionRect(w, subRule, subRule2, PseudoElement_SpinBoxDownArrow, r, opt->direction);
       
  2955                     subRule2.drawRule(p, r);
       
  2956                 } else {
       
  2957                     spinOpt.subControls = QStyle::SC_SpinBoxDown;
       
  2958                     QWindowsStyle::drawComplexControl(cc, &spinOpt, p, w);
       
  2959                 }
       
  2960             }
       
  2961             return;
       
  2962         }
       
  2963         break;
       
  2964 #endif // QT_NO_SPINBOX
       
  2965 
       
  2966     case CC_GroupBox:
       
  2967         if (const QStyleOptionGroupBox *gb = qstyleoption_cast<const QStyleOptionGroupBox *>(opt)) {
       
  2968 
       
  2969             QRect labelRect, checkBoxRect, titleRect, frameRect;
       
  2970             bool hasTitle = (gb->subControls & QStyle::SC_GroupBoxCheckBox) || !gb->text.isEmpty();
       
  2971 
       
  2972             if (!rule.hasDrawable() && (!hasTitle || !hasStyleRule(w, PseudoElement_GroupBoxTitle))
       
  2973                 && !hasStyleRule(w, PseudoElement_Indicator) && !rule.hasBox() && !rule.hasFont && !rule.hasPalette()) {
       
  2974                 // let the native style draw the combobox if there is no style for it.
       
  2975                 break;
       
  2976             }
       
  2977             rule.drawBackground(p, opt->rect);
       
  2978 
       
  2979             QRenderRule titleRule = renderRule(w, opt, PseudoElement_GroupBoxTitle);
       
  2980             bool clipSet = false;
       
  2981 
       
  2982             if (hasTitle) {
       
  2983                 labelRect = subControlRect(CC_GroupBox, opt, SC_GroupBoxLabel, w);
       
  2984                 //Some native style (such as mac) may return a too small rectangle (because they use smaller fonts),  so we may need to expand it a little bit.
       
  2985                 labelRect.setSize(labelRect.size().expandedTo(ParentStyle::subControlRect(CC_GroupBox, opt, SC_GroupBoxLabel, w).size()));
       
  2986                 if (gb->subControls & QStyle::SC_GroupBoxCheckBox) {
       
  2987                     checkBoxRect = subControlRect(CC_GroupBox, opt, SC_GroupBoxCheckBox, w);
       
  2988                     titleRect = titleRule.boxRect(checkBoxRect.united(labelRect));
       
  2989                 } else {
       
  2990                     titleRect = titleRule.boxRect(labelRect);
       
  2991                 }
       
  2992                 if (!titleRule.hasBackground() || !titleRule.background()->isTransparent()) {
       
  2993                     clipSet = true;
       
  2994                     p->save();
       
  2995                     p->setClipRegion(QRegion(opt->rect) - titleRect);
       
  2996                 }
       
  2997             }
       
  2998 
       
  2999             frameRect = subControlRect(CC_GroupBox, opt, SC_GroupBoxFrame, w);
       
  3000             QStyleOptionFrameV2 frame;
       
  3001             frame.QStyleOption::operator=(*gb);
       
  3002             frame.features = gb->features;
       
  3003             frame.lineWidth = gb->lineWidth;
       
  3004             frame.midLineWidth = gb->midLineWidth;
       
  3005             frame.rect = frameRect;
       
  3006             drawPrimitive(PE_FrameGroupBox, &frame, p, w);
       
  3007 
       
  3008             if (clipSet)
       
  3009                 p->restore();
       
  3010 
       
  3011             // draw background and frame of the title
       
  3012             if (hasTitle)
       
  3013                 titleRule.drawRule(p, titleRect);
       
  3014 
       
  3015             // draw the indicator
       
  3016             if (gb->subControls & QStyle::SC_GroupBoxCheckBox) {
       
  3017                 QStyleOptionButton box;
       
  3018                 box.QStyleOption::operator=(*gb);
       
  3019                 box.rect = checkBoxRect;
       
  3020                 drawPrimitive(PE_IndicatorCheckBox, &box, p, w);
       
  3021             }
       
  3022 
       
  3023             // draw the text
       
  3024             if (!gb->text.isEmpty()) {
       
  3025                 int alignment = int(Qt::AlignCenter | Qt::TextShowMnemonic);
       
  3026                 if (!styleHint(QStyle::SH_UnderlineShortcut, opt, w)) {
       
  3027                     alignment |= Qt::TextHideMnemonic;
       
  3028                 }
       
  3029 
       
  3030                 QPalette pal = gb->palette;
       
  3031                 if (gb->textColor.isValid())
       
  3032                     pal.setColor(QPalette::WindowText, gb->textColor);
       
  3033                 titleRule.configurePalette(&pal, QPalette::WindowText, QPalette::Window);
       
  3034                 drawItemText(p, labelRect,  alignment, pal, gb->state & State_Enabled,
       
  3035                              gb->text, QPalette::WindowText);
       
  3036             }
       
  3037 
       
  3038                         return;
       
  3039         }
       
  3040         break;
       
  3041 
       
  3042     case CC_ToolButton:
       
  3043         if (const QStyleOptionToolButton *tool = qstyleoption_cast<const QStyleOptionToolButton *>(opt)) {
       
  3044             QStyleOptionToolButton toolOpt(*tool);
       
  3045             rule.configurePalette(&toolOpt.palette, QPalette::ButtonText, QPalette::Button);
       
  3046             toolOpt.font = rule.font.resolve(toolOpt.font);
       
  3047             toolOpt.rect = rule.borderRect(opt->rect);
       
  3048             bool customArrow = (tool->features & (QStyleOptionToolButton::HasMenu | QStyleOptionToolButton::MenuButtonPopup));
       
  3049             bool customDropDown = tool->features & QStyleOptionToolButton::MenuButtonPopup;
       
  3050             if (rule.hasNativeBorder()) {
       
  3051                 if (tool->subControls & SC_ToolButton) {
       
  3052                     //in some case (eg. the button is "auto raised") the style doesn't draw the background
       
  3053                     //so we need to draw the background.
       
  3054                     // use the same condition as in QCommonStyle
       
  3055                     State bflags = tool->state & ~State_Sunken;
       
  3056                     if (bflags & State_AutoRaise && (!(bflags & State_MouseOver) || !(bflags & State_Enabled)))
       
  3057                             bflags &= ~State_Raised;
       
  3058                     if (tool->state & State_Sunken && tool->activeSubControls & SC_ToolButton)
       
  3059                             bflags |= State_Sunken;
       
  3060                     if (!(bflags & (State_Sunken | State_On | State_Raised)))
       
  3061                         rule.drawBackground(p, toolOpt.rect);
       
  3062                 }
       
  3063                 customArrow = customArrow && hasStyleRule(w, PseudoElement_ToolButtonDownArrow);
       
  3064                 if (customArrow)
       
  3065                     toolOpt.features &= ~QStyleOptionToolButton::HasMenu;
       
  3066                 customDropDown = customDropDown && hasStyleRule(w, PseudoElement_ToolButtonMenu);
       
  3067                 if (customDropDown)
       
  3068                     toolOpt.subControls &= ~QStyle::SC_ToolButtonMenu;
       
  3069 
       
  3070                 if (rule.baseStyleCanDraw() && !(tool->features & QStyleOptionToolButton::Arrow)) {
       
  3071                     baseStyle()->drawComplexControl(cc, &toolOpt, p, w);
       
  3072                 } else {
       
  3073                     QWindowsStyle::drawComplexControl(cc, &toolOpt, p, w);
       
  3074                 }
       
  3075 
       
  3076                 if (!customArrow && !customDropDown)
       
  3077                     return;
       
  3078             } else {
       
  3079                 rule.drawRule(p, opt->rect);
       
  3080                 toolOpt.rect = rule.contentsRect(opt->rect);
       
  3081                 if (rule.hasFont)
       
  3082                     toolOpt.font = rule.font;
       
  3083                 drawControl(CE_ToolButtonLabel, &toolOpt, p, w);
       
  3084             }
       
  3085 
       
  3086             QRenderRule subRule = renderRule(w, opt, PseudoElement_ToolButtonMenu);
       
  3087             QRect r = subControlRect(CC_ToolButton, opt, QStyle::SC_ToolButtonMenu, w);
       
  3088             if (customDropDown) {
       
  3089                 if (opt->subControls & QStyle::SC_ToolButtonMenu) {
       
  3090                     if (subRule.hasDrawable()) {
       
  3091                         subRule.drawRule(p, r);
       
  3092                     } else {
       
  3093                         toolOpt.rect = r;
       
  3094                         baseStyle()->drawPrimitive(PE_IndicatorButtonDropDown, &toolOpt, p, w);
       
  3095                     }
       
  3096                 }
       
  3097             }
       
  3098 
       
  3099             if (customArrow) {
       
  3100                 QRenderRule subRule2 = customDropDown ? renderRule(w, opt, PseudoElement_ToolButtonMenuArrow)
       
  3101                                                       : renderRule(w, opt, PseudoElement_ToolButtonDownArrow);
       
  3102                 QRect r2 = customDropDown
       
  3103                           ? positionRect(w, subRule, subRule2, PseudoElement_ToolButtonMenuArrow, r, opt->direction)
       
  3104                           : positionRect(w, rule, subRule2, PseudoElement_ToolButtonDownArrow, opt->rect, opt->direction);
       
  3105                 if (subRule2.hasDrawable()) {
       
  3106                     subRule2.drawRule(p, r2);
       
  3107                 } else {
       
  3108                     toolOpt.rect = r2;
       
  3109                     baseStyle()->drawPrimitive(QStyle::PE_IndicatorArrowDown, &toolOpt, p, w);
       
  3110                 }
       
  3111             }
       
  3112 
       
  3113             return;
       
  3114         }
       
  3115         break;
       
  3116 
       
  3117 #ifndef QT_NO_SCROLLBAR
       
  3118     case CC_ScrollBar:
       
  3119         if (const QStyleOptionSlider *sb = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
       
  3120             QStyleOptionSlider sbOpt(*sb);
       
  3121             if (!rule.hasDrawable()) {
       
  3122                 sbOpt.rect = rule.borderRect(opt->rect);
       
  3123                 rule.drawBackgroundImage(p, opt->rect);
       
  3124                 baseStyle()->drawComplexControl(cc, &sbOpt, p, w);
       
  3125             } else {
       
  3126                 rule.drawRule(p, opt->rect);
       
  3127                 QWindowsStyle::drawComplexControl(cc, opt, p, w);
       
  3128             }
       
  3129             return;
       
  3130         }
       
  3131         break;
       
  3132 #endif // QT_NO_SCROLLBAR
       
  3133 
       
  3134 #ifndef QT_NO_SLIDER
       
  3135     case CC_Slider:
       
  3136         if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
       
  3137             rule.drawRule(p, opt->rect);
       
  3138 
       
  3139             QRenderRule grooveSubRule = renderRule(w, opt, PseudoElement_SliderGroove);
       
  3140             QRenderRule handleSubRule = renderRule(w, opt, PseudoElement_SliderHandle);
       
  3141             if (!grooveSubRule.hasDrawable()) {
       
  3142                 QStyleOptionSlider slOpt(*slider);
       
  3143                 bool handleHasRule = handleSubRule.hasDrawable();
       
  3144                 // If the style specifies a different handler rule, draw the groove without the handler.
       
  3145                 if (handleHasRule)
       
  3146                     slOpt.subControls &= ~SC_SliderHandle;
       
  3147                 baseStyle()->drawComplexControl(cc, &slOpt, p, w);
       
  3148                 if (!handleHasRule)
       
  3149                     return;
       
  3150             }
       
  3151 
       
  3152             QRect gr = subControlRect(cc, opt, SC_SliderGroove, w);
       
  3153             if (slider->subControls & SC_SliderGroove) {
       
  3154                 grooveSubRule.drawRule(p, gr);
       
  3155             }
       
  3156 
       
  3157             if (slider->subControls & SC_SliderHandle) {
       
  3158                 QRect hr = subControlRect(cc, opt, SC_SliderHandle, w);
       
  3159 
       
  3160                 QRenderRule subRule1 = renderRule(w, opt, PseudoElement_SliderSubPage);
       
  3161                 if (subRule1.hasDrawable()) {
       
  3162                     QRect r(gr.topLeft(),
       
  3163                             slider->orientation == Qt::Horizontal
       
  3164                                 ? QPoint(hr.x()+hr.width()/2, gr.y()+gr.height())
       
  3165                                 : QPoint(gr.x()+gr.width(), hr.y()+hr.height()/2));
       
  3166                     subRule1.drawRule(p, r);
       
  3167                 }
       
  3168 
       
  3169                 QRenderRule subRule2 = renderRule(w, opt, PseudoElement_SliderAddPage);
       
  3170                 if (subRule2.hasDrawable()) {
       
  3171                     QRect r(slider->orientation == Qt::Horizontal
       
  3172                                 ? QPoint(hr.x()+hr.width()/2+1, gr.y())
       
  3173                                 : QPoint(gr.x(), hr.y()+hr.height()/2+1),
       
  3174                             gr.bottomRight());
       
  3175                     subRule2.drawRule(p, r);
       
  3176                 }
       
  3177 
       
  3178                 handleSubRule.drawRule(p, grooveSubRule.boxRect(hr, Margin));
       
  3179             }
       
  3180 
       
  3181             if (slider->subControls & SC_SliderTickmarks) {
       
  3182                 // TODO...
       
  3183             }
       
  3184 
       
  3185             return;
       
  3186         }
       
  3187         break;
       
  3188 #endif // QT_NO_SLIDER
       
  3189 
       
  3190     case CC_MdiControls:
       
  3191         if (hasStyleRule(w, PseudoElement_MdiCloseButton)
       
  3192             || hasStyleRule(w, PseudoElement_MdiNormalButton)
       
  3193             || hasStyleRule(w, PseudoElement_MdiMinButton)) {
       
  3194             QList<QVariant> layout = rule.styleHint(QLatin1String("button-layout")).toList();
       
  3195             if (layout.isEmpty())
       
  3196                 layout = subControlLayout(QLatin1String("mNX"));
       
  3197 
       
  3198             QStyleOptionComplex optCopy(*opt);
       
  3199             optCopy.subControls = 0;
       
  3200             for (int i = 0; i < layout.count(); i++) {
       
  3201                 int layoutButton = layout[i].toInt();
       
  3202                 if (layoutButton < PseudoElement_MdiCloseButton
       
  3203                     || layoutButton > PseudoElement_MdiNormalButton)
       
  3204                     continue;
       
  3205                 QStyle::SubControl control = knownPseudoElements[layoutButton].subControl;
       
  3206                 if (!(opt->subControls & control))
       
  3207                     continue;
       
  3208                 QRenderRule subRule = renderRule(w, opt, layoutButton);
       
  3209                 if (subRule.hasDrawable()) {
       
  3210                     QRect rect = subRule.boxRect(subControlRect(CC_MdiControls, opt, control, w), Margin);
       
  3211                     subRule.drawRule(p, rect);
       
  3212                     QIcon icon = standardIcon(subControlIcon(layoutButton), opt);
       
  3213                     icon.paint(p, subRule.contentsRect(rect), Qt::AlignCenter);
       
  3214                 } else {
       
  3215                     optCopy.subControls |= control;
       
  3216                 }
       
  3217             }
       
  3218 
       
  3219             if (optCopy.subControls)
       
  3220                 baseStyle()->drawComplexControl(CC_MdiControls, &optCopy, p, w);
       
  3221             return;
       
  3222         }
       
  3223         break;
       
  3224 
       
  3225     case CC_TitleBar:
       
  3226         if (const QStyleOptionTitleBar *tb = qstyleoption_cast<const QStyleOptionTitleBar *>(opt)) {
       
  3227             QRenderRule subRule = renderRule(w, opt, PseudoElement_TitleBar);
       
  3228             if (!subRule.hasDrawable() && !subRule.hasBox() && !subRule.hasBorder())
       
  3229                 break;
       
  3230             subRule.drawRule(p, opt->rect);
       
  3231             QHash<QStyle::SubControl, QRect> layout = titleBarLayout(w, tb);
       
  3232 
       
  3233             QRect ir;
       
  3234             ir = layout[SC_TitleBarLabel];
       
  3235             if (ir.isValid()) {
       
  3236                 if (subRule.hasPalette())
       
  3237                     p->setPen(subRule.palette()->foreground.color());
       
  3238                 p->fillRect(ir, Qt::white);
       
  3239                 p->drawText(ir.x(), ir.y(), ir.width(), ir.height(), Qt::AlignLeft | Qt::AlignVCenter | Qt::TextSingleLine, tb->text);
       
  3240             }
       
  3241 
       
  3242             QPixmap pm;
       
  3243 
       
  3244             ir = layout[SC_TitleBarSysMenu];
       
  3245             if (ir.isValid()) {
       
  3246                 QRenderRule subSubRule = renderRule(w, opt, PseudoElement_TitleBarSysMenu);
       
  3247                 subSubRule.drawRule(p, ir);
       
  3248                 ir = subSubRule.contentsRect(ir);
       
  3249                 if (!tb->icon.isNull()) {
       
  3250                     tb->icon.paint(p, ir);
       
  3251                 } else {
       
  3252                     int iconSize = pixelMetric(PM_SmallIconSize, tb, w);
       
  3253                     pm = standardIcon(SP_TitleBarMenuButton, 0, w).pixmap(iconSize, iconSize);
       
  3254                     drawItemPixmap(p, ir, Qt::AlignCenter, pm);
       
  3255                 }
       
  3256             }
       
  3257 
       
  3258             ir = layout[SC_TitleBarCloseButton];
       
  3259             if (ir.isValid()) {
       
  3260                 QRenderRule subSubRule = renderRule(w, opt, PseudoElement_TitleBarCloseButton);
       
  3261                 subSubRule.drawRule(p, ir);
       
  3262 
       
  3263                 QSize sz = subSubRule.contentsRect(ir).size();
       
  3264                 if ((tb->titleBarFlags & Qt::WindowType_Mask) == Qt::Tool)
       
  3265                     pm = standardIcon(SP_DockWidgetCloseButton, 0, w).pixmap(sz);
       
  3266                 else
       
  3267                     pm = standardIcon(SP_TitleBarCloseButton, 0, w).pixmap(sz);
       
  3268                 drawItemPixmap(p, ir, Qt::AlignCenter, pm);
       
  3269             }
       
  3270 
       
  3271             int pes[] = {
       
  3272                 PseudoElement_TitleBarMaxButton,
       
  3273                 PseudoElement_TitleBarMinButton,
       
  3274                 PseudoElement_TitleBarNormalButton,
       
  3275                 PseudoElement_TitleBarShadeButton,
       
  3276                 PseudoElement_TitleBarUnshadeButton,
       
  3277                 PseudoElement_TitleBarContextHelpButton
       
  3278             };
       
  3279 
       
  3280             for (unsigned int i = 0; i < sizeof(pes)/sizeof(int); i++) {
       
  3281                 int pe = pes[i];
       
  3282                 QStyle::SubControl sc = knownPseudoElements[pe].subControl;
       
  3283                 ir = layout[sc];
       
  3284                 if (!ir.isValid())
       
  3285                     continue;
       
  3286                 QRenderRule subSubRule = renderRule(w, opt, pe);
       
  3287                 subSubRule.drawRule(p, ir);
       
  3288                 pm = standardIcon(subControlIcon(pe), 0, w).pixmap(subSubRule.contentsRect(ir).size());
       
  3289                 drawItemPixmap(p, ir, Qt::AlignCenter, pm);
       
  3290             }
       
  3291 
       
  3292             return;
       
  3293         }
       
  3294         break;
       
  3295 
       
  3296 
       
  3297     default:
       
  3298         break;
       
  3299     }
       
  3300 
       
  3301     baseStyle()->drawComplexControl(cc, opt, p, w);
       
  3302 }
       
  3303 
       
  3304 void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter *p,
       
  3305                           const QWidget *w) const
       
  3306 {
       
  3307     RECURSION_GUARD(baseStyle()->drawControl(ce, opt, p, w); return)
       
  3308 
       
  3309     QRenderRule rule = renderRule(w, opt);
       
  3310     int pe1 = PseudoElement_None, pe2 = PseudoElement_None;
       
  3311     bool fallback = false;
       
  3312 
       
  3313     switch (ce) {
       
  3314     case CE_ToolButtonLabel:
       
  3315         if (const QStyleOptionToolButton *btn = qstyleoption_cast<const QStyleOptionToolButton *>(opt)) {
       
  3316             if (rule.hasBox() || btn->features & QStyleOptionToolButton::Arrow) {
       
  3317                 QCommonStyle::drawControl(ce, opt, p, w);
       
  3318             } else {
       
  3319                 QStyleOptionToolButton butOpt(*btn);
       
  3320                 rule.configurePalette(&butOpt.palette, QPalette::ButtonText, QPalette::Button);
       
  3321                 baseStyle()->drawControl(ce, &butOpt, p, w);
       
  3322             }
       
  3323             return;
       
  3324         }
       
  3325         break;
       
  3326 
       
  3327     case CE_PushButton:
       
  3328         ParentStyle::drawControl(ce, opt, p, w);
       
  3329         return;
       
  3330 
       
  3331     case CE_PushButtonBevel:
       
  3332         if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
       
  3333             QStyleOptionButton btnOpt(*btn);
       
  3334             btnOpt.rect = rule.borderRect(opt->rect);
       
  3335             if (rule.hasNativeBorder()) {
       
  3336                 rule.drawBackgroundImage(p, btnOpt.rect);
       
  3337                 rule.configurePalette(&btnOpt.palette, QPalette::ButtonText, QPalette::Button);
       
  3338                 bool customMenu = (btn->features & QStyleOptionButton::HasMenu
       
  3339                                    && hasStyleRule(w, PseudoElement_PushButtonMenuIndicator));
       
  3340                 if (customMenu)
       
  3341                     btnOpt.features &= ~QStyleOptionButton::HasMenu;
       
  3342                 if (rule.baseStyleCanDraw()) {
       
  3343                     baseStyle()->drawControl(ce, &btnOpt, p, w);
       
  3344                 } else {
       
  3345                     QWindowsStyle::drawControl(ce, &btnOpt, p, w);
       
  3346                 }
       
  3347                 if (!customMenu)
       
  3348                     return;
       
  3349             } else {
       
  3350                 rule.drawRule(p, opt->rect);
       
  3351             }
       
  3352 
       
  3353             if (btn->features & QStyleOptionButton::HasMenu) {
       
  3354                 QRenderRule subRule = renderRule(w, opt, PseudoElement_PushButtonMenuIndicator);
       
  3355                 QRect ir = positionRect(w, rule, subRule, PseudoElement_PushButtonMenuIndicator, opt->rect, opt->direction);
       
  3356                 if (subRule.hasDrawable()) {
       
  3357                     subRule.drawRule(p, ir);
       
  3358                 } else {
       
  3359                     btnOpt.rect = ir;
       
  3360                     baseStyle()->drawPrimitive(PE_IndicatorArrowDown, &btnOpt, p, w);
       
  3361                 }
       
  3362             }
       
  3363         }
       
  3364         return;
       
  3365 
       
  3366     case CE_PushButtonLabel:
       
  3367         if (const QStyleOptionButton *button = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
       
  3368             QStyleOptionButton butOpt(*button);
       
  3369             rule.configurePalette(&butOpt.palette, QPalette::ButtonText, QPalette::Button);
       
  3370             if (rule.hasPosition() && rule.position()->textAlignment != 0) {
       
  3371                 Qt::Alignment textAlignment = rule.position()->textAlignment;
       
  3372                 QRect textRect = button->rect;
       
  3373                 uint tf = Qt::AlignVCenter | Qt::TextShowMnemonic;
       
  3374                 if (!styleHint(SH_UnderlineShortcut, button, w))
       
  3375                     tf |= Qt::TextHideMnemonic;
       
  3376                 if (!button->icon.isNull()) {
       
  3377                     //Group both icon and text
       
  3378                     QRect iconRect;
       
  3379                     QIcon::Mode mode = button->state & State_Enabled ? QIcon::Normal : QIcon::Disabled;
       
  3380                     if (mode == QIcon::Normal && button->state & State_HasFocus)
       
  3381                         mode = QIcon::Active;
       
  3382                     QIcon::State state = QIcon::Off;
       
  3383                     if (button->state & State_On)
       
  3384                         state = QIcon::On;
       
  3385 
       
  3386                     QPixmap pixmap = button->icon.pixmap(button->iconSize, mode, state);
       
  3387                     int labelWidth = pixmap.width();
       
  3388                     int labelHeight = pixmap.height();
       
  3389                     int iconSpacing = 4;//### 4 is currently hardcoded in QPushButton::sizeHint()
       
  3390                     int textWidth = button->fontMetrics.boundingRect(opt->rect, tf, button->text).width();
       
  3391                     if (!button->text.isEmpty())
       
  3392                         labelWidth += (textWidth + iconSpacing);
       
  3393 
       
  3394                     //Determine label alignment:
       
  3395                     if (textAlignment & Qt::AlignLeft) { /*left*/
       
  3396                         iconRect = QRect(textRect.x(), textRect.y() + (textRect.height() - labelHeight) / 2,
       
  3397                                          pixmap.width(), pixmap.height());
       
  3398                     } else if (textAlignment & Qt::AlignHCenter) { /* center */
       
  3399                         iconRect = QRect(textRect.x() + (textRect.width() - labelWidth) / 2,
       
  3400                                          textRect.y() + (textRect.height() - labelHeight) / 2,
       
  3401                                          pixmap.width(), pixmap.height());
       
  3402                     } else { /*right*/
       
  3403                         iconRect = QRect(textRect.x() + textRect.width() - labelWidth,
       
  3404                                          textRect.y() + (textRect.height() - labelHeight) / 2,
       
  3405                                          pixmap.width(), pixmap.height());
       
  3406                     }
       
  3407 
       
  3408                     iconRect = visualRect(button->direction, textRect, iconRect);
       
  3409 
       
  3410                     tf |= Qt::AlignLeft; //left align, we adjust the text-rect instead
       
  3411 
       
  3412                     if (button->direction == Qt::RightToLeft)
       
  3413                         textRect.setRight(iconRect.left() - iconSpacing);
       
  3414                     else
       
  3415                         textRect.setLeft(iconRect.left() + iconRect.width() + iconSpacing);
       
  3416 
       
  3417                     if (button->state & (State_On | State_Sunken))
       
  3418                         iconRect.translate(pixelMetric(PM_ButtonShiftHorizontal, opt, w),
       
  3419                                            pixelMetric(PM_ButtonShiftVertical, opt, w));
       
  3420                     p->drawPixmap(iconRect, pixmap);
       
  3421                 } else {
       
  3422                     tf |= textAlignment;
       
  3423                 }
       
  3424                 if (button->state & (State_On | State_Sunken))
       
  3425                     textRect.translate(pixelMetric(PM_ButtonShiftHorizontal, opt, w),
       
  3426                                  pixelMetric(PM_ButtonShiftVertical, opt, w));
       
  3427 
       
  3428                 if (button->features & QStyleOptionButton::HasMenu) {
       
  3429                     int indicatorSize = pixelMetric(PM_MenuButtonIndicator, button, w);
       
  3430                     if (button->direction == Qt::LeftToRight)
       
  3431                         textRect = textRect.adjusted(0, 0, -indicatorSize, 0);
       
  3432                     else
       
  3433                         textRect = textRect.adjusted(indicatorSize, 0, 0, 0);
       
  3434                 }
       
  3435                 drawItemText(p, textRect, tf, butOpt.palette, (button->state & State_Enabled),
       
  3436                              button->text, QPalette::ButtonText);
       
  3437             } else {
       
  3438                 ParentStyle::drawControl(ce, &butOpt, p, w);
       
  3439             }
       
  3440         }
       
  3441         return;
       
  3442 
       
  3443     case CE_RadioButton:
       
  3444     case CE_CheckBox:
       
  3445         rule.drawRule(p, opt->rect);
       
  3446         ParentStyle::drawControl(ce, opt, p, w);
       
  3447         return;
       
  3448 
       
  3449     case CE_RadioButtonLabel:
       
  3450     case CE_CheckBoxLabel:
       
  3451         if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
       
  3452             QStyleOptionButton butOpt(*btn);
       
  3453             rule.configurePalette(&butOpt.palette, QPalette::ButtonText, QPalette::Button);
       
  3454             ParentStyle::drawControl(ce, &butOpt, p, w);
       
  3455         }
       
  3456         return;
       
  3457 
       
  3458     case CE_Splitter:
       
  3459         pe1 = PseudoElement_SplitterHandle;
       
  3460         break;
       
  3461 
       
  3462     case CE_ToolBar:
       
  3463         if (rule.hasBackground()) {
       
  3464             rule.drawBackground(p, opt->rect);
       
  3465         }
       
  3466         if (rule.hasBorder()) {
       
  3467             rule.drawBorder(p, rule.borderRect(opt->rect));
       
  3468         } else {
       
  3469 #ifndef QT_NO_TOOLBAR
       
  3470             if (const QStyleOptionToolBar *tb = qstyleoption_cast<const QStyleOptionToolBar *>(opt)) {
       
  3471                 QStyleOptionToolBar newTb(*tb);
       
  3472                 newTb.rect = rule.borderRect(opt->rect);
       
  3473                 baseStyle()->drawControl(ce, &newTb, p, w);
       
  3474             }
       
  3475 #endif // QT_NO_TOOLBAR
       
  3476         }
       
  3477         return;
       
  3478 
       
  3479     case CE_MenuEmptyArea:
       
  3480     case CE_MenuBarEmptyArea:
       
  3481         if (rule.hasDrawable()) {
       
  3482             // Drawn by PE_Widget
       
  3483             return;
       
  3484         }
       
  3485         break;
       
  3486 
       
  3487     case CE_MenuTearoff:
       
  3488     case CE_MenuScroller:
       
  3489         if (const QStyleOptionMenuItem *m = qstyleoption_cast<const QStyleOptionMenuItem *>(opt)) {
       
  3490             QStyleOptionMenuItem mi(*m);
       
  3491             int pe = ce == CE_MenuTearoff ? PseudoElement_MenuTearoff : PseudoElement_MenuScroller;
       
  3492             QRenderRule subRule = renderRule(w, opt, pe);
       
  3493             mi.rect = subRule.contentsRect(opt->rect);
       
  3494             rule.configurePalette(&mi.palette, QPalette::ButtonText, QPalette::Button);
       
  3495             subRule.configurePalette(&mi.palette, QPalette::ButtonText, QPalette::Button);
       
  3496 
       
  3497             if (subRule.hasDrawable()) {
       
  3498                 subRule.drawRule(p, opt->rect);
       
  3499             } else {
       
  3500                 baseStyle()->drawControl(ce, &mi, p, w);
       
  3501             }
       
  3502         }
       
  3503         return;
       
  3504 
       
  3505     case CE_MenuItem:
       
  3506         if (const QStyleOptionMenuItem *m = qstyleoption_cast<const QStyleOptionMenuItem *>(opt)) {
       
  3507             QStyleOptionMenuItem mi(*m);
       
  3508 
       
  3509             int pseudo = (mi.menuItemType == QStyleOptionMenuItem::Separator) ? PseudoElement_MenuSeparator : PseudoElement_Item;
       
  3510             QRenderRule subRule = renderRule(w, opt, pseudo);
       
  3511             mi.rect = subRule.contentsRect(opt->rect);
       
  3512             rule.configurePalette(&mi.palette, QPalette::ButtonText, QPalette::Button);
       
  3513             rule.configurePalette(&mi.palette, QPalette::HighlightedText, QPalette::Highlight);
       
  3514             subRule.configurePalette(&mi.palette, QPalette::ButtonText, QPalette::Button);
       
  3515             subRule.configurePalette(&mi.palette, QPalette::HighlightedText, QPalette::Highlight);
       
  3516             QFont oldFont = p->font();
       
  3517             if (subRule.hasFont)
       
  3518                 p->setFont(subRule.font.resolve(p->font()));
       
  3519 
       
  3520             // We fall back to drawing with the style sheet code whenever at least one of the
       
  3521             // items are styled in an incompatible way, such as having a background image.
       
  3522             QRenderRule allRules = renderRule(w, PseudoElement_Item, PseudoClass_Any);
       
  3523 
       
  3524             if ((pseudo == PseudoElement_MenuSeparator) && subRule.hasDrawable()) {
       
  3525                 subRule.drawRule(p, opt->rect);
       
  3526             } else if ((pseudo == PseudoElement_Item)
       
  3527                         && (allRules.hasBox() || allRules.hasBorder()
       
  3528                             || (allRules.background() && !allRules.background()->pixmap.isNull()))) {
       
  3529                 subRule.drawRule(p, opt->rect);
       
  3530                 if (subRule.hasBackground()) {
       
  3531                     mi.palette.setBrush(QPalette::Highlight, Qt::NoBrush);
       
  3532                     mi.palette.setBrush(QPalette::Button, Qt::NoBrush);
       
  3533                 } else {
       
  3534                     mi.palette.setBrush(QPalette::Highlight, mi.palette.brush(QPalette::Button));
       
  3535                 }
       
  3536                 mi.palette.setBrush(QPalette::HighlightedText, mi.palette.brush(QPalette::ButtonText));
       
  3537 
       
  3538                 bool checkable = mi.checkType != QStyleOptionMenuItem::NotCheckable;
       
  3539                 bool checked = checkable ? mi.checked : false;
       
  3540 
       
  3541                 bool dis = !(opt->state & QStyle::State_Enabled),
       
  3542                      act = opt->state & QStyle::State_Selected;
       
  3543 
       
  3544                 if (!mi.icon.isNull()) {
       
  3545                     QIcon::Mode mode = dis ? QIcon::Disabled : QIcon::Normal;
       
  3546                     if (act && !dis)
       
  3547                         mode = QIcon::Active;
       
  3548                     QPixmap pixmap;
       
  3549                     if (checked)
       
  3550                         pixmap = mi.icon.pixmap(pixelMetric(PM_SmallIconSize), mode, QIcon::On);
       
  3551                     else
       
  3552                         pixmap = mi.icon.pixmap(pixelMetric(PM_SmallIconSize), mode);
       
  3553                     int pixw = pixmap.width();
       
  3554                     int pixh = pixmap.height();
       
  3555                     QRenderRule iconRule = renderRule(w, opt, PseudoElement_MenuIcon);
       
  3556                     if (!iconRule.hasGeometry()) {
       
  3557                         iconRule.geo = new QStyleSheetGeometryData(pixw, pixh, pixw, pixh, -1, -1);
       
  3558                     } else {
       
  3559                         iconRule.geo->width = pixw;
       
  3560                         iconRule.geo->height = pixh;
       
  3561                     }
       
  3562                     QRect iconRect = positionRect(w, subRule, iconRule, PseudoElement_MenuIcon, opt->rect, opt->direction);
       
  3563                     iconRule.drawRule(p, iconRect);
       
  3564                     QRect pmr(0, 0, pixw, pixh);
       
  3565                     pmr.moveCenter(iconRect.center());
       
  3566                     p->drawPixmap(pmr.topLeft(), pixmap);
       
  3567                 } else if (checkable) {
       
  3568                     QRenderRule subSubRule = renderRule(w, opt, PseudoElement_MenuCheckMark);
       
  3569                     if (subSubRule.hasDrawable() || checked) {
       
  3570                         QStyleOptionMenuItem newMi = mi;
       
  3571                         newMi.rect = positionRect(w, subRule, subSubRule, PseudoElement_MenuCheckMark, opt->rect, opt->direction);
       
  3572                         drawPrimitive(PE_IndicatorMenuCheckMark, &newMi, p, w);
       
  3573                     }
       
  3574                 }
       
  3575 
       
  3576                 QRect textRect = subRule.contentsRect(opt->rect);
       
  3577                 textRect.setWidth(textRect.width() - mi.tabWidth);
       
  3578                 QString s = mi.text;
       
  3579                 p->setPen(mi.palette.buttonText().color());
       
  3580                 if (!s.isEmpty()) {
       
  3581                     int text_flags = Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine;
       
  3582                     if (!styleHint(SH_UnderlineShortcut, &mi, w))
       
  3583                         text_flags |= Qt::TextHideMnemonic;
       
  3584                     int t = s.indexOf(QLatin1Char('\t'));
       
  3585                     if (t >= 0) {
       
  3586                         QRect vShortcutRect = visualRect(opt->direction, mi.rect,
       
  3587                             QRect(textRect.topRight(), QPoint(mi.rect.right(), textRect.bottom())));
       
  3588                         p->drawText(vShortcutRect, text_flags, s.mid(t + 1));
       
  3589                         s = s.left(t);
       
  3590                     }
       
  3591                     p->drawText(textRect, text_flags, s.left(t));
       
  3592                 }
       
  3593 
       
  3594                 if (mi.menuItemType == QStyleOptionMenuItem::SubMenu) {// draw sub menu arrow
       
  3595                     PrimitiveElement arrow = (opt->direction == Qt::RightToLeft) ? PE_IndicatorArrowLeft : PE_IndicatorArrowRight;
       
  3596                     QRenderRule subRule2 = renderRule(w, opt, PseudoElement_MenuRightArrow);
       
  3597                     mi.rect = positionRect(w, subRule, subRule2, PseudoElement_MenuRightArrow, opt->rect, mi.direction);
       
  3598                     drawPrimitive(arrow, &mi, p, w);
       
  3599                 }
       
  3600             } else if (hasStyleRule(w, PseudoElement_MenuCheckMark) || hasStyleRule(w, PseudoElement_MenuRightArrow)) {
       
  3601                 QWindowsStyle::drawControl(ce, &mi, p, w);
       
  3602             } else {
       
  3603                 if (rule.hasDrawable() && !subRule.hasDrawable() && !(opt->state & QStyle::State_Selected)) {
       
  3604                     mi.palette.setColor(QPalette::Window, Qt::transparent);
       
  3605                     mi.palette.setColor(QPalette::Button, Qt::transparent);
       
  3606                 }
       
  3607                 if (rule.baseStyleCanDraw() && subRule.baseStyleCanDraw()) {
       
  3608                     baseStyle()->drawControl(ce, &mi, p, w);
       
  3609                 } else {
       
  3610                     ParentStyle::drawControl(ce, &mi, p, w);
       
  3611                 }
       
  3612             }
       
  3613 
       
  3614             if (subRule.hasFont)
       
  3615                 p->setFont(oldFont);
       
  3616 
       
  3617             return;
       
  3618         }
       
  3619         return;
       
  3620 
       
  3621     case CE_MenuBarItem:
       
  3622         if (const QStyleOptionMenuItem *m = qstyleoption_cast<const QStyleOptionMenuItem *>(opt)) {
       
  3623             QStyleOptionMenuItem mi(*m);
       
  3624             QRenderRule subRule = renderRule(w, opt, PseudoElement_Item);
       
  3625             mi.rect = subRule.contentsRect(opt->rect);
       
  3626             rule.configurePalette(&mi.palette, QPalette::ButtonText, QPalette::Button);
       
  3627             subRule.configurePalette(&mi.palette, QPalette::ButtonText, QPalette::Button);
       
  3628 
       
  3629             if (subRule.hasDrawable()) {
       
  3630                 subRule.drawRule(p, opt->rect);
       
  3631                 QCommonStyle::drawControl(ce, &mi, p, w);
       
  3632             } else {
       
  3633                 if (rule.hasDrawable() && !(opt->state & QStyle::State_Selected)) {
       
  3634                     // So that the menu bar background is not hidden by the items
       
  3635                     mi.palette.setColor(QPalette::Window, Qt::transparent);
       
  3636                     mi.palette.setColor(QPalette::Button, Qt::transparent);
       
  3637                 }
       
  3638                 baseStyle()->drawControl(ce, &mi, p, w);
       
  3639             }
       
  3640         }
       
  3641         return;
       
  3642 
       
  3643 #ifndef QT_NO_COMBOBOX
       
  3644     case CE_ComboBoxLabel:
       
  3645         if (!rule.hasBox())
       
  3646             break;
       
  3647         if (const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(opt)) {
       
  3648             QRect editRect = subControlRect(CC_ComboBox, cb, SC_ComboBoxEditField, w);
       
  3649             p->save();
       
  3650             p->setClipRect(editRect);
       
  3651             if (!cb->currentIcon.isNull()) {
       
  3652                 int spacing = rule.hasBox() ? rule.box()->spacing : -1;
       
  3653                 if (spacing == -1)
       
  3654                     spacing = 6;
       
  3655                 QIcon::Mode mode = cb->state & State_Enabled ? QIcon::Normal : QIcon::Disabled;
       
  3656                 QPixmap pixmap = cb->currentIcon.pixmap(cb->iconSize, mode);
       
  3657                 QRect iconRect(editRect);
       
  3658                 iconRect.setWidth(cb->iconSize.width());
       
  3659                 iconRect = alignedRect(cb->direction,
       
  3660                                        Qt::AlignLeft | Qt::AlignVCenter,
       
  3661                                        iconRect.size(), editRect);
       
  3662                 drawItemPixmap(p, iconRect, Qt::AlignCenter, pixmap);
       
  3663 
       
  3664                 if (cb->direction == Qt::RightToLeft)
       
  3665                         editRect.translate(-spacing - cb->iconSize.width(), 0);
       
  3666                 else
       
  3667                         editRect.translate(cb->iconSize.width() + spacing, 0);
       
  3668             }
       
  3669             if (!cb->currentText.isEmpty() && !cb->editable) {
       
  3670                 drawItemText(p, editRect.adjusted(0, 0, 0, 0), Qt::AlignLeft | Qt::AlignVCenter, cb->palette,
       
  3671                              cb->state & State_Enabled, cb->currentText);
       
  3672             }
       
  3673             p->restore();
       
  3674             return;
       
  3675         }
       
  3676         break;
       
  3677 #endif // QT_NO_COMBOBOX
       
  3678 
       
  3679     case CE_Header:
       
  3680         if (hasStyleRule(w, PseudoElement_HeaderViewUpArrow)
       
  3681             || hasStyleRule(w, PseudoElement_HeaderViewDownArrow)) {
       
  3682             ParentStyle::drawControl(ce, opt, p, w);
       
  3683             return;
       
  3684         }
       
  3685         if(hasStyleRule(w, PseudoElement_HeaderViewSection)) {
       
  3686             QRenderRule subRule = renderRule(w, opt, PseudoElement_HeaderViewSection);
       
  3687             if (!subRule.hasNativeBorder() || !subRule.baseStyleCanDraw()
       
  3688                 || subRule.hasBackground() || subRule.hasPalette()) {
       
  3689                 ParentStyle::drawControl(ce, opt, p, w);
       
  3690                 return;
       
  3691             }
       
  3692         }
       
  3693         break;
       
  3694     case CE_HeaderSection:
       
  3695         if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(opt)) {
       
  3696             QRenderRule subRule = renderRule(w, opt, PseudoElement_HeaderViewSection);
       
  3697             if (subRule.hasNativeBorder()) {
       
  3698                 QStyleOptionHeader hdr(*header);
       
  3699                 subRule.configurePalette(&hdr.palette, QPalette::ButtonText, QPalette::Button);
       
  3700 
       
  3701                 if (subRule.baseStyleCanDraw()) {
       
  3702                     baseStyle()->drawControl(CE_HeaderSection, &hdr, p, w);
       
  3703                 } else {
       
  3704                     QWindowsStyle::drawControl(CE_HeaderSection, &hdr, p, w);
       
  3705                 }
       
  3706             } else {
       
  3707                 subRule.drawRule(p, opt->rect);
       
  3708             }
       
  3709             return;
       
  3710         }
       
  3711         break;
       
  3712 
       
  3713     case CE_HeaderLabel:
       
  3714         if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(opt)) {
       
  3715             QStyleOptionHeader hdr(*header);
       
  3716             QRenderRule subRule = renderRule(w, opt, PseudoElement_HeaderViewSection);
       
  3717             subRule.configurePalette(&hdr.palette, QPalette::ButtonText, QPalette::Button);
       
  3718             QFont oldFont = p->font();
       
  3719             if (subRule.hasFont)
       
  3720                 p->setFont(subRule.font.resolve(p->font()));
       
  3721             baseStyle()->drawControl(ce, &hdr, p, w);
       
  3722             if (subRule.hasFont)
       
  3723                 p->setFont(oldFont);
       
  3724             return;
       
  3725         }
       
  3726         break;
       
  3727 
       
  3728     case CE_HeaderEmptyArea:
       
  3729         if (rule.hasDrawable()) {
       
  3730             return;
       
  3731         }
       
  3732         break;
       
  3733 
       
  3734     case CE_ProgressBar:
       
  3735         QWindowsStyle::drawControl(ce, opt, p, w);
       
  3736         return;
       
  3737 
       
  3738     case CE_ProgressBarGroove:
       
  3739         if (!rule.hasNativeBorder()) {
       
  3740             rule.drawRule(p, rule.boxRect(opt->rect, Margin));
       
  3741             return;
       
  3742         }
       
  3743         break;
       
  3744 
       
  3745     case CE_ProgressBarContents: {
       
  3746         QRenderRule subRule = renderRule(w, opt, PseudoElement_ProgressBarChunk);
       
  3747         if (subRule.hasDrawable()) {
       
  3748             if (const QStyleOptionProgressBarV2 *pb = qstyleoption_cast<const QStyleOptionProgressBarV2 *>(opt)) {
       
  3749                 p->save();
       
  3750                 p->setClipRect(pb->rect);
       
  3751 
       
  3752                 qint64 minimum = qint64(pb->minimum);
       
  3753                 qint64 maximum = qint64(pb->maximum);
       
  3754                 qint64 progress = qint64(pb->progress);
       
  3755                 bool vertical = (pb->orientation == Qt::Vertical);
       
  3756                 bool inverted = pb->invertedAppearance;
       
  3757 
       
  3758                 QTransform m;
       
  3759                 QRect rect = pb->rect;
       
  3760                 if (vertical) {
       
  3761                     rect = QRect(rect.y(), rect.x(), rect.height(), rect.width());
       
  3762                     m.rotate(90);
       
  3763                     m.translate(0, -(rect.height() + rect.y()*2));
       
  3764                 }
       
  3765 
       
  3766                 bool reverse = ((!vertical && (pb->direction == Qt::RightToLeft)) || vertical);
       
  3767                 if (inverted)
       
  3768                     reverse = !reverse;
       
  3769                 const bool indeterminate = pb->minimum == pb->maximum;
       
  3770                 qreal fillRatio = indeterminate ? 0.50 : qreal(progress - minimum)/(maximum - minimum);
       
  3771                 int fillWidth = int(rect.width() * fillRatio);
       
  3772                 int chunkWidth = fillWidth;
       
  3773                 if (subRule.hasContentsSize()) {
       
  3774                     QSize sz = subRule.size();
       
  3775                     chunkWidth = (opt->state & QStyle::State_Horizontal) ? sz.width() : sz.height();
       
  3776                 }
       
  3777 
       
  3778                 QRect r = rect;
       
  3779                 if (pb->minimum == 0 && pb->maximum == 0) {
       
  3780                     Q_D(const QWindowsStyle);
       
  3781                     int chunkCount = fillWidth/chunkWidth;
       
  3782                     int offset = (d->animateStep*8%rect.width());
       
  3783                     int x = reverse ? r.left() + r.width() - offset - chunkWidth : r.x() + offset;
       
  3784                     while (chunkCount > 0) {
       
  3785                         r.setRect(x, rect.y(), chunkWidth, rect.height());
       
  3786                         r = m.mapRect(QRectF(r)).toRect();
       
  3787                         subRule.drawRule(p, r);
       
  3788                         x += reverse ? -chunkWidth : chunkWidth;
       
  3789                         if (reverse ? x < rect.left() : x > rect.right())
       
  3790                             break;
       
  3791                         --chunkCount;
       
  3792                     }
       
  3793 
       
  3794                     r = rect;
       
  3795                     x = reverse ? r.right() - (r.left() - x - chunkWidth)
       
  3796                                 : r.left() + (x - r.right() - chunkWidth);
       
  3797                     while (chunkCount > 0) {
       
  3798                         r.setRect(x, rect.y(), chunkWidth, rect.height());
       
  3799                         r = m.mapRect(QRectF(r)).toRect();
       
  3800                         subRule.drawRule(p, r);
       
  3801                         x += reverse ? -chunkWidth : chunkWidth;
       
  3802                         --chunkCount;
       
  3803                     };
       
  3804                 } else {
       
  3805                     int x = reverse ? r.left() + r.width() - chunkWidth : r.x();
       
  3806 
       
  3807                     for (int i = 0; i < ceil(qreal(fillWidth)/chunkWidth); ++i) {
       
  3808                         r.setRect(x, rect.y(), chunkWidth, rect.height());
       
  3809                         r = m.mapRect(QRectF(r)).toRect();
       
  3810                         subRule.drawRule(p, r);
       
  3811                         x += reverse ? -chunkWidth : chunkWidth;
       
  3812                     }
       
  3813                 }
       
  3814 
       
  3815                 p->restore();
       
  3816                 return;
       
  3817             }
       
  3818         }
       
  3819                                }
       
  3820         break;
       
  3821 
       
  3822     case CE_ProgressBarLabel:
       
  3823         if (const QStyleOptionProgressBarV2 *pb = qstyleoption_cast<const QStyleOptionProgressBarV2 *>(opt)) {
       
  3824             if (rule.hasBox() || rule.hasBorder() || hasStyleRule(w, PseudoElement_ProgressBarChunk)) {
       
  3825                 drawItemText(p, pb->rect, pb->textAlignment | Qt::TextSingleLine, pb->palette,
       
  3826                              pb->state & State_Enabled, pb->text, QPalette::Text);
       
  3827             } else {
       
  3828                 QStyleOptionProgressBarV2 pbCopy(*pb);
       
  3829                 rule.configurePalette(&pbCopy.palette, QPalette::HighlightedText, QPalette::Highlight);
       
  3830                 baseStyle()->drawControl(ce, &pbCopy, p, w);
       
  3831             }
       
  3832             return;
       
  3833         }
       
  3834         break;
       
  3835 
       
  3836     case CE_SizeGrip:
       
  3837         if (const QStyleOptionSizeGrip *sgOpt = qstyleoption_cast<const QStyleOptionSizeGrip *>(opt)) {
       
  3838             if (rule.hasDrawable()) {
       
  3839                 rule.drawFrame(p, opt->rect);
       
  3840                 p->save();
       
  3841                 switch (sgOpt->corner) {
       
  3842                 case Qt::BottomRightCorner: break;
       
  3843                 case Qt::BottomLeftCorner: p->rotate(90); break;
       
  3844                 case Qt::TopLeftCorner: p->rotate(180); break;
       
  3845                 case Qt::TopRightCorner: p->rotate(270); break;
       
  3846                 default: break;
       
  3847                 }
       
  3848                 rule.drawImage(p, opt->rect);
       
  3849                 p->restore();
       
  3850             } else {
       
  3851                 QStyleOptionSizeGrip sg(*sgOpt);
       
  3852                 sg.rect = rule.contentsRect(opt->rect);
       
  3853                 baseStyle()->drawControl(CE_SizeGrip, &sg, p, w);
       
  3854             }
       
  3855             return;
       
  3856         }
       
  3857         break;
       
  3858 
       
  3859     case CE_ToolBoxTab:
       
  3860         QWindowsStyle::drawControl(ce, opt, p, w);
       
  3861         return;
       
  3862 
       
  3863     case CE_ToolBoxTabShape: {
       
  3864             QRenderRule subRule = renderRule(w, opt, PseudoElement_ToolBoxTab);
       
  3865             if (subRule.hasDrawable()) {
       
  3866                 subRule.drawRule(p, opt->rect);
       
  3867                 return;
       
  3868             }
       
  3869                             }
       
  3870         break;
       
  3871 
       
  3872     case CE_ToolBoxTabLabel:
       
  3873         if (const QStyleOptionToolBox *box = qstyleoption_cast<const QStyleOptionToolBox *>(opt)) {
       
  3874             QStyleOptionToolBox boxCopy(*box);
       
  3875             QRenderRule subRule = renderRule(w, opt, PseudoElement_ToolBoxTab);
       
  3876             subRule.configurePalette(&boxCopy.palette, QPalette::ButtonText, QPalette::Button);
       
  3877             QFont oldFont = p->font();
       
  3878             if (subRule.hasFont)
       
  3879                 p->setFont(subRule.font);
       
  3880             boxCopy.rect = subRule.contentsRect(opt->rect);
       
  3881             QWindowsStyle::drawControl(ce, &boxCopy, p , w);
       
  3882             if (subRule.hasFont)
       
  3883                 p->setFont(oldFont);
       
  3884             return;
       
  3885         }
       
  3886         break;
       
  3887 
       
  3888     case CE_ScrollBarAddPage:
       
  3889         pe1 = PseudoElement_ScrollBarAddPage;
       
  3890         break;
       
  3891 
       
  3892     case CE_ScrollBarSubPage:
       
  3893         pe1 = PseudoElement_ScrollBarSubPage;
       
  3894         break;
       
  3895 
       
  3896     case CE_ScrollBarAddLine:
       
  3897         pe1 = PseudoElement_ScrollBarAddLine;
       
  3898         pe2 = (opt->state & QStyle::State_Horizontal) ? PseudoElement_ScrollBarRightArrow : PseudoElement_ScrollBarDownArrow;
       
  3899         fallback = true;
       
  3900         break;
       
  3901 
       
  3902     case CE_ScrollBarSubLine:
       
  3903         pe1 = PseudoElement_ScrollBarSubLine;
       
  3904         pe2 = (opt->state & QStyle::State_Horizontal) ? PseudoElement_ScrollBarLeftArrow : PseudoElement_ScrollBarUpArrow;
       
  3905         fallback = true;
       
  3906         break;
       
  3907 
       
  3908     case CE_ScrollBarFirst:
       
  3909         pe1 = PseudoElement_ScrollBarFirst;
       
  3910         break;
       
  3911 
       
  3912     case CE_ScrollBarLast:
       
  3913         pe1 = PseudoElement_ScrollBarLast;
       
  3914         break;
       
  3915 
       
  3916     case CE_ScrollBarSlider:
       
  3917         pe1 = PseudoElement_ScrollBarSlider;
       
  3918         fallback = true;
       
  3919         break;
       
  3920 
       
  3921 #ifndef QT_NO_ITEMVIEWS
       
  3922     case CE_ItemViewItem:
       
  3923         if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast<const QStyleOptionViewItemV4 *>(opt)) {
       
  3924             QRenderRule subRule = renderRule(w, opt, PseudoElement_ViewItem);
       
  3925             if (subRule.hasDrawable() || hasStyleRule(w, PseudoElement_Indicator)) {
       
  3926                 QStyleOptionViewItemV4 optCopy(*vopt);
       
  3927                 subRule.configurePalette(&optCopy.palette, vopt->state & QStyle::State_Selected ? QPalette::HighlightedText : QPalette::Text,
       
  3928                                                            vopt->state & QStyle::State_Selected ? QPalette::Highlight : QPalette::Base);
       
  3929                 QWindowsStyle::drawControl(ce, &optCopy, p, w);
       
  3930             } else {
       
  3931                 QStyleOptionViewItemV4 voptCopy(*vopt);
       
  3932                 subRule.configurePalette(&voptCopy.palette, QPalette::Text, QPalette::NoRole);
       
  3933                 baseStyle()->drawControl(ce, &voptCopy, p, w);
       
  3934             }
       
  3935             return;
       
  3936         }
       
  3937         break;
       
  3938 #endif // QT_NO_ITEMVIEWS
       
  3939 
       
  3940 #ifndef QT_NO_TABBAR
       
  3941     case CE_TabBarTab:
       
  3942         if (hasStyleRule(w, PseudoElement_TabBarTab)) {
       
  3943             QWindowsStyle::drawControl(ce, opt, p, w);
       
  3944             return;
       
  3945         }
       
  3946         break;
       
  3947 
       
  3948     case CE_TabBarTabLabel:
       
  3949     case CE_TabBarTabShape:
       
  3950         if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(opt)) {
       
  3951             QStyleOptionTabV3 tabCopy(*tab);
       
  3952             QRenderRule subRule = renderRule(w, opt, PseudoElement_TabBarTab);
       
  3953             QRect r = positionRect(w, subRule, PseudoElement_TabBarTab, opt->rect, opt->direction);
       
  3954             if (ce == CE_TabBarTabShape && subRule.hasDrawable()) {
       
  3955                 subRule.drawRule(p, r);
       
  3956                 return;
       
  3957             }
       
  3958             subRule.configurePalette(&tabCopy.palette, QPalette::WindowText, QPalette::Window);
       
  3959             QFont oldFont = p->font();
       
  3960             if (subRule.hasFont)
       
  3961                 p->setFont(subRule.font);
       
  3962             if (subRule.hasBox() || !subRule.hasNativeBorder()) {
       
  3963                 tabCopy.rect = ce == CE_TabBarTabShape ? subRule.borderRect(r)
       
  3964                                                        : subRule.contentsRect(r);
       
  3965                 QWindowsStyle::drawControl(ce, &tabCopy, p, w);
       
  3966             } else {
       
  3967                 baseStyle()->drawControl(ce, &tabCopy, p, w);
       
  3968             }
       
  3969             if (subRule.hasFont)
       
  3970                 p->setFont(oldFont);
       
  3971 
       
  3972             return;
       
  3973         }
       
  3974        break;
       
  3975 #endif // QT_NO_TABBAR
       
  3976 
       
  3977     case CE_ColumnViewGrip:
       
  3978        if (rule.hasDrawable()) {
       
  3979            rule.drawRule(p, opt->rect);
       
  3980            return;
       
  3981        }
       
  3982        break;
       
  3983 
       
  3984     case CE_DockWidgetTitle:
       
  3985        if (const QStyleOptionDockWidgetV2 *dwOpt = qstyleoption_cast<const QStyleOptionDockWidgetV2 *>(opt)) {
       
  3986            QRenderRule subRule = renderRule(w, opt, PseudoElement_DockWidgetTitle);
       
  3987            if (!subRule.hasDrawable() && !subRule.hasPosition())
       
  3988                break;
       
  3989            if (subRule.hasDrawable()) {
       
  3990                subRule.drawRule(p, opt->rect);
       
  3991            } else {
       
  3992                QStyleOptionDockWidgetV2 dwCopy(*dwOpt);
       
  3993                dwCopy.title = QString();
       
  3994                baseStyle()->drawControl(ce, &dwCopy, p, w);
       
  3995            }
       
  3996 
       
  3997            if (!dwOpt->title.isEmpty()) {
       
  3998                QRect r = opt->rect;
       
  3999                if (dwOpt->verticalTitleBar) {
       
  4000                    QSize s = r.size();
       
  4001                    s.transpose();
       
  4002                    r.setSize(s);
       
  4003 
       
  4004                    p->save();
       
  4005                    p->translate(r.left(), r.top() + r.width());
       
  4006                    p->rotate(-90);
       
  4007                    p->translate(-r.left(), -r.top());
       
  4008                 }
       
  4009 
       
  4010                 Qt::Alignment alignment = 0;
       
  4011                 if (subRule.hasPosition())
       
  4012                     alignment = subRule.position()->textAlignment;
       
  4013                 if (alignment == 0)
       
  4014                     alignment = Qt::AlignLeft;
       
  4015                 drawItemText(p, subRule.contentsRect(opt->rect),
       
  4016                              alignment | Qt::TextShowMnemonic, dwOpt->palette,
       
  4017                              dwOpt->state & State_Enabled, dwOpt->title,
       
  4018                              QPalette::WindowText);
       
  4019 
       
  4020                 if (dwOpt->verticalTitleBar)
       
  4021                     p->restore();
       
  4022             }
       
  4023 
       
  4024            return;
       
  4025         }
       
  4026         break;
       
  4027     case CE_ShapedFrame:
       
  4028         if (const QStyleOptionFrame *frm = qstyleoption_cast<const QStyleOptionFrame *>(opt)) {
       
  4029             if (rule.hasNativeBorder()) {
       
  4030                 QStyleOptionFrameV3 frmOpt(*frm);
       
  4031                 rule.configurePalette(&frmOpt.palette, QPalette::Text, QPalette::Base);
       
  4032                 frmOpt.rect = rule.borderRect(frmOpt.rect);
       
  4033                 baseStyle()->drawControl(ce, &frmOpt, p, w);
       
  4034             }
       
  4035             // else, borders are already drawn in PE_Widget
       
  4036         }
       
  4037         return;
       
  4038 
       
  4039 
       
  4040     default:
       
  4041         break;
       
  4042     }
       
  4043 
       
  4044     if (pe1 != PseudoElement_None) {
       
  4045         QRenderRule subRule = renderRule(w, opt, pe1);
       
  4046         if (subRule.bg != 0 || subRule.hasDrawable()) {
       
  4047             //We test subRule.bg dirrectly because hasBackground() would return false for background:none.
       
  4048             //But we still don't want the default drawning in that case (example for QScrollBar::add-page) (task 198926)
       
  4049             subRule.drawRule(p, opt->rect);
       
  4050         } else if (fallback) {
       
  4051             QWindowsStyle::drawControl(ce, opt, p, w);
       
  4052             pe2 = PseudoElement_None;
       
  4053         } else {
       
  4054             baseStyle()->drawControl(ce, opt, p, w);
       
  4055         }
       
  4056         if (pe2 != PseudoElement_None) {
       
  4057             QRenderRule subSubRule = renderRule(w, opt, pe2);
       
  4058             QRect r = positionRect(w, subRule, subSubRule, pe2, opt->rect, opt->direction);
       
  4059             subSubRule.drawRule(p, r);
       
  4060         }
       
  4061         return;
       
  4062     }
       
  4063 
       
  4064     baseStyle()->drawControl(ce, opt, p, w);
       
  4065 }
       
  4066 
       
  4067 void QStyleSheetStyle::drawItemPixmap(QPainter *p, const QRect &rect, int alignment, const
       
  4068                                   QPixmap &pixmap) const
       
  4069 {
       
  4070     baseStyle()->drawItemPixmap(p, rect, alignment, pixmap);
       
  4071 }
       
  4072 
       
  4073 void QStyleSheetStyle::drawItemText(QPainter *painter, const QRect& rect, int alignment, const QPalette &pal,
       
  4074                                 bool enabled, const QString& text, QPalette::ColorRole textRole) const
       
  4075 {
       
  4076     baseStyle()->drawItemText(painter, rect, alignment, pal, enabled, text, textRole);
       
  4077 }
       
  4078 
       
  4079 void QStyleSheetStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPainter *p,
       
  4080                                      const QWidget *w) const
       
  4081 {
       
  4082     RECURSION_GUARD(baseStyle()->drawPrimitive(pe, opt, p, w); return)
       
  4083 
       
  4084     int pseudoElement = PseudoElement_None;
       
  4085     QRenderRule rule = renderRule(w, opt);
       
  4086     QRect rect = opt->rect;
       
  4087 
       
  4088     switch (pe) {
       
  4089 
       
  4090     case PE_FrameStatusBar: {
       
  4091         QRenderRule subRule = renderRule(w->parentWidget(), opt, PseudoElement_Item);
       
  4092         if (subRule.hasDrawable()) {
       
  4093             subRule.drawRule(p, opt->rect);
       
  4094             return;
       
  4095         }
       
  4096         break;
       
  4097                             }
       
  4098 
       
  4099     case PE_IndicatorArrowDown:
       
  4100         pseudoElement = PseudoElement_DownArrow;
       
  4101         break;
       
  4102 
       
  4103     case PE_IndicatorRadioButton:
       
  4104         pseudoElement = PseudoElement_ExclusiveIndicator;
       
  4105         break;
       
  4106 
       
  4107     case PE_IndicatorViewItemCheck:
       
  4108         pseudoElement = PseudoElement_ViewItemIndicator;
       
  4109         break;
       
  4110 
       
  4111     case PE_IndicatorCheckBox:
       
  4112         pseudoElement = PseudoElement_Indicator;
       
  4113         break;
       
  4114 
       
  4115     case PE_IndicatorHeaderArrow:
       
  4116         if (const QStyleOptionHeader *hdr = qstyleoption_cast<const QStyleOptionHeader *>(opt)) {
       
  4117             pseudoElement = hdr->sortIndicator == QStyleOptionHeader::SortUp
       
  4118                 ? PseudoElement_HeaderViewUpArrow
       
  4119                 : PseudoElement_HeaderViewDownArrow;
       
  4120         }
       
  4121         break;
       
  4122 
       
  4123     case PE_PanelButtonTool:
       
  4124     case PE_PanelButtonCommand:
       
  4125         if (qobject_cast<const QAbstractButton *>(w) && rule.hasBackground() && rule.hasNativeBorder()) {
       
  4126             //the window style will draw the borders
       
  4127             ParentStyle::drawPrimitive(pe, opt, p, w);
       
  4128             if (!rule.background()->pixmap.isNull() || rule.hasImage()) {
       
  4129                 rule.drawRule(p, rule.boxRect(opt->rect, QRenderRule::Margin).adjusted(1,1,-1,-1));
       
  4130             }
       
  4131             return;
       
  4132         }
       
  4133         if (!rule.hasNativeBorder()) {
       
  4134             rule.drawRule(p, rule.boxRect(opt->rect, QRenderRule::Margin));
       
  4135             return;
       
  4136         }
       
  4137         break;
       
  4138 
       
  4139     case PE_IndicatorButtonDropDown: {
       
  4140         QRenderRule subRule = renderRule(w, opt, PseudoElement_ToolButtonMenu);
       
  4141         if (!subRule.hasNativeBorder()) {
       
  4142             rule.drawBorder(p, opt->rect);
       
  4143             return;
       
  4144         }
       
  4145         break;
       
  4146                                      }
       
  4147 
       
  4148     case PE_FrameDefaultButton:
       
  4149         if (rule.hasNativeBorder()) {
       
  4150             if (rule.baseStyleCanDraw())
       
  4151                 break;
       
  4152             QWindowsStyle::drawPrimitive(pe, opt, p, w);
       
  4153         }
       
  4154         return;
       
  4155 
       
  4156     case PE_FrameWindow:
       
  4157     case PE_FrameDockWidget:
       
  4158     case PE_Frame:
       
  4159         if (const QStyleOptionFrame *frm = qstyleoption_cast<const QStyleOptionFrame *>(opt)) {
       
  4160             if (rule.hasNativeBorder()) {
       
  4161                 QStyleOptionFrameV2 frmOpt(*frm);
       
  4162                 rule.configurePalette(&frmOpt.palette, QPalette::Text, QPalette::Base);
       
  4163                 if (!qstyleoption_cast<const QStyleOptionFrameV3 *>(opt)) //if it comes from  CE_ShapedFrame, the margins are already sustracted
       
  4164                     frmOpt.rect = rule.borderRect(frmOpt.rect);
       
  4165                 baseStyle()->drawPrimitive(pe, &frmOpt, p, w);
       
  4166             } else {
       
  4167                 rule.drawBorder(p, rule.borderRect(opt->rect));
       
  4168             }
       
  4169         }
       
  4170         return;
       
  4171 
       
  4172     case PE_PanelLineEdit:
       
  4173         if (const QStyleOptionFrame *frm = qstyleoption_cast<const QStyleOptionFrame *>(opt)) {
       
  4174 #ifndef QT_NO_SPINBOX
       
  4175             if (w && qobject_cast<const QAbstractSpinBox *>(w->parentWidget())) {
       
  4176                 QRenderRule spinboxRule = renderRule(w->parentWidget(), opt);
       
  4177                 if (!spinboxRule.hasNativeBorder() || !spinboxRule.baseStyleCanDraw())
       
  4178                     return;
       
  4179                 rule = spinboxRule;
       
  4180             }
       
  4181 #endif
       
  4182             if (rule.hasNativeBorder()) {
       
  4183                 QStyleOptionFrame frmOpt(*frm);
       
  4184                 rule.configurePalette(&frmOpt.palette, QPalette::Text, QPalette::Base);
       
  4185                 frmOpt.rect = rule.borderRect(frmOpt.rect);
       
  4186                 if (rule.baseStyleCanDraw()) {
       
  4187                     rule.drawBackgroundImage(p, opt->rect);
       
  4188                     baseStyle()->drawPrimitive(pe, &frmOpt, p, w);
       
  4189                 } else {
       
  4190                     rule.drawBackground(p, opt->rect);
       
  4191                     if (frmOpt.lineWidth > 0)
       
  4192                         baseStyle()->drawPrimitive(PE_FrameLineEdit, &frmOpt, p, w);
       
  4193                 }
       
  4194             } else {
       
  4195                 rule.drawRule(p, opt->rect);
       
  4196             }
       
  4197         }
       
  4198         return;
       
  4199 
       
  4200     case PE_Widget:
       
  4201         if (!rule.hasDrawable()) {
       
  4202             QWidget *container = containerWidget(w);
       
  4203             if (autoFillDisabledWidgets->contains(container)
       
  4204                 && (container == w || !renderRule(container, opt).hasBackground())) {
       
  4205                 //we do not have a background, but we disabled the autofillbackground anyway. so fill the background now.
       
  4206                 // (this may happen if we have rules like :focus)
       
  4207                 p->fillRect(opt->rect, opt->palette.brush(w->backgroundRole()));
       
  4208             }
       
  4209             break;
       
  4210         }
       
  4211 #ifndef QT_NO_SCROLLAREA
       
  4212         if (const QAbstractScrollArea *sa = qobject_cast<const QAbstractScrollArea *>(w)) {
       
  4213             const QAbstractScrollAreaPrivate *sap = sa->d_func();
       
  4214             rule.drawBackground(p, opt->rect, sap->contentsOffset());
       
  4215             if (rule.hasBorder())
       
  4216                 rule.drawBorder(p, rule.borderRect(opt->rect));
       
  4217             break;
       
  4218         }
       
  4219 #endif
       
  4220     //fall tghought
       
  4221     case PE_PanelMenu:
       
  4222     case PE_PanelStatusBar:
       
  4223         if(rule.hasDrawable()) {
       
  4224             rule.drawRule(p, opt->rect);
       
  4225             return;
       
  4226         }
       
  4227     break;
       
  4228 
       
  4229     case PE_PanelMenuBar:
       
  4230     if (rule.hasDrawable()) {
       
  4231         // Drawn by PE_Widget
       
  4232         return;
       
  4233     }
       
  4234     break;
       
  4235 
       
  4236     case PE_IndicatorToolBarSeparator:
       
  4237     case PE_IndicatorToolBarHandle: {
       
  4238         PseudoElement ps = pe == PE_IndicatorToolBarHandle ? PseudoElement_ToolBarHandle : PseudoElement_ToolBarSeparator;
       
  4239         QRenderRule subRule = renderRule(w, opt, ps);
       
  4240         if (subRule.hasDrawable()) {
       
  4241             subRule.drawRule(p, opt->rect);
       
  4242             return;
       
  4243         }
       
  4244                                     }
       
  4245         break;
       
  4246 
       
  4247     case PE_IndicatorMenuCheckMark:
       
  4248         pseudoElement = PseudoElement_MenuCheckMark;
       
  4249         break;
       
  4250 
       
  4251     case PE_IndicatorArrowLeft:
       
  4252         pseudoElement = PseudoElement_LeftArrow;
       
  4253         break;
       
  4254 
       
  4255     case PE_IndicatorArrowRight:
       
  4256         pseudoElement = PseudoElement_RightArrow;
       
  4257         break;
       
  4258 
       
  4259     case PE_IndicatorColumnViewArrow:
       
  4260         if (const QStyleOptionViewItem *viewOpt = qstyleoption_cast<const QStyleOptionViewItem *>(opt)) {
       
  4261             bool reverse = (viewOpt->direction == Qt::RightToLeft);
       
  4262             pseudoElement = reverse ? PseudoElement_LeftArrow : PseudoElement_RightArrow;
       
  4263         } else {
       
  4264             pseudoElement = PseudoElement_RightArrow;
       
  4265         }
       
  4266         break;
       
  4267 
       
  4268     case PE_IndicatorBranch:
       
  4269         if (const QStyleOptionViewItemV2 *v2 = qstyleoption_cast<const QStyleOptionViewItemV2 *>(opt)) {
       
  4270             QRenderRule subRule = renderRule(w, opt, PseudoElement_TreeViewBranch);
       
  4271             if (subRule.hasDrawable()) {
       
  4272                 if ((v2->state & QStyle::State_Selected) && v2->showDecorationSelected)
       
  4273                     p->fillRect(v2->rect, v2->palette.highlight());
       
  4274                 else if (v2->features & QStyleOptionViewItemV2::Alternate)
       
  4275                     p->fillRect(v2->rect, v2->palette.alternateBase());
       
  4276                 subRule.drawRule(p, opt->rect);
       
  4277             } else {
       
  4278                 QStyleOptionViewItemV2 v2Copy(*v2);
       
  4279                 if (v2->showDecorationSelected) {
       
  4280                     QRenderRule subRule2 = renderRule(w, opt, PseudoElement_ViewItem);
       
  4281                     if (v2->state & QStyle::State_Selected) {
       
  4282                         subRule2.configurePalette(&v2Copy.palette, QPalette::NoRole, QPalette::Highlight);
       
  4283                     } else if (v2->features & QStyleOptionViewItemV2::Alternate) {
       
  4284                         subRule2.configurePalette(&v2Copy.palette, QPalette::NoRole, QPalette::AlternateBase);
       
  4285                     } else if (subRule2.hasBackground()) {
       
  4286                         p->fillRect(v2->rect, subRule2.background()->brush);
       
  4287                     }
       
  4288                 } else if (v2->features & QStyleOptionViewItemV2::Alternate) {
       
  4289                     quint64 pc = v2->state & QStyle::State_Enabled ? PseudoClass_Enabled : PseudoClass_Disabled;
       
  4290                     pc |= PseudoClass_Alternate;
       
  4291                     QRenderRule subRule2 = renderRule(w, PseudoElement_ViewItem, pc);
       
  4292                     subRule2.configurePalette(&v2Copy.palette, QPalette::NoRole, QPalette::AlternateBase);
       
  4293                 }
       
  4294                 baseStyle()->drawPrimitive(pe, &v2Copy, p, w);
       
  4295             }
       
  4296         }
       
  4297         return;
       
  4298 
       
  4299     case PE_PanelTipLabel:
       
  4300         if (!rule.hasDrawable())
       
  4301             break;
       
  4302 
       
  4303         if (const QStyleOptionFrame *frmOpt = qstyleoption_cast<const QStyleOptionFrame *>(opt)) {
       
  4304             if (rule.hasNativeBorder()) {
       
  4305                 rule.drawBackground(p, opt->rect);
       
  4306                 QStyleOptionFrame optCopy(*frmOpt);
       
  4307                 optCopy.rect = rule.borderRect(opt->rect);
       
  4308                 optCopy.palette.setBrush(QPalette::Window, Qt::NoBrush); // oh dear
       
  4309                 baseStyle()->drawPrimitive(pe, &optCopy, p, w);
       
  4310             } else {
       
  4311                 rule.drawRule(p, opt->rect);
       
  4312             }
       
  4313         }
       
  4314         return;
       
  4315 
       
  4316     case PE_FrameGroupBox:
       
  4317         if (rule.hasNativeBorder())
       
  4318             break;
       
  4319         rule.drawBorder(p, opt->rect);
       
  4320         return;
       
  4321 
       
  4322 #ifndef QT_NO_TABWIDGET
       
  4323     case PE_FrameTabWidget:
       
  4324         if (const QStyleOptionTabWidgetFrame *frm = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(opt)) {
       
  4325             QRenderRule subRule = renderRule(w, opt, PseudoElement_TabWidgetPane);
       
  4326             if (subRule.hasNativeBorder()) {
       
  4327                 subRule.drawBackground(p, opt->rect);
       
  4328                 QStyleOptionTabWidgetFrame frmCopy(*frm);
       
  4329                 subRule.configurePalette(&frmCopy.palette, QPalette::WindowText, QPalette::Window);
       
  4330                 baseStyle()->drawPrimitive(pe, &frmCopy, p, w);
       
  4331             } else {
       
  4332                 subRule.drawRule(p, opt->rect);
       
  4333             }
       
  4334             return;
       
  4335         }
       
  4336         break;
       
  4337 #endif // QT_NO_TABWIDGET
       
  4338 
       
  4339     case PE_IndicatorProgressChunk:
       
  4340         pseudoElement = PseudoElement_ProgressBarChunk;
       
  4341         break;
       
  4342 
       
  4343     case PE_IndicatorTabTear:
       
  4344         pseudoElement = PseudoElement_TabBarTear;
       
  4345         break;
       
  4346 
       
  4347     case PE_FrameFocusRect:
       
  4348         if (!rule.hasNativeOutline()) {
       
  4349             rule.drawOutline(p, opt->rect);
       
  4350             return;
       
  4351         }
       
  4352         break;
       
  4353 
       
  4354     case PE_IndicatorDockWidgetResizeHandle:
       
  4355         pseudoElement = PseudoElement_DockWidgetSeparator;
       
  4356         break;
       
  4357 
       
  4358     case PE_PanelItemViewItem:
       
  4359         if (!styleHint(SH_ItemView_ShowDecorationSelected, opt, w)) {
       
  4360             rect = subElementRect(QStyle::SE_ItemViewItemText,  opt, w)
       
  4361                    | subElementRect(QStyle::SE_ItemViewItemDecoration, opt, w)
       
  4362                    | subElementRect(QStyle::SE_ItemViewItemCheckIndicator, opt, w);
       
  4363         }
       
  4364         pseudoElement = PseudoElement_ViewItem;
       
  4365         break;
       
  4366 
       
  4367     case PE_PanelItemViewRow:
       
  4368         ParentStyle::drawPrimitive(pe, opt, p, w);
       
  4369         if (!styleHint(SH_ItemView_ShowDecorationSelected, opt, w))
       
  4370             return;
       
  4371         pseudoElement = PseudoElement_ViewItem;
       
  4372         break;
       
  4373 
       
  4374     case PE_PanelScrollAreaCorner:
       
  4375         pseudoElement = PseudoElement_ScrollAreaCorner;
       
  4376         break;
       
  4377 
       
  4378     case PE_IndicatorSpinDown:
       
  4379     case PE_IndicatorSpinMinus:
       
  4380         pseudoElement = PseudoElement_SpinBoxDownArrow;
       
  4381         break;
       
  4382 
       
  4383     case PE_IndicatorSpinUp:
       
  4384     case PE_IndicatorSpinPlus:
       
  4385         pseudoElement = PseudoElement_SpinBoxUpArrow;
       
  4386         break;
       
  4387 #ifndef QT_NO_TABBAR
       
  4388     case PE_IndicatorTabClose:
       
  4389         if (w)
       
  4390             w = w->parentWidget(); //match on the QTabBar instead of the CloseButton
       
  4391         pseudoElement = PseudoElement_TabBarTabCloseButton;
       
  4392 #endif
       
  4393 
       
  4394     default:
       
  4395         break;
       
  4396     }
       
  4397 
       
  4398     if (pseudoElement != PseudoElement_None) {
       
  4399         QRenderRule subRule = renderRule(w, opt, pseudoElement);
       
  4400         if (subRule.hasDrawable()) {
       
  4401             subRule.drawRule(p, rect);
       
  4402         } else {
       
  4403             baseStyle()->drawPrimitive(pe, opt, p, w);
       
  4404         }
       
  4405     } else {
       
  4406         baseStyle()->drawPrimitive(pe, opt, p, w);
       
  4407     }
       
  4408 }
       
  4409 
       
  4410 QPixmap QStyleSheetStyle::generatedIconPixmap(QIcon::Mode iconMode, const QPixmap& pixmap,
       
  4411                                           const QStyleOption *option) const
       
  4412 {
       
  4413     return baseStyle()->generatedIconPixmap(iconMode, pixmap, option);
       
  4414 }
       
  4415 
       
  4416 QStyle::SubControl QStyleSheetStyle::hitTestComplexControl(ComplexControl cc, const QStyleOptionComplex *opt,
       
  4417                                  const QPoint &pt, const QWidget *w) const
       
  4418 {
       
  4419     RECURSION_GUARD(return baseStyle()->hitTestComplexControl(cc, opt, pt, w))
       
  4420     switch (cc) {
       
  4421     case CC_TitleBar:
       
  4422         if (const QStyleOptionTitleBar *tb = qstyleoption_cast<const QStyleOptionTitleBar *>(opt)) {
       
  4423             QRenderRule rule = renderRule(w, opt, PseudoElement_TitleBar);
       
  4424             if (rule.hasDrawable() || rule.hasBox() || rule.hasBorder()) {
       
  4425                 QHash<QStyle::SubControl, QRect> layout = titleBarLayout(w, tb);
       
  4426                 QRect r;
       
  4427                 QStyle::SubControl sc = QStyle::SC_None;
       
  4428                 uint ctrl = SC_TitleBarSysMenu;
       
  4429                 while (ctrl <= SC_TitleBarLabel) {
       
  4430                     r = layout[QStyle::SubControl(ctrl)];
       
  4431                     if (r.isValid() && r.contains(pt)) {
       
  4432                         sc = QStyle::SubControl(ctrl);
       
  4433                         break;
       
  4434                     }
       
  4435                     ctrl <<= 1;
       
  4436                 }
       
  4437                 return sc;
       
  4438             }
       
  4439         }
       
  4440         break;
       
  4441 
       
  4442     case CC_MdiControls:
       
  4443         if (hasStyleRule(w, PseudoElement_MdiCloseButton)
       
  4444             || hasStyleRule(w, PseudoElement_MdiNormalButton)
       
  4445             || hasStyleRule(w, PseudoElement_MdiMinButton))
       
  4446             return QWindowsStyle::hitTestComplexControl(cc, opt, pt, w);
       
  4447         break;
       
  4448 
       
  4449     case CC_ScrollBar: {
       
  4450         QRenderRule rule = renderRule(w, opt);
       
  4451         if (!rule.hasDrawable() && !rule.hasBox())
       
  4452             break;
       
  4453                        }
       
  4454         // intentionally falls through
       
  4455     case CC_SpinBox:
       
  4456     case CC_GroupBox:
       
  4457     case CC_ComboBox:
       
  4458     case CC_Slider:
       
  4459     case CC_ToolButton:
       
  4460         return QWindowsStyle::hitTestComplexControl(cc, opt, pt, w);
       
  4461     default:
       
  4462         break;
       
  4463     }
       
  4464 
       
  4465     return baseStyle()->hitTestComplexControl(cc, opt, pt, w);
       
  4466 }
       
  4467 
       
  4468 QRect QStyleSheetStyle::itemPixmapRect(const QRect &rect, int alignment, const QPixmap &pixmap) const
       
  4469 {
       
  4470     return baseStyle()->itemPixmapRect(rect, alignment, pixmap);
       
  4471 }
       
  4472 
       
  4473 QRect QStyleSheetStyle::itemTextRect(const QFontMetrics &metrics, const QRect& rect, int alignment,
       
  4474                                  bool enabled, const QString& text) const
       
  4475 {
       
  4476     return baseStyle()->itemTextRect(metrics, rect, alignment, enabled, text);
       
  4477 }
       
  4478 
       
  4479 int QStyleSheetStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const QWidget *w) const
       
  4480 {
       
  4481     RECURSION_GUARD(return baseStyle()->pixelMetric(m, opt, w))
       
  4482 
       
  4483     QRenderRule rule = renderRule(w, opt);
       
  4484     QRenderRule subRule;
       
  4485 
       
  4486     switch (m) {
       
  4487     case PM_MenuButtonIndicator:
       
  4488 #ifndef QT_NO_TOOLBUTTON
       
  4489         // QToolButton adds this directly to the width
       
  4490         if (qobject_cast<const QToolButton *>(w) && (rule.hasBox() || !rule.hasNativeBorder()))
       
  4491             return 0;
       
  4492 #endif
       
  4493         subRule = renderRule(w, opt, PseudoElement_PushButtonMenuIndicator);
       
  4494         if (subRule.hasContentsSize())
       
  4495             return subRule.size().width();
       
  4496         break;
       
  4497 
       
  4498     case PM_ButtonShiftHorizontal:
       
  4499     case PM_ButtonShiftVertical:
       
  4500     case PM_ButtonMargin:
       
  4501     case PM_ButtonDefaultIndicator:
       
  4502         if (rule.hasBox())
       
  4503             return 0;
       
  4504         break;
       
  4505 
       
  4506     case PM_DefaultFrameWidth:
       
  4507         if (!rule.hasNativeBorder())
       
  4508             return rule.border()->borders[LeftEdge];
       
  4509         break;
       
  4510 
       
  4511     case PM_ExclusiveIndicatorWidth:
       
  4512     case PM_IndicatorWidth:
       
  4513     case PM_ExclusiveIndicatorHeight:
       
  4514     case PM_IndicatorHeight:
       
  4515         subRule = renderRule(w, opt, PseudoElement_Indicator);
       
  4516         if (subRule.hasContentsSize()) {
       
  4517             return (m == PM_ExclusiveIndicatorWidth) || (m == PM_IndicatorWidth)
       
  4518                         ? subRule.size().width() : subRule.size().height();
       
  4519         }
       
  4520         break;
       
  4521 
       
  4522     case PM_DockWidgetFrameWidth:
       
  4523     case PM_ToolTipLabelFrameWidth: // border + margin + padding (support only one width)
       
  4524         if (!rule.hasDrawable())
       
  4525             break;
       
  4526 
       
  4527         return (rule.border() ? rule.border()->borders[LeftEdge] : 0)
       
  4528                 + (rule.hasBox() ? rule.box()->margins[LeftEdge] + rule.box()->paddings[LeftEdge]: 0);
       
  4529 
       
  4530     case PM_ToolBarFrameWidth:
       
  4531         if (rule.hasBorder() || rule.hasBox())
       
  4532             return (rule.border() ? rule.border()->borders[LeftEdge] : 0)
       
  4533                    + (rule.hasBox() ? rule.box()->paddings[LeftEdge]: 0);
       
  4534         break;
       
  4535 
       
  4536     case PM_MenuPanelWidth:
       
  4537     case PM_MenuBarPanelWidth:
       
  4538         if (rule.hasBorder() || rule.hasBox())
       
  4539             return (rule.border() ? rule.border()->borders[LeftEdge] : 0)
       
  4540                    + (rule.hasBox() ? rule.box()->margins[LeftEdge]: 0);
       
  4541         break;
       
  4542 
       
  4543 
       
  4544     case PM_MenuHMargin:
       
  4545     case PM_MenuBarHMargin:
       
  4546         if (rule.hasBox())
       
  4547             return rule.box()->paddings[LeftEdge];
       
  4548         break;
       
  4549 
       
  4550     case PM_MenuVMargin:
       
  4551     case PM_MenuBarVMargin:
       
  4552         if (rule.hasBox())
       
  4553             return rule.box()->paddings[TopEdge];
       
  4554         break;
       
  4555 
       
  4556     case PM_DockWidgetTitleBarButtonMargin:
       
  4557     case PM_ToolBarItemMargin:
       
  4558         if (rule.hasBox())
       
  4559             return rule.box()->margins[TopEdge];
       
  4560         break;
       
  4561 
       
  4562     case PM_ToolBarItemSpacing:
       
  4563     case PM_MenuBarItemSpacing:
       
  4564         if (rule.hasBox() && rule.box()->spacing != -1)
       
  4565             return rule.box()->spacing;
       
  4566         break;
       
  4567 
       
  4568     case PM_MenuTearoffHeight:
       
  4569     case PM_MenuScrollerHeight: {
       
  4570         PseudoElement ps = m == PM_MenuTearoffHeight ? PseudoElement_MenuTearoff : PseudoElement_MenuScroller;
       
  4571         subRule = renderRule(w, opt, ps);
       
  4572         if (subRule.hasContentsSize())
       
  4573             return subRule.size().height();
       
  4574         break;
       
  4575                                 }
       
  4576 
       
  4577     case PM_ToolBarExtensionExtent:
       
  4578         break;
       
  4579 
       
  4580     case PM_SplitterWidth:
       
  4581     case PM_ToolBarSeparatorExtent:
       
  4582     case PM_ToolBarHandleExtent: {
       
  4583         PseudoElement ps;
       
  4584         if (m == PM_ToolBarHandleExtent) ps = PseudoElement_ToolBarHandle;
       
  4585         else if (m == PM_SplitterWidth) ps = PseudoElement_SplitterHandle;
       
  4586         else ps = PseudoElement_ToolBarSeparator;
       
  4587         subRule = renderRule(w, opt, ps);
       
  4588         if (subRule.hasContentsSize()) {
       
  4589             QSize sz = subRule.size();
       
  4590             return (opt && opt->state & QStyle::State_Horizontal) ? sz.width() : sz.height();
       
  4591         }
       
  4592         break;
       
  4593                                  }
       
  4594 
       
  4595     case PM_RadioButtonLabelSpacing:
       
  4596         if (rule.hasBox() && rule.box()->spacing != -1)
       
  4597             return rule.box()->spacing;
       
  4598         break;
       
  4599     case PM_CheckBoxLabelSpacing:
       
  4600         if (qobject_cast<const QCheckBox *>(w)) {
       
  4601             if (rule.hasBox() && rule.box()->spacing != -1)
       
  4602                 return rule.box()->spacing;
       
  4603         }
       
  4604         // assume group box
       
  4605         subRule = renderRule(w, opt, PseudoElement_GroupBoxTitle);
       
  4606         if (subRule.hasBox() && subRule.box()->spacing != -1)
       
  4607             return subRule.box()->spacing;
       
  4608         break;
       
  4609 
       
  4610 #ifndef QT_NO_SCROLLBAR
       
  4611     case PM_ScrollBarExtent:
       
  4612         if (rule.hasContentsSize()) {
       
  4613             QSize sz = rule.size();
       
  4614             if (const QStyleOptionSlider *sb = qstyleoption_cast<const QStyleOptionSlider *>(opt))
       
  4615                 return sb->orientation == Qt::Horizontal ? sz.height() : sz.width();
       
  4616             return sz.width() == -1 ? sz.height() : sz.width();
       
  4617         }
       
  4618         break;
       
  4619 
       
  4620     case PM_ScrollBarSliderMin:
       
  4621         if (hasStyleRule(w, PseudoElement_ScrollBarSlider)) {
       
  4622             subRule = renderRule(w, opt, PseudoElement_ScrollBarSlider);
       
  4623             QSize msz = subRule.minimumSize();
       
  4624             if (const QStyleOptionSlider *sb = qstyleoption_cast<const QStyleOptionSlider *>(opt))
       
  4625                 return sb->orientation == Qt::Horizontal ? msz.width() : msz.height();
       
  4626             return msz.width() == -1 ? msz.height() : msz.width();
       
  4627         }
       
  4628         break;
       
  4629 #endif // QT_NO_SCROLLBAR
       
  4630 
       
  4631     case PM_ProgressBarChunkWidth:
       
  4632         subRule = renderRule(w, opt, PseudoElement_ProgressBarChunk);
       
  4633         if (subRule.hasContentsSize()) {
       
  4634             QSize sz = subRule.size();
       
  4635             return (opt->state & QStyle::State_Horizontal)
       
  4636                    ? sz.width() : sz.height();
       
  4637         }
       
  4638         break;
       
  4639 
       
  4640     case PM_TabBarTabHSpace:
       
  4641     case PM_TabBarTabVSpace:
       
  4642         subRule = renderRule(w, opt, PseudoElement_TabBarTab);
       
  4643         if (subRule.hasBox() || subRule.hasBorder())
       
  4644             return 0;
       
  4645         break;
       
  4646 
       
  4647     case PM_TabBarScrollButtonWidth:   {
       
  4648         subRule = renderRule(w, opt, PseudoElement_TabBarScroller);
       
  4649         if (subRule.hasContentsSize()) {
       
  4650             QSize sz = subRule.size();
       
  4651             return sz.width() != -1 ? sz.width() : sz.height();
       
  4652         }
       
  4653                                         }
       
  4654         break;
       
  4655 
       
  4656     case PM_TabBarTabShiftHorizontal:
       
  4657     case PM_TabBarTabShiftVertical:
       
  4658         subRule = renderRule(w, opt, PseudoElement_TabBarTab);
       
  4659         if (subRule.hasBox())
       
  4660             return 0;
       
  4661         break;
       
  4662 
       
  4663     case PM_TabBarBaseOverlap:
       
  4664         if (hasStyleRule(w->parentWidget(), PseudoElement_TabWidgetPane)) {
       
  4665             return 0;
       
  4666         }
       
  4667         break;
       
  4668 
       
  4669     case PM_SliderThickness: // horizontal slider's height (sizeHint)
       
  4670     case PM_SliderLength: // minimum length of slider
       
  4671         if (rule.hasContentsSize()) {
       
  4672             bool horizontal = opt->state & QStyle::State_Horizontal;
       
  4673             if (m == PM_SliderThickness) {
       
  4674                 QSize sz = rule.size();
       
  4675                 return horizontal ? sz.height() : sz.width();
       
  4676             } else {
       
  4677                 QSize msz = rule.minimumContentsSize();
       
  4678                 return horizontal ? msz.width() : msz.height();
       
  4679             }
       
  4680         }
       
  4681         break;
       
  4682 
       
  4683     case PM_SliderControlThickness: {
       
  4684         QRenderRule subRule = renderRule(w, opt, PseudoElement_SliderHandle);
       
  4685         if (!subRule.hasContentsSize())
       
  4686             break;
       
  4687         QSize size = subRule.size();
       
  4688         return (opt->state & QStyle::State_Horizontal) ? size.height() : size.width();
       
  4689                                     }
       
  4690 
       
  4691     case PM_ToolBarIconSize:
       
  4692     case PM_ListViewIconSize:
       
  4693     case PM_IconViewIconSize:
       
  4694     case PM_TabBarIconSize:
       
  4695     case PM_MessageBoxIconSize:
       
  4696     case PM_ButtonIconSize:
       
  4697     case PM_SmallIconSize:
       
  4698         if (rule.hasStyleHint(QLatin1String("icon-size"))) {
       
  4699             return rule.styleHint(QLatin1String("icon-size")).toSize().width();
       
  4700         }
       
  4701         break;
       
  4702 
       
  4703     case PM_DockWidgetTitleMargin: {
       
  4704         QRenderRule subRule = renderRule(w, opt, PseudoElement_DockWidgetTitle);
       
  4705         if (!subRule.hasBox())
       
  4706             break;
       
  4707         return (subRule.border() ? subRule.border()->borders[TopEdge] : 0)
       
  4708                 + (subRule.hasBox() ? subRule.box()->margins[TopEdge] + subRule.box()->paddings[TopEdge]: 0);
       
  4709                                    }
       
  4710 
       
  4711     case PM_DockWidgetSeparatorExtent: {
       
  4712         QRenderRule subRule = renderRule(w, opt, PseudoElement_DockWidgetSeparator);
       
  4713         if (!subRule.hasContentsSize())
       
  4714             break;
       
  4715         QSize sz = subRule.size();
       
  4716         return qMax(sz.width(), sz.height());
       
  4717                                         }
       
  4718 
       
  4719     case PM_TitleBarHeight: {
       
  4720         QRenderRule subRule = renderRule(w, opt, PseudoElement_TitleBar);
       
  4721         if (subRule.hasContentsSize())
       
  4722             return subRule.size().height();
       
  4723         else if (subRule.hasBox() || subRule.hasBorder()) {
       
  4724             QFontMetrics fm = opt ?  opt->fontMetrics : w->fontMetrics();
       
  4725             return subRule.size(QSize(0, fm.lineSpacing())).height();
       
  4726         }
       
  4727         break;
       
  4728                             }
       
  4729 
       
  4730     case PM_MdiSubWindowFrameWidth:
       
  4731         if (rule.hasBox() || rule.hasBorder()) {
       
  4732             return (rule.border() ? rule.border()->borders[LeftEdge] : 0)
       
  4733                    + (rule.hasBox() ? rule.box()->paddings[LeftEdge]+rule.box()->margins[LeftEdge]: 0);
       
  4734         }
       
  4735         break;
       
  4736 
       
  4737     case PM_MdiSubWindowMinimizedWidth: {
       
  4738         QRenderRule subRule = renderRule(w, PseudoElement_None, PseudoClass_Minimized);
       
  4739         int width = subRule.size().width();
       
  4740         if (width != -1)
       
  4741             return width;
       
  4742         break;
       
  4743                                      }
       
  4744     default:
       
  4745         break;
       
  4746     }
       
  4747 
       
  4748     return baseStyle()->pixelMetric(m, opt, w);
       
  4749 }
       
  4750 
       
  4751 QSize QStyleSheetStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
       
  4752                                          const QSize &csz, const QWidget *w) const
       
  4753 {
       
  4754     RECURSION_GUARD(return baseStyle()->sizeFromContents(ct, opt, csz, w))
       
  4755 
       
  4756     QRenderRule rule = renderRule(w, opt);
       
  4757     QSize sz = rule.adjustSize(csz);
       
  4758 
       
  4759     switch (ct) {
       
  4760     case CT_SpinBox: // ### hopelessly broken QAbstractSpinBox (part 1)
       
  4761         if (rule.hasBox() || !rule.hasNativeBorder())
       
  4762             return csz;
       
  4763         return rule.baseStyleCanDraw() ? baseStyle()->sizeFromContents(ct, opt, sz, w)
       
  4764                                        : QWindowsStyle::sizeFromContents(ct, opt, sz, w);
       
  4765     case CT_ToolButton:
       
  4766         if (rule.hasBox() || !rule.hasNativeBorder() || !rule.baseStyleCanDraw())
       
  4767             sz += QSize(3, 3); // ### broken QToolButton
       
  4768         //fall thought
       
  4769     case CT_ComboBox:
       
  4770     case CT_PushButton:
       
  4771         if (rule.hasBox() || !rule.hasNativeBorder()) {
       
  4772             if(ct == CT_ComboBox) {
       
  4773                 //add some space for the drop down.
       
  4774                 QRenderRule subRule = renderRule(w, opt, PseudoElement_ComboBoxDropDown);
       
  4775                 QRect comboRect = positionRect(w, rule, subRule, PseudoElement_ComboBoxDropDown, opt->rect, opt->direction);
       
  4776                 //+2 because there is hardcoded margins in QCommonStyle::drawControl(CE_ComboBoxLabel)
       
  4777                 sz += QSize(comboRect.width() + 2, 0);
       
  4778             }
       
  4779             return rule.boxSize(sz);
       
  4780         }
       
  4781         sz = rule.baseStyleCanDraw() ? baseStyle()->sizeFromContents(ct, opt, sz, w)
       
  4782                                      : QWindowsStyle::sizeFromContents(ct, opt, sz, w);
       
  4783         return rule.boxSize(sz, Margin);
       
  4784 
       
  4785     case CT_HeaderSection: {
       
  4786             if (const QStyleOptionHeader *hdr = qstyleoption_cast<const QStyleOptionHeader *>(opt)) {
       
  4787                 QRenderRule subRule = renderRule(w, opt, PseudoElement_HeaderViewSection);
       
  4788                 if (subRule.hasGeometry() || subRule.hasBox() || !subRule.hasNativeBorder()) {
       
  4789                     sz = subRule.adjustSize(csz);
       
  4790                     if (!subRule.hasGeometry()) {
       
  4791                         QSize nativeContentsSize;
       
  4792                         bool nullIcon = hdr->icon.isNull();
       
  4793                         int iconSize = nullIcon ? 0 : pixelMetric(QStyle::PM_SmallIconSize, hdr, w);
       
  4794                         QSize txt = hdr->fontMetrics.size(0, hdr->text);
       
  4795                         nativeContentsSize.setHeight(qMax(iconSize, txt.height()));
       
  4796                         nativeContentsSize.setWidth(iconSize + txt.width());
       
  4797                         sz = sz.expandedTo(nativeContentsSize);
       
  4798                     }
       
  4799                     return subRule.size(sz);
       
  4800                 }
       
  4801                 return subRule.baseStyleCanDraw() ? baseStyle()->sizeFromContents(ct, opt, sz, w)
       
  4802                                                   : QWindowsStyle::sizeFromContents(ct, opt, sz, w);
       
  4803             }
       
  4804         }
       
  4805         break;
       
  4806     case CT_GroupBox:
       
  4807     case CT_LineEdit:
       
  4808 #ifndef QT_NO_SPINBOX
       
  4809         // ### hopelessly broken QAbstractSpinBox (part 2)
       
  4810         if (QAbstractSpinBox *spinBox = qobject_cast<QAbstractSpinBox *>(w ? w->parentWidget() : 0)) {
       
  4811             QRenderRule rule = renderRule(spinBox, opt);
       
  4812             if (rule.hasBox() || !rule.hasNativeBorder())
       
  4813                 return csz;
       
  4814             return rule.baseStyleCanDraw() ? baseStyle()->sizeFromContents(ct, opt, sz, w)
       
  4815                                            : QWindowsStyle::sizeFromContents(ct, opt, sz, w);
       
  4816         }
       
  4817 #endif
       
  4818         if (rule.hasBox() || !rule.hasNativeBorder()) {
       
  4819             return rule.boxSize(sz);
       
  4820         }
       
  4821         break;
       
  4822 
       
  4823     case CT_CheckBox:
       
  4824     case CT_RadioButton:
       
  4825         if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
       
  4826             if (rule.hasBox() || rule.hasBorder() || hasStyleRule(w, PseudoElement_Indicator)) {
       
  4827                 bool isRadio = (ct == CT_RadioButton);
       
  4828                 int iw = pixelMetric(isRadio ? PM_ExclusiveIndicatorWidth
       
  4829                                              : PM_IndicatorWidth, btn, w);
       
  4830                 int ih = pixelMetric(isRadio ? PM_ExclusiveIndicatorHeight
       
  4831                                              : PM_IndicatorHeight, btn, w);
       
  4832 
       
  4833                 int spacing = pixelMetric(isRadio ? PM_RadioButtonLabelSpacing
       
  4834                                                   : PM_CheckBoxLabelSpacing, btn, w);
       
  4835                 sz.setWidth(sz.width() + iw + spacing);
       
  4836                 sz.setHeight(qMax(sz.height(), ih));
       
  4837                 return rule.boxSize(sz);
       
  4838             }
       
  4839         }
       
  4840         break;
       
  4841 
       
  4842     case CT_Menu:
       
  4843     case CT_MenuBar: // already has everything!
       
  4844     case CT_ScrollBar:
       
  4845         if (rule.hasBox() || rule.hasBorder())
       
  4846             return sz;
       
  4847         break;
       
  4848 
       
  4849     case CT_MenuItem:
       
  4850         if (const QStyleOptionMenuItem *mi = qstyleoption_cast<const QStyleOptionMenuItem *>(opt)) {
       
  4851             PseudoElement pe = (mi->menuItemType == QStyleOptionMenuItem::Separator)
       
  4852                                     ? PseudoElement_MenuSeparator : PseudoElement_Item;
       
  4853             QRenderRule subRule = renderRule(w, opt, pe);
       
  4854             if ((pe == PseudoElement_MenuSeparator) && subRule.hasContentsSize()) {
       
  4855                 return QSize(sz.width(), subRule.size().height());
       
  4856             } else if ((pe == PseudoElement_Item) && (subRule.hasBox() || subRule.hasBorder())) {
       
  4857                 int width = csz.width();
       
  4858                 if (mi->text.contains(QLatin1Char('\t')))
       
  4859                     width += 12; //as in QCommonStyle
       
  4860                 return subRule.boxSize(subRule.adjustSize(QSize(width, csz.height())));
       
  4861             }
       
  4862         }
       
  4863         break;
       
  4864 
       
  4865     case CT_Splitter:
       
  4866     case CT_MenuBarItem: {
       
  4867         PseudoElement pe = (ct == CT_Splitter) ? PseudoElement_SplitterHandle : PseudoElement_Item;
       
  4868         QRenderRule subRule = renderRule(w, opt, pe);
       
  4869         if (subRule.hasBox() || subRule.hasBorder())
       
  4870             return subRule.boxSize(sz);
       
  4871         break;
       
  4872                         }
       
  4873 
       
  4874     case CT_ProgressBar:
       
  4875     case CT_SizeGrip:
       
  4876         return (rule.hasContentsSize())
       
  4877             ? rule.size(sz)
       
  4878             : rule.boxSize(baseStyle()->sizeFromContents(ct, opt, sz, w));
       
  4879         break;
       
  4880 
       
  4881     case CT_Slider:
       
  4882         if (rule.hasBorder() || rule.hasBox() || rule.hasGeometry())
       
  4883             return rule.boxSize(sz);
       
  4884         break;
       
  4885 
       
  4886 #ifndef QT_NO_TABBAR
       
  4887     case CT_TabBarTab: {
       
  4888         QRenderRule subRule = renderRule(w, opt, PseudoElement_TabBarTab);
       
  4889         if (subRule.hasBox() || !subRule.hasNativeBorder()) {
       
  4890             int spaceForIcon = 0;
       
  4891             bool vertical = false;
       
  4892             if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(opt)) {
       
  4893                 if (!tab->icon.isNull())
       
  4894                     spaceForIcon = 6 /* icon offset */ + 4 /* spacing */ + 2 /* magic */; // ###: hardcoded to match with common style
       
  4895                 vertical = verticalTabs(tab->shape);
       
  4896             }
       
  4897             sz = csz + QSize(vertical ? 0 : spaceForIcon, vertical ? spaceForIcon : 0);
       
  4898             return subRule.boxSize(subRule.adjustSize(sz));
       
  4899         }
       
  4900 #ifdef Q_WS_MAC
       
  4901         if (baseStyle()->inherits("QMacStyle")) {
       
  4902             //adjust the size after the call to the style because the mac style ignore the size arguments anyway.
       
  4903             //this might cause the (max-){width,height} property to include the native style border while they should not.
       
  4904             return subRule.adjustSize(baseStyle()->sizeFromContents(ct, opt, csz, w));
       
  4905         }
       
  4906 #endif
       
  4907         sz = subRule.adjustSize(csz);
       
  4908         break;
       
  4909     }
       
  4910 #endif // QT_NO_TABBAR
       
  4911 
       
  4912     case CT_MdiControls:
       
  4913         if (const QStyleOptionComplex *ccOpt = qstyleoption_cast<const QStyleOptionComplex *>(opt)) {
       
  4914             if (!hasStyleRule(w, PseudoElement_MdiCloseButton)
       
  4915                 && !hasStyleRule(w, PseudoElement_MdiNormalButton)
       
  4916                 && !hasStyleRule(w, PseudoElement_MdiMinButton))
       
  4917                 break;
       
  4918 
       
  4919             QList<QVariant> layout = rule.styleHint(QLatin1String("button-layout")).toList();
       
  4920             if (layout.isEmpty())
       
  4921                 layout = subControlLayout(QLatin1String("mNX"));
       
  4922 
       
  4923             int width = 0, height = 0;
       
  4924             for (int i = 0; i < layout.count(); i++) {
       
  4925                 int layoutButton = layout[i].toInt();
       
  4926                 if (layoutButton < PseudoElement_MdiCloseButton
       
  4927                     || layoutButton > PseudoElement_MdiNormalButton)
       
  4928                     continue;
       
  4929                 QStyle::SubControl sc = knownPseudoElements[layoutButton].subControl;
       
  4930                 if (!(ccOpt->subControls & sc))
       
  4931                     continue;
       
  4932                 QRenderRule subRule = renderRule(w, opt, layoutButton);
       
  4933                 QSize sz = subRule.size();
       
  4934                 width += sz.width();
       
  4935                 height = qMax(height, sz.height());
       
  4936             }
       
  4937 
       
  4938             return QSize(width, height);
       
  4939         }
       
  4940         break;
       
  4941 
       
  4942 #ifndef QT_NO_ITEMVIEWS
       
  4943     case CT_ItemViewItem: {
       
  4944         QRenderRule subRule = renderRule(w, opt, PseudoElement_ViewItem);
       
  4945         sz = baseStyle()->sizeFromContents(ct, opt, csz, w);
       
  4946         sz = subRule.adjustSize(sz);
       
  4947         if (subRule.hasBox() || subRule.hasBorder())
       
  4948             sz = subRule.boxSize(sz);
       
  4949         return sz;
       
  4950                       }
       
  4951 #endif // QT_NO_ITEMVIEWS
       
  4952 
       
  4953     default:
       
  4954         break;
       
  4955     }
       
  4956 
       
  4957     return baseStyle()->sizeFromContents(ct, opt, sz, w);
       
  4958 }
       
  4959 
       
  4960 /*!
       
  4961     \internal
       
  4962 */
       
  4963 static QLatin1String propertyNameForStandardPixmap(QStyle::StandardPixmap sp)
       
  4964 {
       
  4965     switch (sp) {
       
  4966         case QStyle::SP_TitleBarMenuButton: return QLatin1String("titlebar-menu-icon");
       
  4967         case QStyle::SP_TitleBarMinButton: return QLatin1String("titlebar-minimize-icon");
       
  4968         case QStyle::SP_TitleBarMaxButton: return QLatin1String("titlebar-maximize-icon");
       
  4969         case QStyle::SP_TitleBarCloseButton: return QLatin1String("titlebar-close-icon");
       
  4970         case QStyle::SP_TitleBarNormalButton: return QLatin1String("titlebar-normal-icon");
       
  4971         case QStyle::SP_TitleBarShadeButton: return QLatin1String("titlebar-shade-icon");
       
  4972         case QStyle::SP_TitleBarUnshadeButton: return QLatin1String("titlebar-unshade-icon");
       
  4973         case QStyle::SP_TitleBarContextHelpButton: return QLatin1String("titlebar-contexthelp-icon");
       
  4974         case QStyle::SP_DockWidgetCloseButton: return QLatin1String("dockwidget-close-icon");
       
  4975         case QStyle::SP_MessageBoxInformation: return QLatin1String("messagebox-information-icon");
       
  4976         case QStyle::SP_MessageBoxWarning: return QLatin1String("messagebox-warning-icon");
       
  4977         case QStyle::SP_MessageBoxCritical: return QLatin1String("messagebox-critical-icon");
       
  4978         case QStyle::SP_MessageBoxQuestion: return QLatin1String("messagebox-question-icon");
       
  4979         case QStyle::SP_DesktopIcon: return QLatin1String("desktop-icon");
       
  4980         case QStyle::SP_TrashIcon: return QLatin1String("trash-icon");
       
  4981         case QStyle::SP_ComputerIcon: return QLatin1String("computer-icon");
       
  4982         case QStyle::SP_DriveFDIcon: return QLatin1String("floppy-icon");
       
  4983         case QStyle::SP_DriveHDIcon: return QLatin1String("harddisk-icon");
       
  4984         case QStyle::SP_DriveCDIcon: return QLatin1String("cd-icon");
       
  4985         case QStyle::SP_DriveDVDIcon: return QLatin1String("dvd-icon");
       
  4986         case QStyle::SP_DriveNetIcon: return QLatin1String("network-icon");
       
  4987         case QStyle::SP_DirOpenIcon: return QLatin1String("directory-open-icon");
       
  4988         case QStyle::SP_DirClosedIcon: return QLatin1String("directory-closed-icon");
       
  4989         case QStyle::SP_DirLinkIcon: return QLatin1String("directory-link-icon");
       
  4990         case QStyle::SP_FileIcon: return QLatin1String("file-icon");
       
  4991         case QStyle::SP_FileLinkIcon: return QLatin1String("file-link-icon");
       
  4992         case QStyle::SP_FileDialogStart: return QLatin1String("filedialog-start-icon");
       
  4993         case QStyle::SP_FileDialogEnd: return QLatin1String("filedialog-end-icon");
       
  4994         case QStyle::SP_FileDialogToParent: return QLatin1String("filedialog-parent-directory-icon");
       
  4995         case QStyle::SP_FileDialogNewFolder: return QLatin1String("filedialog-new-directory-icon");
       
  4996         case QStyle::SP_FileDialogDetailedView: return QLatin1String("filedialog-detailedview-icon");
       
  4997         case QStyle::SP_FileDialogInfoView: return QLatin1String("filedialog-infoview-icon");
       
  4998         case QStyle::SP_FileDialogContentsView: return QLatin1String("filedialog-contentsview-icon");
       
  4999         case QStyle::SP_FileDialogListView: return QLatin1String("filedialog-listview-icon");
       
  5000         case QStyle::SP_FileDialogBack: return QLatin1String("filedialog-backward-icon");
       
  5001         case QStyle::SP_DirIcon: return QLatin1String("directory-icon");
       
  5002         case QStyle::SP_DialogOkButton: return QLatin1String("dialog-ok-icon");
       
  5003         case QStyle::SP_DialogCancelButton: return QLatin1String("dialog-cancel-icon");
       
  5004         case QStyle::SP_DialogHelpButton: return QLatin1String("dialog-help-icon");
       
  5005         case QStyle::SP_DialogOpenButton: return QLatin1String("dialog-open-icon");
       
  5006         case QStyle::SP_DialogSaveButton: return QLatin1String("dialog-save-icon");
       
  5007         case QStyle::SP_DialogCloseButton: return QLatin1String("dialog-close-icon");
       
  5008         case QStyle::SP_DialogApplyButton: return QLatin1String("dialog-apply-icon");
       
  5009         case QStyle::SP_DialogResetButton: return QLatin1String("dialog-reset-icon");
       
  5010         case QStyle::SP_DialogDiscardButton: return QLatin1String("discard-icon");
       
  5011         case QStyle::SP_DialogYesButton: return QLatin1String("dialog-yes-icon");
       
  5012         case QStyle::SP_DialogNoButton: return QLatin1String("dialog-no-icon");
       
  5013         case QStyle::SP_ArrowUp: return QLatin1String("uparrow-icon");
       
  5014         case QStyle::SP_ArrowDown: return QLatin1String("downarrow-icon");
       
  5015         case QStyle::SP_ArrowLeft: return QLatin1String("leftarrow-icon");
       
  5016         case QStyle::SP_ArrowRight: return QLatin1String("rightarrow-icon");
       
  5017         case QStyle::SP_ArrowBack: return QLatin1String("backward-icon");
       
  5018         case QStyle::SP_ArrowForward: return QLatin1String("forward-icon");
       
  5019         case QStyle::SP_DirHomeIcon: return QLatin1String("home-icon");
       
  5020         default: return QLatin1String("");
       
  5021     }
       
  5022 }
       
  5023 
       
  5024 QIcon QStyleSheetStyle::standardIconImplementation(StandardPixmap standardIcon, const QStyleOption *opt,
       
  5025                                                    const QWidget *w) const
       
  5026 {
       
  5027     RECURSION_GUARD(return baseStyle()->standardIcon(standardIcon, opt, w))
       
  5028     QString s = propertyNameForStandardPixmap(standardIcon);
       
  5029     if (!s.isEmpty()) {
       
  5030         QRenderRule rule = renderRule(w, opt);
       
  5031         if (rule.hasStyleHint(s))
       
  5032             return qVariantValue<QIcon>(rule.styleHint(s));
       
  5033     }
       
  5034     return baseStyle()->standardIcon(standardIcon, opt, w);
       
  5035 }
       
  5036 
       
  5037 QPalette QStyleSheetStyle::standardPalette() const
       
  5038 {
       
  5039     return baseStyle()->standardPalette();
       
  5040 }
       
  5041 
       
  5042 QPixmap QStyleSheetStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt,
       
  5043                                          const QWidget *w) const
       
  5044 {
       
  5045     RECURSION_GUARD(return baseStyle()->standardPixmap(standardPixmap, opt, w))
       
  5046     QString s = propertyNameForStandardPixmap(standardPixmap);
       
  5047     if (!s.isEmpty()) {
       
  5048         QRenderRule rule = renderRule(w, opt);
       
  5049         if (rule.hasStyleHint(s)) {
       
  5050             QIcon icon = qVariantValue<QIcon>(rule.styleHint(s));
       
  5051             return icon.pixmap(16, 16); // ###: unhard-code this if someone complains
       
  5052         }
       
  5053     }
       
  5054     return baseStyle()->standardPixmap(standardPixmap, opt, w);
       
  5055 }
       
  5056 
       
  5057 int QStyleSheetStyle::layoutSpacing(QSizePolicy::ControlType control1, QSizePolicy::ControlType control2,
       
  5058                           Qt::Orientation orientation, const QStyleOption *option,
       
  5059                           const QWidget *widget) const
       
  5060 {
       
  5061     return baseStyle()->layoutSpacing(control1, control2, orientation, option, widget);
       
  5062 }
       
  5063 
       
  5064 int QStyleSheetStyle::layoutSpacingImplementation(QSizePolicy::ControlType  control1 ,
       
  5065                                         QSizePolicy::ControlType  control2,
       
  5066                                         Qt::Orientation orientation,
       
  5067                                         const QStyleOption *  option ,
       
  5068                                         const QWidget *  widget) const
       
  5069 {
       
  5070     return baseStyle()->layoutSpacing(control1, control2, orientation, option, widget);
       
  5071 }
       
  5072 
       
  5073 int QStyleSheetStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget *w,
       
  5074                            QStyleHintReturn *shret) const
       
  5075 {
       
  5076     RECURSION_GUARD(return baseStyle()->styleHint(sh, opt, w, shret))
       
  5077     // Prevent endless loop if somebody use isActiveWindow property as selector.
       
  5078     // QWidget::isActiveWindow uses this styleHint to determine if the window is active or not
       
  5079     if (sh == SH_Widget_ShareActivation)
       
  5080         return baseStyle()->styleHint(sh, opt, w, shret);
       
  5081 
       
  5082     QRenderRule rule = renderRule(w, opt);
       
  5083     QString s;
       
  5084     switch (sh) {
       
  5085         case SH_LineEdit_PasswordCharacter: s = QLatin1String("lineedit-password-character"); break;
       
  5086         case SH_DitherDisabledText: s = QLatin1String("dither-disabled-text"); break;
       
  5087         case SH_EtchDisabledText: s = QLatin1String("etch-disabled-text"); break;
       
  5088         case SH_ItemView_ActivateItemOnSingleClick: s = QLatin1String("activate-on-singleclick"); break;
       
  5089         case SH_ItemView_ShowDecorationSelected: s = QLatin1String("show-decoration-selected"); break;
       
  5090         case SH_Table_GridLineColor: s = QLatin1String("gridline-color"); break;
       
  5091         case SH_DialogButtonLayout: s = QLatin1String("button-layout"); break;
       
  5092         case SH_ToolTipLabel_Opacity: s = QLatin1String("opacity"); break;
       
  5093         case SH_ComboBox_Popup: s = QLatin1String("combobox-popup"); break;
       
  5094         case SH_ComboBox_ListMouseTracking: s = QLatin1String("combobox-list-mousetracking"); break;
       
  5095         case SH_MenuBar_AltKeyNavigation: s = QLatin1String("menubar-altkey-navigation"); break;
       
  5096         case SH_Menu_Scrollable: s = QLatin1String("menu-scrollable"); break;
       
  5097         case SH_DrawMenuBarSeparator: s = QLatin1String("menubar-separator"); break;
       
  5098         case SH_MenuBar_MouseTracking: s = QLatin1String("mouse-tracking"); break;
       
  5099         case SH_SpinBox_ClickAutoRepeatRate: s = QLatin1String("spinbox-click-autorepeat-rate"); break;
       
  5100         case SH_SpinControls_DisableOnBounds: s = QLatin1String("spincontrol-disable-on-bounds"); break;
       
  5101         case SH_MessageBox_TextInteractionFlags: s = QLatin1String("messagebox-text-interaction-flags"); break;
       
  5102         case SH_ToolButton_PopupDelay: s = QLatin1String("toolbutton-popup-delay"); break;
       
  5103         case SH_ToolBox_SelectedPageTitleBold:
       
  5104             if (renderRule(w, opt, PseudoElement_ToolBoxTab).hasFont)
       
  5105                 return 0;
       
  5106             break;
       
  5107         case SH_GroupBox_TextLabelColor:
       
  5108             if (rule.hasPalette() && rule.palette()->foreground.style() != Qt::NoBrush)
       
  5109                 return rule.palette()->foreground.color().rgba();
       
  5110             break;
       
  5111         case SH_ScrollView_FrameOnlyAroundContents: s = QLatin1String("scrollview-frame-around-contents"); break;
       
  5112         case SH_ScrollBar_ContextMenu: s = QLatin1String("scrollbar-contextmenu"); break;
       
  5113         case SH_ScrollBar_LeftClickAbsolutePosition: s = QLatin1String("scrollbar-leftclick-absolute-position"); break;
       
  5114         case SH_ScrollBar_MiddleClickAbsolutePosition: s = QLatin1String("scrollbar-middleclick-absolute-position"); break;
       
  5115         case SH_ScrollBar_RollBetweenButtons: s = QLatin1String("scrollbar-roll-between-buttons"); break;
       
  5116         case SH_ScrollBar_ScrollWhenPointerLeavesControl: s = QLatin1String("scrollbar-scroll-when-pointer-leaves-control"); break;
       
  5117         case SH_TabBar_Alignment:
       
  5118 #ifndef QT_NO_TABWIDGET
       
  5119             if (qobject_cast<const QTabWidget *>(w)) {
       
  5120                 rule = renderRule(w, opt, PseudoElement_TabWidgetTabBar);
       
  5121                 if (rule.hasPosition())
       
  5122                     return rule.position()->position;
       
  5123             }
       
  5124 #endif // QT_NO_TABWIDGET
       
  5125             s = QLatin1String("alignment");
       
  5126             break;
       
  5127 #ifndef QT_NO_TABBAR
       
  5128         case SH_TabBar_CloseButtonPosition:
       
  5129             rule = renderRule(w, opt, PseudoElement_TabBarTabCloseButton);
       
  5130             if (rule.hasPosition()) {
       
  5131                 Qt::Alignment align = rule.position()->position;
       
  5132                 if (align & Qt::AlignLeft || align & Qt::AlignTop)
       
  5133                     return QTabBar::LeftSide;
       
  5134                 if (align & Qt::AlignRight || align & Qt::AlignBottom)
       
  5135                     return QTabBar::RightSide;
       
  5136             }
       
  5137             break;
       
  5138 #endif
       
  5139         case SH_TabBar_ElideMode: s = QLatin1String("tabbar-elide-mode"); break;
       
  5140         case SH_TabBar_PreferNoArrows: s = QLatin1String("tabbar-prefer-no-arrows"); break;
       
  5141         case SH_ComboBox_PopupFrameStyle:
       
  5142 #ifndef QT_NO_COMBOBOX
       
  5143             if (qobject_cast<const QComboBox *>(w)) {
       
  5144                 QAbstractItemView *view = qFindChild<QAbstractItemView *>(w);
       
  5145                 if (view) {
       
  5146                     view->ensurePolished();
       
  5147                     QRenderRule subRule = renderRule(view, PseudoElement_None);
       
  5148                     if (subRule.hasBox() || !subRule.hasNativeBorder())
       
  5149                         return QFrame::NoFrame;
       
  5150                 }
       
  5151             }
       
  5152 #endif // QT_NO_COMBOBOX
       
  5153             break;
       
  5154         case SH_DialogButtonBox_ButtonsHaveIcons: s = QLatin1String("dialogbuttonbox-buttons-have-icons"); break;
       
  5155         case SH_Workspace_FillSpaceOnMaximize: s = QLatin1String("mdi-fill-space-on-maximize"); break;
       
  5156         case SH_TitleBar_NoBorder:
       
  5157             if (rule.hasBorder())
       
  5158                 return !rule.border()->borders[LeftEdge];
       
  5159             break;
       
  5160         case SH_TitleBar_AutoRaise: { // plain absurd
       
  5161             QRenderRule subRule = renderRule(w, opt, PseudoElement_TitleBar);
       
  5162             if (subRule.hasDrawable())
       
  5163                 return 1;
       
  5164             break;
       
  5165                                    }
       
  5166         case SH_ItemView_ArrowKeysNavigateIntoChildren: s = QLatin1String("arrow-keys-navigate-into-children"); break;
       
  5167         case SH_ItemView_PaintAlternatingRowColorsForEmptyArea: s = QLatin1String("paint-alternating-row-colors-for-empty-area"); break;
       
  5168         default: break;
       
  5169     }
       
  5170     if (!s.isEmpty() && rule.hasStyleHint(s)) {
       
  5171         return rule.styleHint(s).toInt();
       
  5172     }
       
  5173 
       
  5174     return baseStyle()->styleHint(sh, opt, w, shret);
       
  5175 }
       
  5176 
       
  5177 QRect QStyleSheetStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *opt, SubControl sc,
       
  5178                               const QWidget *w) const
       
  5179 {
       
  5180     RECURSION_GUARD(return baseStyle()->subControlRect(cc, opt, sc, w))
       
  5181 
       
  5182     QRenderRule rule = renderRule(w, opt);
       
  5183     switch (cc) {
       
  5184     case CC_ComboBox:
       
  5185         if (const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(opt)) {
       
  5186             if (rule.hasBox() || !rule.hasNativeBorder()) {
       
  5187                 switch (sc) {
       
  5188                 case SC_ComboBoxFrame: return rule.borderRect(opt->rect);
       
  5189                 case SC_ComboBoxEditField:
       
  5190                     {
       
  5191                         QRenderRule subRule = renderRule(w, opt, PseudoElement_ComboBoxDropDown);
       
  5192                         QRect r = rule.contentsRect(opt->rect);
       
  5193                         QRect r2 = positionRect(w, rule, subRule, PseudoElement_ComboBoxDropDown,
       
  5194                                 opt->rect, opt->direction);
       
  5195                         if (subRule.hasPosition() && subRule.position()->position & Qt::AlignLeft) {
       
  5196                             return visualRect(opt->direction, r, r.adjusted(r2.width(),0,0,0));
       
  5197                         } else {
       
  5198                             return visualRect(opt->direction, r, r.adjusted(0,0,-r2.width(),0));
       
  5199                         }
       
  5200                     }
       
  5201                 case SC_ComboBoxArrow: {
       
  5202                     QRenderRule subRule = renderRule(w, opt, PseudoElement_ComboBoxDropDown);
       
  5203                     return positionRect(w, rule, subRule, PseudoElement_ComboBoxDropDown, opt->rect, opt->direction);
       
  5204                                                                            }
       
  5205                 case SC_ComboBoxListBoxPopup:
       
  5206                 default:
       
  5207                     return baseStyle()->subControlRect(cc, opt, sc, w);
       
  5208                 }
       
  5209             }
       
  5210 
       
  5211             QStyleOptionComboBox comboBox(*cb);
       
  5212             comboBox.rect = rule.borderRect(opt->rect);
       
  5213             return rule.baseStyleCanDraw() ? baseStyle()->subControlRect(cc, &comboBox, sc, w)
       
  5214                                            : QWindowsStyle::subControlRect(cc, &comboBox, sc, w);
       
  5215         }
       
  5216         break;
       
  5217 
       
  5218 #ifndef QT_NO_SPINBOX
       
  5219     case CC_SpinBox:
       
  5220         if (const QStyleOptionSpinBox *spin = qstyleoption_cast<const QStyleOptionSpinBox *>(opt)) {
       
  5221             QRenderRule upRule = renderRule(w, opt, PseudoElement_SpinBoxUpButton);
       
  5222             QRenderRule downRule = renderRule(w, opt, PseudoElement_SpinBoxDownButton);
       
  5223             bool ruleMatch = rule.hasBox() || !rule.hasNativeBorder();
       
  5224             bool upRuleMatch = upRule.hasGeometry() || upRule.hasPosition();
       
  5225             bool downRuleMatch = downRule.hasGeometry() || upRule.hasPosition();
       
  5226             if (ruleMatch || upRuleMatch || downRuleMatch) {
       
  5227                 switch (sc) {
       
  5228                 case SC_SpinBoxFrame:
       
  5229                     return rule.borderRect(opt->rect);
       
  5230                 case SC_SpinBoxEditField:
       
  5231                     {
       
  5232                         QRect r = rule.contentsRect(opt->rect);
       
  5233                         // Use the widest button on each side to determine edit field size.
       
  5234                         Qt::Alignment upAlign, downAlign;
       
  5235 
       
  5236                         upAlign = upRule.hasPosition() ? upRule.position()->position
       
  5237                                 : Qt::Alignment(Qt::AlignRight);
       
  5238                         upAlign = resolveAlignment(opt->direction, upAlign);
       
  5239 
       
  5240                         downAlign = downRule.hasPosition() ? downRule.position()->position
       
  5241                                 : Qt::Alignment(Qt::AlignRight);
       
  5242                         downAlign = resolveAlignment(opt->direction, downAlign);
       
  5243 
       
  5244                         int upSize = subControlRect(CC_SpinBox, opt, SC_SpinBoxUp, w).width();
       
  5245                         int downSize = subControlRect(CC_SpinBox, opt, SC_SpinBoxDown, w).width();
       
  5246                         int widestL = qMax((upAlign & Qt::AlignLeft) ? upSize : 0,
       
  5247                                 (downAlign & Qt::AlignLeft) ? downSize : 0);
       
  5248                         int widestR = qMax((upAlign & Qt::AlignRight) ? upSize : 0,
       
  5249                                 (downAlign & Qt::AlignRight) ? downSize : 0);
       
  5250                         r.setRight(r.right() - widestR);
       
  5251                         r.setLeft(r.left() + widestL);
       
  5252                         return r;
       
  5253                     }
       
  5254                 case SC_SpinBoxDown:
       
  5255                     if (downRuleMatch)
       
  5256                         return positionRect(w, rule, downRule, PseudoElement_SpinBoxDownButton,
       
  5257                                 opt->rect, opt->direction);
       
  5258                     break;
       
  5259                 case SC_SpinBoxUp:
       
  5260                     if (upRuleMatch)
       
  5261                         return positionRect(w, rule, upRule, PseudoElement_SpinBoxUpButton,
       
  5262                                 opt->rect, opt->direction);
       
  5263                     break;
       
  5264                 default:
       
  5265                     break;
       
  5266                 }
       
  5267 
       
  5268                 return baseStyle()->subControlRect(cc, opt, sc, w);
       
  5269             }
       
  5270 
       
  5271             QStyleOptionSpinBox spinBox(*spin);
       
  5272             spinBox.rect = rule.borderRect(opt->rect);
       
  5273             return rule.baseStyleCanDraw() ? baseStyle()->subControlRect(cc, &spinBox, sc, w)
       
  5274                                            : QWindowsStyle::subControlRect(cc, &spinBox, sc, w);
       
  5275         }
       
  5276         break;
       
  5277 #endif // QT_NO_SPINBOX
       
  5278 
       
  5279     case CC_GroupBox:
       
  5280         if (const QStyleOptionGroupBox *gb = qstyleoption_cast<const QStyleOptionGroupBox *>(opt)) {
       
  5281             switch (sc) {
       
  5282             case SC_GroupBoxFrame:
       
  5283             case SC_GroupBoxContents: {
       
  5284                 if (rule.hasBox() || !rule.hasNativeBorder()) {
       
  5285                     return sc == SC_GroupBoxFrame ? rule.borderRect(opt->rect)
       
  5286                                                   : rule.contentsRect(opt->rect);
       
  5287                 }
       
  5288                 QStyleOptionGroupBox groupBox(*gb);
       
  5289                 groupBox.rect = rule.borderRect(opt->rect);
       
  5290                 return baseStyle()->subControlRect(cc, &groupBox, sc, w);
       
  5291             }
       
  5292             default:
       
  5293             case SC_GroupBoxLabel:
       
  5294             case SC_GroupBoxCheckBox: {
       
  5295                 QRenderRule indRule = renderRule(w, opt, PseudoElement_GroupBoxIndicator);
       
  5296                 QRenderRule labelRule = renderRule(w, opt, PseudoElement_GroupBoxTitle);
       
  5297                 if (!labelRule.hasPosition() && !labelRule.hasGeometry() && !labelRule.hasBox()
       
  5298                     && !labelRule.hasBorder() && !indRule.hasContentsSize()) {
       
  5299                     QStyleOptionGroupBox groupBox(*gb);
       
  5300                     groupBox.rect = rule.borderRect(opt->rect);
       
  5301                     return baseStyle()->subControlRect(cc, &groupBox, sc, w);
       
  5302                 }
       
  5303                 int tw = opt->fontMetrics.width(gb->text);
       
  5304                 int th = opt->fontMetrics.height();
       
  5305                 int spacing = pixelMetric(QStyle::PM_CheckBoxLabelSpacing, opt, w);
       
  5306                 int iw = pixelMetric(QStyle::PM_IndicatorWidth, opt, w);
       
  5307                 int ih = pixelMetric(QStyle::PM_IndicatorHeight, opt, w);
       
  5308 
       
  5309                 if (gb->subControls & QStyle::SC_GroupBoxCheckBox) {
       
  5310                     tw = tw + iw + spacing;
       
  5311                     th = qMax(th, ih);
       
  5312                 }
       
  5313                 if (!labelRule.hasGeometry()) {
       
  5314                     labelRule.geo = new QStyleSheetGeometryData(tw, th, tw, th, -1, -1);
       
  5315                 } else {
       
  5316                     labelRule.geo->width = tw;
       
  5317                     labelRule.geo->height = th;
       
  5318                 }
       
  5319                 if (!labelRule.hasPosition()) {
       
  5320                     labelRule.p = new QStyleSheetPositionData(0, 0, 0, 0, defaultOrigin(PseudoElement_GroupBoxTitle),
       
  5321                                                               gb->textAlignment, PositionMode_Static);
       
  5322                 }
       
  5323                 QRect r = positionRect(w, rule, labelRule, PseudoElement_GroupBoxTitle,
       
  5324                                       opt->rect, opt->direction);
       
  5325                 if (gb->subControls & SC_GroupBoxCheckBox) {
       
  5326                     r = labelRule.contentsRect(r);
       
  5327                     if (sc == SC_GroupBoxLabel) {
       
  5328                         r.setLeft(r.left() + iw + spacing);
       
  5329                         r.setTop(r.center().y() - th/2);
       
  5330                     } else {
       
  5331                         r = QRect(r.left(), r.center().y() - ih/2, iw, ih);
       
  5332                     }
       
  5333                     return r;
       
  5334                 } else {
       
  5335                     return labelRule.contentsRect(r);
       
  5336                 }
       
  5337             }
       
  5338             } // switch
       
  5339         }
       
  5340         break;
       
  5341 
       
  5342     case CC_ToolButton:
       
  5343         if (const QStyleOptionToolButton *tb = qstyleoption_cast<const QStyleOptionToolButton *>(opt)) {
       
  5344             if (rule.hasBox() || !rule.hasNativeBorder()) {
       
  5345                 switch (sc) {
       
  5346                 case SC_ToolButton: return rule.borderRect(opt->rect);
       
  5347                 case SC_ToolButtonMenu: {
       
  5348                     QRenderRule subRule = renderRule(w, opt, PseudoElement_ToolButtonMenu);
       
  5349                     return positionRect(w, rule, subRule, PseudoElement_ToolButtonMenu, opt->rect, opt->direction);
       
  5350                                                                             }
       
  5351                 default:
       
  5352                     break;
       
  5353                 }
       
  5354             }
       
  5355 
       
  5356             QStyleOptionToolButton tool(*tb);
       
  5357             tool.rect = rule.borderRect(opt->rect);
       
  5358             return rule.baseStyleCanDraw() ? baseStyle()->subControlRect(cc, &tool, sc, w)
       
  5359                                            : QWindowsStyle::subControlRect(cc, &tool, sc, w);
       
  5360             }
       
  5361             break;
       
  5362 
       
  5363 #ifndef QT_NO_SCROLLBAR
       
  5364     case CC_ScrollBar:
       
  5365         if (const QStyleOptionSlider *sb = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
       
  5366             QStyleOptionSlider styleOptionSlider(*sb);
       
  5367             styleOptionSlider.rect = rule.borderRect(opt->rect);
       
  5368             if (rule.hasDrawable() || rule.hasBox()) {
       
  5369                 QRect grooveRect;
       
  5370                 if (!rule.hasBox()) {
       
  5371                     grooveRect = rule.baseStyleCanDraw() ? baseStyle()->subControlRect(cc, sb, SC_ScrollBarGroove, w)
       
  5372                                  : QWindowsStyle::subControlRect(cc, sb, SC_ScrollBarGroove, w);
       
  5373                 } else {
       
  5374                     grooveRect = rule.contentsRect(opt->rect);
       
  5375                 }
       
  5376 
       
  5377                 PseudoElement pe = PseudoElement_None;
       
  5378 
       
  5379                 switch (sc) {
       
  5380                 case SC_ScrollBarGroove:
       
  5381                     return grooveRect;
       
  5382                 case SC_ScrollBarAddPage:
       
  5383                 case SC_ScrollBarSubPage:
       
  5384                 case SC_ScrollBarSlider: {
       
  5385                     QRect contentRect = grooveRect;
       
  5386                     if (hasStyleRule(w, PseudoElement_ScrollBarSlider)) {
       
  5387                         QRenderRule sliderRule = renderRule(w, opt, PseudoElement_ScrollBarSlider);
       
  5388                         Origin origin = sliderRule.hasPosition() ? sliderRule.position()->origin : defaultOrigin(PseudoElement_ScrollBarSlider);
       
  5389                         contentRect = rule.originRect(opt->rect, origin);
       
  5390                     }
       
  5391                     int maxlen = (styleOptionSlider.orientation == Qt::Horizontal) ? contentRect.width() : contentRect.height();
       
  5392                     int sliderlen;
       
  5393                     if (sb->maximum != sb->minimum) {
       
  5394                         uint range = sb->maximum - sb->minimum;
       
  5395                         sliderlen = (qint64(sb->pageStep) * maxlen) / (range + sb->pageStep);
       
  5396 
       
  5397                         int slidermin = pixelMetric(PM_ScrollBarSliderMin, sb, w);
       
  5398                         if (sliderlen < slidermin || range > INT_MAX / 2)
       
  5399                             sliderlen = slidermin;
       
  5400                         if (sliderlen > maxlen)
       
  5401                             sliderlen = maxlen;
       
  5402                     } else {
       
  5403                         sliderlen = maxlen;
       
  5404                     }
       
  5405 
       
  5406                     int sliderstart = (styleOptionSlider.orientation == Qt::Horizontal ? contentRect.left() : contentRect.top())
       
  5407                         + sliderPositionFromValue(sb->minimum, sb->maximum, sb->sliderPosition,
       
  5408                                                   maxlen - sliderlen, sb->upsideDown);
       
  5409 
       
  5410                     QRect sr = (sb->orientation == Qt::Horizontal)
       
  5411                                ? QRect(sliderstart, contentRect.top(), sliderlen, contentRect.height())
       
  5412                                : QRect(contentRect.left(), sliderstart, contentRect.width(), sliderlen);
       
  5413                     if (sc == SC_ScrollBarSlider) {
       
  5414                         return sr;
       
  5415                     } else if (sc == SC_ScrollBarSubPage) {
       
  5416                         return QRect(contentRect.topLeft(), sb->orientation == Qt::Horizontal ? sr.bottomLeft() : sr.topRight());
       
  5417                     } else { // SC_ScrollBarAddPage
       
  5418                         return QRect(sb->orientation == Qt::Horizontal ? sr.topRight() : sr.bottomLeft(), contentRect.bottomRight());
       
  5419                     }
       
  5420                     break;
       
  5421                 }
       
  5422                 case SC_ScrollBarAddLine: pe = PseudoElement_ScrollBarAddLine; break;
       
  5423                 case SC_ScrollBarSubLine: pe = PseudoElement_ScrollBarSubLine; break;
       
  5424                 case SC_ScrollBarFirst: pe = PseudoElement_ScrollBarFirst;  break;
       
  5425                 case SC_ScrollBarLast: pe = PseudoElement_ScrollBarLast; break;
       
  5426                 default: break;
       
  5427                 }
       
  5428                 if (hasStyleRule(w,pe)) {
       
  5429                     QRenderRule subRule = renderRule(w, opt, pe);
       
  5430                     if (subRule.hasPosition() || subRule.hasGeometry() || subRule.hasBox()) {
       
  5431                         const QStyleSheetPositionData *pos = subRule.position();
       
  5432                         QRect originRect = grooveRect;
       
  5433                         if (rule.hasBox()) {
       
  5434                             Origin origin = (pos && pos->origin != Origin_Unknown) ? pos->origin : defaultOrigin(pe);
       
  5435                             originRect = rule.originRect(opt->rect, origin);
       
  5436                         }
       
  5437                         return positionRect(w, subRule, pe, originRect, styleOptionSlider.direction);
       
  5438                     }
       
  5439                 }
       
  5440             }
       
  5441             return rule.baseStyleCanDraw() ? baseStyle()->subControlRect(cc, &styleOptionSlider, sc, w)
       
  5442                                            : QWindowsStyle::subControlRect(cc, &styleOptionSlider, sc, w);
       
  5443         }
       
  5444         break;
       
  5445 #endif // QT_NO_SCROLLBAR
       
  5446 
       
  5447 #ifndef QT_NO_SLIDER
       
  5448     case CC_Slider:
       
  5449         if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
       
  5450             QRenderRule subRule = renderRule(w, opt, PseudoElement_SliderGroove);
       
  5451             if (!subRule.hasDrawable())
       
  5452                 break;
       
  5453             subRule.img = 0;
       
  5454             QRect gr = positionRect(w, rule, subRule, PseudoElement_SliderGroove, opt->rect, opt->direction);
       
  5455             switch (sc) {
       
  5456             case SC_SliderGroove:
       
  5457                 return gr;
       
  5458             case SC_SliderHandle: {
       
  5459                 bool horizontal = slider->orientation & Qt::Horizontal;
       
  5460                 QRect cr = subRule.contentsRect(gr);
       
  5461                 QRenderRule subRule2 = renderRule(w, opt, PseudoElement_SliderHandle);
       
  5462                 int len = horizontal ? subRule2.size().width() : subRule2.size().height();
       
  5463                 subRule2.img = 0;
       
  5464                 subRule2.geo = 0;
       
  5465                 cr = positionRect(w, subRule2, PseudoElement_SliderHandle, cr, opt->direction);
       
  5466                 int thickness = horizontal ? cr.height() : cr.width();
       
  5467                 int sliderPos = sliderPositionFromValue(slider->minimum, slider->maximum, slider->sliderPosition,
       
  5468                                                         (horizontal ? cr.width() : cr.height()) - len, slider->upsideDown);
       
  5469                 cr = horizontal ? QRect(cr.x() + sliderPos, cr.y(), len, thickness)
       
  5470                                   : QRect(cr.x(), cr.y() + sliderPos, thickness, len);
       
  5471                 return subRule2.borderRect(cr);
       
  5472                 break; }
       
  5473             case SC_SliderTickmarks:
       
  5474                 // TODO...
       
  5475             default:
       
  5476                 break;
       
  5477             }
       
  5478         }
       
  5479         break;
       
  5480 #endif // QT_NO_SLIDER
       
  5481 
       
  5482     case CC_MdiControls:
       
  5483         if (hasStyleRule(w, PseudoElement_MdiCloseButton)
       
  5484             || hasStyleRule(w, PseudoElement_MdiNormalButton)
       
  5485             || hasStyleRule(w, PseudoElement_MdiMinButton)) {
       
  5486             QList<QVariant> layout = rule.styleHint(QLatin1String("button-layout")).toList();
       
  5487             if (layout.isEmpty())
       
  5488                 layout = subControlLayout(QLatin1String("mNX"));
       
  5489 
       
  5490             int x = 0, width = 0;
       
  5491             QRenderRule subRule;
       
  5492             for (int i = 0; i < layout.count(); i++) {
       
  5493                 int layoutButton = layout[i].toInt();
       
  5494                 if (layoutButton < PseudoElement_MdiCloseButton
       
  5495                     || layoutButton > PseudoElement_MdiNormalButton)
       
  5496                     continue;
       
  5497                 QStyle::SubControl control = knownPseudoElements[layoutButton].subControl;
       
  5498                 if (!(opt->subControls & control))
       
  5499                     continue;
       
  5500                 subRule = renderRule(w, opt, layoutButton);
       
  5501                 width = subRule.size().width();
       
  5502                 if (sc == control)
       
  5503                     break;
       
  5504                 x += width;
       
  5505             }
       
  5506 
       
  5507             return subRule.borderRect(QRect(x, opt->rect.top(), width, opt->rect.height()));
       
  5508         }
       
  5509         break;
       
  5510 
       
  5511     case CC_TitleBar:
       
  5512         if (const QStyleOptionTitleBar *tb = qstyleoption_cast<const QStyleOptionTitleBar *>(opt)) {
       
  5513             QRenderRule subRule = renderRule(w, opt, PseudoElement_TitleBar);
       
  5514             if (!subRule.hasDrawable() && !subRule.hasBox() && !subRule.hasBorder())
       
  5515                 break;
       
  5516             QHash<QStyle::SubControl, QRect> layoutRects = titleBarLayout(w, tb);
       
  5517             return layoutRects.value(sc);
       
  5518         }
       
  5519         break;
       
  5520 
       
  5521     default:
       
  5522         break;
       
  5523     }
       
  5524 
       
  5525     return baseStyle()->subControlRect(cc, opt, sc, w);
       
  5526 }
       
  5527 
       
  5528 QRect QStyleSheetStyle::subElementRect(SubElement se, const QStyleOption *opt, const QWidget *w) const
       
  5529 {
       
  5530     RECURSION_GUARD(return baseStyle()->subElementRect(se, opt, w))
       
  5531 
       
  5532     QRenderRule rule = renderRule(w, opt);
       
  5533 #ifndef QT_NO_TABBAR
       
  5534     int pe = PseudoElement_None;
       
  5535 #endif
       
  5536 
       
  5537     switch (se) {
       
  5538     case SE_PushButtonContents:
       
  5539     case SE_PushButtonFocusRect:
       
  5540         if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
       
  5541             QStyleOptionButton btnOpt(*btn);
       
  5542             if (rule.hasBox() || !rule.hasNativeBorder())
       
  5543                 return visualRect(opt->direction, opt->rect, rule.contentsRect(opt->rect));
       
  5544             return rule.baseStyleCanDraw() ? baseStyle()->subElementRect(se, &btnOpt, w)
       
  5545                                            : QWindowsStyle::subElementRect(se, &btnOpt, w);
       
  5546         }
       
  5547         break;
       
  5548 
       
  5549     case SE_LineEditContents:
       
  5550     case SE_FrameContents:
       
  5551     case SE_ShapedFrameContents:
       
  5552         if (rule.hasBox() || !rule.hasNativeBorder()) {
       
  5553             return visualRect(opt->direction, opt->rect, rule.contentsRect(opt->rect));
       
  5554         }
       
  5555         break;
       
  5556 
       
  5557     case SE_CheckBoxIndicator:
       
  5558     case SE_RadioButtonIndicator:
       
  5559         if (rule.hasBox() || rule.hasBorder() || hasStyleRule(w, PseudoElement_Indicator)) {
       
  5560             PseudoElement pe = se == SE_CheckBoxIndicator ? PseudoElement_Indicator : PseudoElement_ExclusiveIndicator;
       
  5561             QRenderRule subRule = renderRule(w, opt, pe);
       
  5562             return positionRect(w, rule, subRule, pe, opt->rect, opt->direction);
       
  5563         }
       
  5564         break;
       
  5565 
       
  5566     case SE_CheckBoxContents:
       
  5567     case SE_RadioButtonContents:
       
  5568         if (rule.hasBox() || rule.hasBorder() || hasStyleRule(w, PseudoElement_Indicator)) {
       
  5569             bool isRadio = se == SE_RadioButtonContents;
       
  5570             QRect ir = subElementRect(isRadio ? SE_RadioButtonIndicator : SE_CheckBoxIndicator,
       
  5571                                       opt, w);
       
  5572             ir = visualRect(opt->direction, opt->rect, ir);
       
  5573             int spacing = pixelMetric(isRadio ? PM_RadioButtonLabelSpacing : PM_CheckBoxLabelSpacing, 0, w);
       
  5574             QRect cr = rule.contentsRect(opt->rect);
       
  5575             ir.setRect(ir.left() + ir.width() + spacing, cr.y(),
       
  5576                        cr.width() - ir.width() - spacing, cr.height());
       
  5577             return visualRect(opt->direction, opt->rect, ir);
       
  5578         }
       
  5579         break;
       
  5580 
       
  5581     case SE_ToolBoxTabContents:
       
  5582         if (w && hasStyleRule(w->parentWidget(), PseudoElement_ToolBoxTab)) {
       
  5583             QRenderRule subRule = renderRule(w->parentWidget(), opt, PseudoElement_ToolBoxTab);
       
  5584             return visualRect(opt->direction, opt->rect, subRule.contentsRect(opt->rect));
       
  5585         }
       
  5586         break;
       
  5587 
       
  5588     case SE_RadioButtonFocusRect:
       
  5589     case SE_RadioButtonClickRect: // focusrect | indicator
       
  5590         if (rule.hasBox() || rule.hasBorder() || hasStyleRule(w, PseudoElement_Indicator)) {
       
  5591             return opt->rect;
       
  5592         }
       
  5593         break;
       
  5594 
       
  5595     case SE_CheckBoxFocusRect:
       
  5596     case SE_CheckBoxClickRect: // relies on indicator and contents
       
  5597         return ParentStyle::subElementRect(se, opt, w);
       
  5598 
       
  5599 #ifndef QT_NO_ITEMVIEWS
       
  5600     case SE_ViewItemCheckIndicator:
       
  5601         if (!qstyleoption_cast<const QStyleOptionViewItemV4 *>(opt)) {
       
  5602             return subElementRect(SE_CheckBoxIndicator, opt, w);
       
  5603         }
       
  5604         // intentionally falls through
       
  5605     case SE_ItemViewItemText:
       
  5606     case SE_ItemViewItemDecoration:
       
  5607     case SE_ItemViewItemFocusRect:
       
  5608         if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast<const QStyleOptionViewItemV4 *>(opt)) {
       
  5609             QRenderRule subRule = renderRule(w, opt, PseudoElement_ViewItem);
       
  5610             QStyleOptionViewItemV4 optCopy(*vopt);
       
  5611             optCopy.rect = subRule.contentsRect(vopt->rect);
       
  5612             QRect rect = ParentStyle::subElementRect(se, &optCopy, w);
       
  5613             PseudoElement pe = PseudoElement_None;
       
  5614             if (se == SE_ItemViewItemText || se == SE_ItemViewItemFocusRect)
       
  5615                 pe = PseudoElement_ViewItemText;
       
  5616             else if (se == SE_ItemViewItemDecoration && vopt->features & QStyleOptionViewItemV2::HasDecoration)
       
  5617                 pe = PseudoElement_ViewItemIcon;
       
  5618             else if (se == SE_ItemViewItemCheckIndicator && vopt->features & QStyleOptionViewItemV2::HasCheckIndicator)
       
  5619                 pe = PseudoElement_ViewItemIndicator;
       
  5620             else
       
  5621                 break;
       
  5622             QRenderRule subRule2 = renderRule(w, opt, pe);
       
  5623             return positionRect(w, subRule2, pe, rect, opt->direction);
       
  5624          }
       
  5625         break;
       
  5626 #endif // QT_NO_ITEMVIEWS
       
  5627 
       
  5628     case SE_HeaderArrow: {
       
  5629         QRenderRule subRule = renderRule(w, opt, PseudoElement_HeaderViewUpArrow);
       
  5630         if (subRule.hasPosition() || subRule.hasGeometry())
       
  5631             return positionRect(w, rule, subRule, PseudoElement_HeaderViewUpArrow, opt->rect, opt->direction);
       
  5632                          }
       
  5633         break;
       
  5634 
       
  5635     case SE_HeaderLabel: {
       
  5636         QRenderRule subRule = renderRule(w, opt, PseudoElement_HeaderViewSection);
       
  5637         if (subRule.hasBox() || !subRule.hasNativeBorder())
       
  5638             return subRule.contentsRect(opt->rect);
       
  5639                          }
       
  5640         break;
       
  5641 
       
  5642     case SE_ProgressBarGroove:
       
  5643     case SE_ProgressBarContents:
       
  5644     case SE_ProgressBarLabel:
       
  5645         if (const QStyleOptionProgressBarV2 *pb = qstyleoption_cast<const QStyleOptionProgressBarV2 *>(opt)) {
       
  5646             if (rule.hasBox() || !rule.hasNativeBorder() || rule.hasPosition() || hasStyleRule(w, PseudoElement_ProgressBarChunk)) {
       
  5647                 if (se == SE_ProgressBarGroove)
       
  5648                     return rule.borderRect(pb->rect);
       
  5649                 else if (se == SE_ProgressBarContents)
       
  5650                     return rule.contentsRect(pb->rect);
       
  5651 
       
  5652                 QSize sz = pb->fontMetrics.size(0, pb->text);
       
  5653                 return QStyle::alignedRect(Qt::LeftToRight, rule.hasPosition() ? rule.position()->textAlignment : pb->textAlignment,
       
  5654                                            sz, pb->rect);
       
  5655             }
       
  5656         }
       
  5657         break;
       
  5658 
       
  5659 #ifndef QT_NO_TABBAR
       
  5660     case SE_TabWidgetLeftCorner:
       
  5661         pe = PseudoElement_TabWidgetLeftCorner;
       
  5662         // intentionally falls through
       
  5663     case SE_TabWidgetRightCorner:
       
  5664         if (pe == PseudoElement_None)
       
  5665             pe = PseudoElement_TabWidgetRightCorner;
       
  5666         // intentionally falls through
       
  5667     case SE_TabWidgetTabBar:
       
  5668         if (pe == PseudoElement_None)
       
  5669             pe = PseudoElement_TabWidgetTabBar;
       
  5670         // intentionally falls through
       
  5671     case SE_TabWidgetTabPane:
       
  5672     case SE_TabWidgetTabContents:
       
  5673         if (pe == PseudoElement_None)
       
  5674             pe = PseudoElement_TabWidgetPane;
       
  5675 
       
  5676         if (hasStyleRule(w, pe)) {
       
  5677             QRect r = QWindowsStyle::subElementRect(pe == PseudoElement_TabWidgetPane ? SE_TabWidgetTabPane : se, opt, w);
       
  5678             QRenderRule subRule = renderRule(w, opt, pe);
       
  5679             r = positionRect(w, subRule, pe, r, opt->direction);
       
  5680             if (pe == PseudoElement_TabWidgetTabBar) {
       
  5681                 Q_ASSERT(opt);
       
  5682                 r = opt->rect.intersected(r);
       
  5683             }
       
  5684             if (se == SE_TabWidgetTabContents)
       
  5685                 r = subRule.contentsRect(r);
       
  5686             return r;
       
  5687         }
       
  5688         break;
       
  5689 
       
  5690     case SE_TabBarTearIndicator: {
       
  5691         QRenderRule subRule = renderRule(w, opt, PseudoElement_TabBarTear);
       
  5692         if (subRule.hasContentsSize()) {
       
  5693             QRect r;
       
  5694             if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(opt)) {
       
  5695                 switch (tab->shape) {
       
  5696                 case QTabBar::RoundedNorth:
       
  5697                 case QTabBar::TriangularNorth:
       
  5698                 case QTabBar::RoundedSouth:
       
  5699                 case QTabBar::TriangularSouth:
       
  5700                     r.setRect(tab->rect.left(), tab->rect.top(), subRule.size().width(), opt->rect.height());
       
  5701                     break;
       
  5702                 case QTabBar::RoundedWest:
       
  5703                 case QTabBar::TriangularWest:
       
  5704                 case QTabBar::RoundedEast:
       
  5705                 case QTabBar::TriangularEast:
       
  5706                     r.setRect(tab->rect.left(), tab->rect.top(), opt->rect.width(), subRule.size().height());
       
  5707                     break;
       
  5708                 default:
       
  5709                     break;
       
  5710                 }
       
  5711                 r = visualRect(opt->direction, opt->rect, r);
       
  5712             }
       
  5713             return r;
       
  5714         }
       
  5715         break;
       
  5716     }
       
  5717     case SE_TabBarTabText:
       
  5718     case SE_TabBarTabLeftButton:
       
  5719     case SE_TabBarTabRightButton: {
       
  5720         QRenderRule subRule = renderRule(w, opt, PseudoElement_TabBarTab);
       
  5721         if (subRule.hasBox() || !subRule.hasNativeBorder()) {
       
  5722             return ParentStyle::subElementRect(se, opt, w);
       
  5723         }
       
  5724         break;
       
  5725     }
       
  5726 #endif // QT_NO_TABBAR
       
  5727 
       
  5728     case SE_DockWidgetCloseButton:
       
  5729     case SE_DockWidgetFloatButton: {
       
  5730         PseudoElement pe = (se == SE_DockWidgetCloseButton) ? PseudoElement_DockWidgetCloseButton : PseudoElement_DockWidgetFloatButton;
       
  5731         QRenderRule subRule2 = renderRule(w, opt, pe);
       
  5732         if (!subRule2.hasPosition())
       
  5733             break;
       
  5734         QRenderRule subRule = renderRule(w, opt, PseudoElement_DockWidgetTitle);
       
  5735         return positionRect(w, subRule, subRule2, pe, opt->rect, opt->direction);
       
  5736                                    }
       
  5737 
       
  5738     default:
       
  5739         break;
       
  5740     }
       
  5741 
       
  5742     return baseStyle()->subElementRect(se, opt, w);
       
  5743 }
       
  5744 
       
  5745 bool QStyleSheetStyle::event(QEvent *e)
       
  5746 {
       
  5747     return (baseStyle()->event(e) && e->isAccepted()) || ParentStyle::event(e);
       
  5748 }
       
  5749 
       
  5750 void QStyleSheetStyle::updateStyleSheetFont(QWidget* w) const
       
  5751 {
       
  5752     QWidget *container = containerWidget(w);
       
  5753     QRenderRule rule = renderRule(container, PseudoElement_None,
       
  5754             PseudoClass_Active | PseudoClass_Enabled | extendedPseudoClass(container));
       
  5755     QFont font = rule.font.resolve(w->font());
       
  5756 
       
  5757     if ((!w->isWindow() || w->testAttribute(Qt::WA_WindowPropagation))
       
  5758         && isNaturalChild(w) && qobject_cast<QWidget *>(w->parent())) {
       
  5759 
       
  5760         font = font.resolve(static_cast<QWidget *>(w->parent())->font());
       
  5761     }
       
  5762 
       
  5763     if (w->data->fnt == font)
       
  5764         return;
       
  5765 
       
  5766 #ifdef QT3_SUPPORT
       
  5767     QFont old = w->data->fnt;
       
  5768 #endif
       
  5769     w->data->fnt = font;
       
  5770 #if defined(Q_WS_X11)
       
  5771     // make sure the font set on this widget is associated with the correct screen
       
  5772     //w->data->fnt.x11SetScreen(w->d_func()->xinfo.screen());
       
  5773 #endif
       
  5774 
       
  5775     QEvent e(QEvent::FontChange);
       
  5776     QApplication::sendEvent(w, &e);
       
  5777 #ifdef QT3_SUPPORT
       
  5778     w->fontChange(old);
       
  5779 #endif
       
  5780 }
       
  5781 
       
  5782 void QStyleSheetStyle::saveWidgetFont(QWidget* w, const QFont& font) const
       
  5783 {
       
  5784     w->setProperty("_q_styleSheetWidgetFont", font);
       
  5785 }
       
  5786 
       
  5787 void QStyleSheetStyle::clearWidgetFont(QWidget* w) const
       
  5788 {
       
  5789     w->setProperty("_q_styleSheetWidgetFont", QVariant(QVariant::Invalid));
       
  5790 }
       
  5791 
       
  5792 // Polish palette that should be used for a particular widget, with particular states
       
  5793 // (eg. :focus, :hover, ...)
       
  5794 // this is called by widgets that paint themself in their paint event
       
  5795 // Returns true if there is a new palette in pal.
       
  5796 bool QStyleSheetStyle::styleSheetPalette(const QWidget* w, const QStyleOption* opt, QPalette* pal)
       
  5797 {
       
  5798     if (!w || !opt || !pal)
       
  5799         return false;
       
  5800 
       
  5801     RECURSION_GUARD(return false)
       
  5802 
       
  5803     w = containerWidget(w);
       
  5804 
       
  5805     QRenderRule rule = renderRule(w, PseudoElement_None, pseudoClass(opt->state) | extendedPseudoClass(w));
       
  5806     if (!rule.hasPalette())
       
  5807         return false;
       
  5808 
       
  5809     rule.configurePalette(pal, QPalette::NoRole, QPalette::NoRole);
       
  5810     return true;
       
  5811 }
       
  5812 
       
  5813 Qt::Alignment QStyleSheetStyle::resolveAlignment(Qt::LayoutDirection layDir, Qt::Alignment src)
       
  5814 {
       
  5815     if (layDir == Qt::LeftToRight || src & Qt::AlignAbsolute)
       
  5816         return src;
       
  5817 
       
  5818     if (src & Qt::AlignLeft) {
       
  5819         src &= ~Qt::AlignLeft;
       
  5820         src |= Qt::AlignRight;
       
  5821     } else if (src & Qt::AlignRight) {
       
  5822         src &= ~Qt::AlignRight;
       
  5823         src |= Qt::AlignLeft;
       
  5824     }
       
  5825     src |= Qt::AlignAbsolute;
       
  5826     return src;
       
  5827 }
       
  5828 
       
  5829 // Returns whether the given QWidget has a "natural" parent, meaning that
       
  5830 // the parent contains this child as part of its normal operation.
       
  5831 // An example is the QTabBar inside a QTabWidget.
       
  5832 // This does not mean that any QTabBar which is a child of QTabWidget will
       
  5833 // match, only the one that was created by the QTabWidget initialization
       
  5834 // (and hence has the correct object name).
       
  5835 bool QStyleSheetStyle::isNaturalChild(const QWidget *w)
       
  5836 {
       
  5837     if (w->objectName().startsWith(QLatin1String("qt_")))
       
  5838         return true;
       
  5839 
       
  5840     return false;
       
  5841 }
       
  5842 
       
  5843 QT_END_NAMESPACE
       
  5844 
       
  5845 #include "moc_qstylesheetstyle_p.cpp"
       
  5846 
       
  5847 #endif // QT_NO_STYLE_STYLESHEET