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