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