QGtkStyle: use gtk_widget_get_style()
[profile/ivi/qtbase.git] / src / widgets / styles / qgtkstyle.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.  For licensing terms and
14 ** conditions see http://qt.digia.com/licensing.  For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file.  Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights.  These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file.  Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 #include "qgtkstyle.h"
42
43 #if !defined(QT_NO_STYLE_GTK)
44
45 #include <private/qapplication_p.h>
46 #include <QtCore/QLibrary>
47 #include <QtCore/QSettings>
48 #include <QtWidgets/QDialogButtonBox>
49 #include <QtWidgets/QStatusBar>
50 #include <QtWidgets/QLineEdit>
51 #include <QtWidgets/QWidget>
52 #include <QtWidgets/QListView>
53 #include <QtWidgets/QApplication>
54 #include <QtWidgets/QStyleOption>
55 #include <QtWidgets/QPushButton>
56 #include <QtGui/QPainter>
57 #include <QtWidgets/QMainWindow>
58 #include <QtWidgets/QToolBar>
59 #include <QtWidgets/QHeaderView>
60 #include <QtWidgets/QMenuBar>
61 #include <QtWidgets/QComboBox>
62 #include <QtWidgets/QSpinBox>
63 #include <QtWidgets/QScrollBar>
64 #include <QtWidgets/QAbstractButton>
65 #include <QtWidgets/QToolButton>
66 #include <QtWidgets/QGroupBox>
67 #include <QtWidgets/QRadioButton>
68 #include <QtWidgets/QCheckBox>
69 #include <QtWidgets/QTreeView>
70 #include <QtWidgets/QStyledItemDelegate>
71 #include <QtWidgets/QWizard>
72
73 #include <qpixmapcache.h>
74 #undef signals // Collides with GTK stymbols
75 #include <private/qgtkpainter_p.h>
76 #include <private/qstylehelper_p.h>
77 #include <private/qgtkstyle_p.h>
78
79 QT_BEGIN_NAMESPACE
80
81 static void qt_gtk_draw_mdibutton(QPainter *painter, const QStyleOptionTitleBar *option, const QRect &tmp, bool hover, bool sunken)
82 {
83     QColor dark;
84     dark.setHsv(option->palette.button().color().hue(),
85                 qMin(255, (int)(option->palette.button().color().saturation()*1.9)),
86                 qMin(255, (int)(option->palette.button().color().value()*0.7)));
87
88     QColor highlight = option->palette.highlight().color();
89
90     bool active = (option->titleBarState & QStyle::State_Active);
91     QColor titleBarHighlight(255, 255, 255, 60);
92
93     if (sunken)
94         painter->fillRect(tmp.adjusted(1, 1, -1, -1), option->palette.highlight().color().darker(120));
95     else if (hover)
96         painter->fillRect(tmp.adjusted(1, 1, -1, -1), QColor(255, 255, 255, 20));
97
98     QColor mdiButtonGradientStartColor;
99     QColor mdiButtonGradientStopColor;
100
101     mdiButtonGradientStartColor = QColor(0, 0, 0, 40);
102     mdiButtonGradientStopColor = QColor(255, 255, 255, 60);
103
104     if (sunken)
105         titleBarHighlight = highlight.darker(130);
106
107     QLinearGradient gradient(tmp.center().x(), tmp.top(), tmp.center().x(), tmp.bottom());
108     gradient.setColorAt(0, mdiButtonGradientStartColor);
109     gradient.setColorAt(1, mdiButtonGradientStopColor);
110     QColor mdiButtonBorderColor(active ? option->palette.highlight().color().darker(180): dark.darker(110));
111
112     painter->setPen(QPen(mdiButtonBorderColor, 1));
113     const QLine lines[4] = {
114         QLine(tmp.left() + 2, tmp.top(), tmp.right() - 2, tmp.top()),
115         QLine(tmp.left() + 2, tmp.bottom(), tmp.right() - 2, tmp.bottom()),
116         QLine(tmp.left(), tmp.top() + 2, tmp.left(), tmp.bottom() - 2),
117         QLine(tmp.right(), tmp.top() + 2, tmp.right(), tmp.bottom() - 2)
118     };
119     painter->drawLines(lines, 4);
120     const QPoint points[4] = {
121         QPoint(tmp.left() + 1, tmp.top() + 1),
122         QPoint(tmp.right() - 1, tmp.top() + 1),
123         QPoint(tmp.left() + 1, tmp.bottom() - 1),
124         QPoint(tmp.right() - 1, tmp.bottom() - 1)
125     };
126     painter->drawPoints(points, 4);
127
128     painter->setPen(titleBarHighlight);
129     painter->drawLine(tmp.left() + 2, tmp.top() + 1, tmp.right() - 2, tmp.top() + 1);
130     painter->drawLine(tmp.left() + 1, tmp.top() + 2, tmp.left() + 1, tmp.bottom() - 2);
131
132     painter->setPen(QPen(gradient, 1));
133     painter->drawLine(tmp.right() + 1, tmp.top() + 2, tmp.right() + 1, tmp.bottom() - 2);
134     painter->drawPoint(tmp.right() , tmp.top() + 1);
135
136     painter->drawLine(tmp.left() + 2, tmp.bottom() + 1, tmp.right() - 2, tmp.bottom() + 1);
137     painter->drawPoint(tmp.left() + 1, tmp.bottom());
138     painter->drawPoint(tmp.right() - 1, tmp.bottom());
139     painter->drawPoint(tmp.right() , tmp.bottom() - 1);
140 }
141
142 static const char * const dock_widget_close_xpm[] =
143     {
144         "11 13 5 1",
145         "  c None",
146         ". c #D5CFCB",
147         "+ c #6C6A67",
148         "@ c #6C6A67",
149         "$ c #B5B0AC",
150         "           ",
151         " @@@@@@@@@ ",
152         "@+       +@",
153         "@ +@   @+ @",
154         "@ @@@ @@@ @",
155         "@  @@@@@  @",
156         "@   @@@   @",
157         "@  @@@@@  @",
158         "@ @@@ @@@ @",
159         "@ +@   @+ @",
160         "@+       +@",
161         " @@@@@@@@@ ",
162         "           "
163     };
164
165 static const char * const dock_widget_restore_xpm[] =
166     {
167         "11 13 5 1",
168         "  c None",
169         ". c #D5CFCB",
170         "+ c #6C6A67",
171         "@ c #6C6A67",
172         "# c #6C6A67",
173         "           ",
174         " @@@@@@@@@ ",
175         "@+       +@",
176         "@   #@@@# @",
177         "@   @   @ @",
178         "@ #@@@# @ @",
179         "@ @   @ @ @",
180         "@ @   @@@ @",
181         "@ @   @   @",
182         "@ #@@@@   @",
183         "@+       +@",
184         " @@@@@@@@@ ",
185         "           "
186     };
187
188 static const char * const qt_titlebar_context_help[] = {
189     "10 10 3 1",
190     "  c None",
191     "# c #000000",
192     "+ c #444444",
193     "  +####+  ",
194     " ###  ### ",
195     " ##    ## ",
196     "     +##+ ",
197     "    +##   ",
198     "    ##    ",
199     "    ##    ",
200     "          ",
201     "    ##    ",
202     "    ##    "};
203
204 static const char * const qt_scrollbar_button_arrow_up[] = {
205     "7 4 2 1",
206     "   c None",
207     "*  c #BFBFBF",
208     "   *   ",
209     "  ***  ",
210     " ***** ",
211     "*******"};
212
213 static const char * const qt_scrollbar_button_arrow_down[] = {
214     "7 4 2 1",
215     "   c None",
216     "*  c #BFBFBF",
217     "*******",
218     " ***** ",
219     "  ***  ",
220     "   *   "};
221
222 static const int groupBoxBottomMargin    =  2;  // space below the groupbox
223 static const int groupBoxTitleMargin     =  6;  // space between contents and title
224 static const int groupBoxTopMargin       =  2;
225
226 /*!
227   Returns the configuration string for \a value.
228   Returns \a fallback if \a value is not found.
229  */
230 QString QGtkStyle::getGConfString(const QString &value, const QString &fallback)
231 {
232     return QGtkStylePrivate::getGConfString(value, fallback);
233 }
234
235 /*!
236   Returns the configuration boolean for \a key.
237   Returns \a fallback if \a key is not found.
238  */
239 bool QGtkStyle::getGConfBool(const QString &key, bool fallback)
240 {
241     return QGtkStylePrivate::getGConfBool(key, fallback);
242 }
243
244 static QColor mergedColors(const QColor &colorA, const QColor &colorB, int factor = 50)
245 {
246     const int maxFactor = 100;
247     QColor tmp = colorA;
248     tmp.setRed((tmp.red() * factor) / maxFactor + (colorB.red() * (maxFactor - factor)) / maxFactor);
249     tmp.setGreen((tmp.green() * factor) / maxFactor + (colorB.green() * (maxFactor - factor)) / maxFactor);
250     tmp.setBlue((tmp.blue() * factor) / maxFactor + (colorB.blue() * (maxFactor - factor)) / maxFactor);
251     return tmp;
252 }
253
254 static GdkColor fromQColor(const QColor &color)
255 {
256     GdkColor retval;
257     retval.red = color.red() * 255;
258     retval.green = color.green() * 255;
259     retval.blue = color.blue() * 255;
260     return retval;
261 }
262
263 /*!
264     \class QGtkStyle
265     \brief The QGtkStyle class provides a widget style rendered by GTK+
266     \since 4.5
267
268     \inmodule QtWidgets
269  
270     The QGtkStyle style provides a look and feel that integrates well
271     into GTK-based desktop environments such as the XFCe and GNOME.
272
273     It does this by making use of the GTK+ theme engine, ensuring
274     that Qt applications look and feel native on these platforms.
275
276     Note: The style requires GTK+ version 2.10 or later.
277           The Qt3-based "Qt" GTK+ theme engine will not work with QGtkStyle.
278
279     \sa {Cleanlooks Style Widget Gallery}, QWindowsXPStyle, QMacStyle, QWindowsStyle,
280         QPlastiqueStyle, QCleanlooksStyle
281 */
282
283 /*!
284     Constructs a QGtkStyle object.
285 */
286 QGtkStyle::QGtkStyle()
287     : QWindowsStyle(*new QGtkStylePrivate)
288 {
289     Q_D(QGtkStyle);
290     d->init();
291 }
292
293 /*!
294     \internal
295
296     Constructs a QGtkStyle object.
297 */
298 QGtkStyle::QGtkStyle(QGtkStylePrivate &dd)
299      : QWindowsStyle(dd)
300 {
301     Q_D(QGtkStyle);
302     d->init();
303 }
304
305
306 /*!
307     Destroys the QGtkStyle object.
308 */
309 QGtkStyle::~QGtkStyle()
310 {
311 }
312
313 /*!
314     \reimp
315 */
316 QPalette QGtkStyle::standardPalette() const
317 {
318     Q_D(const QGtkStyle);
319
320     QPalette palette = QWindowsStyle::standardPalette();
321     if (d->isThemeAvailable()) {
322         GtkStyle *style = d->gtkStyle();
323         GtkWidget *gtkButton = d->gtkWidget("GtkButton");
324         GtkWidget *gtkEntry = d->getTextColorWidget();
325         GdkColor gdkBg, gdkBase, gdkText, gdkForeground, gdkSbg, gdkSfg, gdkaSbg, gdkaSfg;
326         QColor bg, base, text, fg, highlight, highlightText, inactiveHighlight, inactiveHighlightedTExt;
327         gdkBg = style->bg[GTK_STATE_NORMAL];
328         gdkForeground = d->gtk_widget_get_style(gtkButton)->fg[GTK_STATE_NORMAL];
329
330         // Our base and selected color is primarily used for text
331         // so we assume a gtkEntry will have the most correct value
332         GtkStyle *gtkEntryStyle = d->gtk_widget_get_style(gtkEntry);
333         gdkBase = gtkEntryStyle->base[GTK_STATE_NORMAL];
334         gdkText = gtkEntryStyle->text[GTK_STATE_NORMAL];
335         gdkSbg = gtkEntryStyle->base[GTK_STATE_SELECTED];
336         gdkSfg = gtkEntryStyle->text[GTK_STATE_SELECTED];
337
338         // The ACTIVE base color is really used for inactive windows
339         gdkaSbg = gtkEntryStyle->base[GTK_STATE_ACTIVE];
340         gdkaSfg = gtkEntryStyle->text[GTK_STATE_ACTIVE];
341
342         bg = QColor(gdkBg.red>>8, gdkBg.green>>8, gdkBg.blue>>8);
343         text = QColor(gdkText.red>>8, gdkText.green>>8, gdkText.blue>>8);
344         fg = QColor(gdkForeground.red>>8, gdkForeground.green>>8, gdkForeground.blue>>8);
345         base = QColor(gdkBase.red>>8, gdkBase.green>>8, gdkBase.blue>>8);
346         highlight = QColor(gdkSbg.red>>8, gdkSbg.green>>8, gdkSbg.blue>>8);
347         highlightText = QColor(gdkSfg.red>>8, gdkSfg.green>>8, gdkSfg.blue>>8);
348         inactiveHighlight = QColor(gdkaSbg.red>>8, gdkaSbg.green>>8, gdkaSbg.blue>>8);
349         inactiveHighlightedTExt = QColor(gdkaSfg.red>>8, gdkaSfg.green>>8, gdkaSfg.blue>>8);
350
351         palette.setColor(QPalette::HighlightedText, highlightText);
352
353
354         palette.setColor(QPalette::Light, bg.lighter(125));
355         palette.setColor(QPalette::Shadow, bg.darker(130));
356         palette.setColor(QPalette::Dark, bg.darker(120));
357         palette.setColor(QPalette::Text, text);
358         palette.setColor(QPalette::WindowText, fg);
359         palette.setColor(QPalette::ButtonText, fg);
360         palette.setColor(QPalette::Base, base);
361
362         QColor alternateRowColor = palette.base().color().lighter(93); // ref gtkstyle.c draw_flat_box
363         GtkWidget *gtkTreeView = d->gtkWidget("GtkTreeView");
364         GdkColor *gtkAltBase = NULL;
365         d->gtk_widget_style_get(gtkTreeView, "odd-row-color", &gtkAltBase, NULL);
366         if (gtkAltBase) {
367             alternateRowColor = QColor(gtkAltBase->red>>8, gtkAltBase->green>>8, gtkAltBase->blue>>8);
368             d->gdk_color_free(gtkAltBase);
369         }
370         palette.setColor(QPalette::AlternateBase, alternateRowColor);
371
372         palette.setColor(QPalette::Window, bg);
373         palette.setColor(QPalette::Button, bg);
374         palette.setColor(QPalette::Background, bg);
375         QColor disabled((fg.red()   + bg.red())  / 2,
376                         (fg.green() + bg.green())/ 2,
377                         (fg.blue()  + bg.blue()) / 2);
378         palette.setColor(QPalette::Disabled, QPalette::Text, disabled);
379         palette.setColor(QPalette::Disabled, QPalette::WindowText, disabled);
380         palette.setColor(QPalette::Disabled, QPalette::Foreground, disabled);
381         palette.setColor(QPalette::Disabled, QPalette::ButtonText, disabled);
382         palette.setColor(QPalette::Highlight, highlight);
383         // calculate disabled colors by removing saturation
384         highlight.setHsv(highlight.hue(), 0, highlight.value(), highlight.alpha());
385         highlightText.setHsv(highlightText.hue(), 0, highlightText.value(), highlightText.alpha());
386         palette.setColor(QPalette::Disabled, QPalette::Highlight, highlight);
387         palette.setColor(QPalette::Disabled, QPalette::HighlightedText, highlightText);
388
389         palette.setColor(QPalette::Inactive, QPalette::HighlightedText, inactiveHighlightedTExt);
390         palette.setColor(QPalette::Inactive, QPalette::Highlight, inactiveHighlight);
391
392         style = d->gtk_rc_get_style_by_paths(d->gtk_settings_get_default(), "gtk-tooltips", "GtkWindow",
393                 d->gtk_window_get_type());
394         if (style) {
395             gdkText = style->fg[GTK_STATE_NORMAL];
396             text = QColor(gdkText.red>>8, gdkText.green>>8, gdkText.blue>>8);
397             palette.setColor(QPalette::ToolTipText, text);
398         }
399     }
400     return palette;
401 }
402
403 /*!
404     \reimp
405 */
406 void QGtkStyle::polish(QPalette &palette)
407 {
408     Q_D(QGtkStyle);
409
410     if (!d->isThemeAvailable())
411         QWindowsStyle::polish(palette);
412     else
413         palette = palette.resolve(standardPalette());
414 }
415
416 /*!
417     \reimp
418 */
419 void QGtkStyle::polish(QApplication *app)
420 {
421     Q_D(QGtkStyle);
422
423     QWindowsStyle::polish(app);
424     // Custom fonts and palettes with QtConfig are intentionally 
425     // not supported as these should be entirely determined by
426     // current Gtk settings
427     if (app->desktopSettingsAware() && d->isThemeAvailable()) {
428         QApplicationPrivate::setSystemPalette(standardPalette());
429         QApplicationPrivate::setSystemFont(d->getThemeFont());
430         d->applyCustomPaletteHash();
431         if (!d->isKDE4Session()) {
432 #ifndef QT_NO_FILEDIALOG
433             qt_filedialog_open_filename_hook = &QGtkStylePrivate::openFilename;
434             qt_filedialog_save_filename_hook = &QGtkStylePrivate::saveFilename;
435             qt_filedialog_open_filenames_hook = &QGtkStylePrivate::openFilenames;
436             qt_filedialog_existing_directory_hook = &QGtkStylePrivate::openDirectory;
437 #endif
438             qApp->installEventFilter(&d->filter);
439         }
440     }
441 }
442
443 /*!
444     \reimp
445 */
446 void QGtkStyle::unpolish(QApplication *app)
447 {
448     Q_D(QGtkStyle);
449
450     QWindowsStyle::unpolish(app);
451     QPixmapCache::clear();
452
453     if (app->desktopSettingsAware() && d->isThemeAvailable()
454         && !d->isKDE4Session()) {
455 #ifndef QT_NO_FILEDIALOG
456         qt_filedialog_open_filename_hook = 0;
457         qt_filedialog_save_filename_hook = 0;
458         qt_filedialog_open_filenames_hook = 0;
459         qt_filedialog_existing_directory_hook = 0;
460 #endif
461         qApp->removeEventFilter(&d->filter);
462     }
463 }
464
465 /*!
466     \reimp
467 */
468
469 void QGtkStyle::polish(QWidget *widget)
470 {
471     Q_D(QGtkStyle);
472
473     QWindowsStyle::polish(widget);
474     if (!d->isThemeAvailable())
475         return;
476     if (qobject_cast<QAbstractButton*>(widget)
477             || qobject_cast<QToolButton*>(widget)
478             || qobject_cast<QComboBox*>(widget)
479             || qobject_cast<QGroupBox*>(widget)
480             || qobject_cast<QScrollBar*>(widget)
481             || qobject_cast<QSlider*>(widget)
482             || qobject_cast<QAbstractSpinBox*>(widget)
483             || qobject_cast<QSpinBox*>(widget)
484             || qobject_cast<QHeaderView*>(widget))
485         widget->setAttribute(Qt::WA_Hover);
486 #ifndef QT_NO_TREEVIEW
487     else if (QTreeView *tree = qobject_cast<QTreeView *> (widget))
488         tree->viewport()->setAttribute(Qt::WA_Hover);
489 #endif
490 }
491
492 /*!
493     \reimp
494 */
495 void QGtkStyle::unpolish(QWidget *widget)
496 {
497     QWindowsStyle::unpolish(widget);
498 }
499
500 /*!
501     \reimp
502 */
503 int QGtkStyle::pixelMetric(PixelMetric metric,
504                            const QStyleOption *option,
505                            const QWidget *widget) const
506 {
507     Q_D(const QGtkStyle);
508
509     if (!d->isThemeAvailable())
510         return QWindowsStyle::pixelMetric(metric, option, widget);
511
512     switch (metric) {
513     case PM_DefaultFrameWidth:
514         if (qobject_cast<const QFrame*>(widget)) {
515             if (GtkStyle *style =
516                 d->gtk_rc_get_style_by_paths(d->gtk_settings_get_default(),
517                                                 "*.GtkScrolledWindow",
518                                                 "*.GtkScrolledWindow",
519                                                 d->gtk_window_get_type()))
520                 return qMax(style->xthickness, style->ythickness);
521         }
522         return 2;
523
524     case PM_MenuButtonIndicator:
525         return 20;
526
527     case PM_TabBarBaseOverlap:
528         return 1;
529
530     case PM_ToolBarSeparatorExtent:
531         return 11;
532
533     case PM_ToolBarFrameWidth:
534         return 1;
535
536     case PM_ToolBarItemSpacing:
537         return 0;
538
539     case PM_ButtonShiftHorizontal: {
540         GtkWidget *gtkButton = d->gtkWidget("GtkButton");
541         guint horizontal_shift;
542         d->gtk_widget_style_get(gtkButton, "child-displacement-x", &horizontal_shift, NULL);
543         return horizontal_shift;
544     }
545
546     case PM_ButtonShiftVertical: {
547         GtkWidget *gtkButton = d->gtkWidget("GtkButton");
548         guint vertical_shift;
549         d->gtk_widget_style_get(gtkButton, "child-displacement-y", &vertical_shift, NULL);
550         return vertical_shift;
551     }
552
553     case PM_MenuBarPanelWidth:
554         return 0;
555
556     case PM_MenuPanelWidth: {
557         GtkWidget *gtkMenu = d->gtkWidget("GtkMenu");
558         guint horizontal_padding = 0;
559         // horizontal-padding is used by Maemo to get thicker borders
560         if (!d->gtk_check_version(2, 10, 0))
561             d->gtk_widget_style_get(gtkMenu, "horizontal-padding", &horizontal_padding, NULL);
562         int padding = qMax<int>(d->gtk_widget_get_style(gtkMenu)->xthickness, horizontal_padding);
563         return padding;
564     }
565
566     case PM_ButtonIconSize: {
567         int retVal = 24;
568         GtkSettings *settings = d->gtk_settings_get_default();
569         gchararray icon_sizes;
570         g_object_get(settings, "gtk-icon-sizes", &icon_sizes, NULL);
571         QStringList values = QString(QLS(icon_sizes)).split(QLatin1Char(':'));
572         g_free(icon_sizes);
573         QChar splitChar(QLatin1Char(','));
574         foreach (const QString &value, values) {
575             if (value.startsWith(QLS("gtk-button="))) {
576                 QString iconSize = value.right(value.size() - 11);
577
578                 if (iconSize.contains(splitChar))
579                     retVal = iconSize.split(splitChar)[0].toInt();
580                 break;
581             }
582         }
583         return retVal;
584     }
585
586     case PM_MenuVMargin:
587
588     case PM_MenuHMargin:
589         return 0;
590
591     case PM_DockWidgetTitleMargin:
592         return 0;
593
594     case PM_DockWidgetTitleBarButtonMargin:
595         return 5;
596
597     case PM_TabBarTabVSpace:
598         return 12;
599
600     case PM_TabBarTabHSpace:
601         return 14;
602
603     case PM_TabBarTabShiftVertical:
604         return 2;
605
606     case PM_ToolBarHandleExtent:
607         return 9;
608
609     case PM_SplitterWidth:
610         return 6;
611
612     case PM_SliderThickness:
613     case PM_SliderControlThickness: {
614         GtkWidget *gtkScale = d->gtkWidget("GtkHScale");
615         gint val;
616         d->gtk_widget_style_get(gtkScale, "slider-width", &val, NULL);
617         if (metric == PM_SliderControlThickness)
618             return val + 2*d->gtk_widget_get_style(gtkScale)->ythickness;
619         return val;
620     }
621
622     case PM_ScrollBarExtent: {
623         gint sliderLength;
624         gint trough_border;
625         GtkWidget *hScrollbar = d->gtkWidget("GtkHScrollbar");
626         d->gtk_widget_style_get(hScrollbar,
627                                "trough-border",   &trough_border,
628                                "slider-width",    &sliderLength,
629                                NULL);
630         return sliderLength + trough_border*2;
631     }
632
633     case PM_ScrollBarSliderMin:
634         return 34;
635
636     case PM_SliderLength:
637         gint val;
638         d->gtk_widget_style_get(d->gtkWidget("GtkHScale"), "slider-length", &val, NULL);
639         return val;
640
641     case PM_ExclusiveIndicatorWidth:
642     case PM_ExclusiveIndicatorHeight:
643     case PM_IndicatorWidth:
644     case PM_IndicatorHeight: {
645         GtkWidget *gtkCheckButton = d->gtkWidget("GtkCheckButton");
646         gint size, spacing;
647         d->gtk_widget_style_get(gtkCheckButton, "indicator-spacing", &spacing, "indicator-size", &size, NULL);
648         return size + 2 * spacing;
649     }
650
651     case PM_MenuBarVMargin: {
652         GtkWidget *gtkMenubar = d->gtkWidget("GtkMenuBar");
653         return  qMax(0, d->gtk_widget_get_style(gtkMenubar)->ythickness);
654     }
655     case PM_ScrollView_ScrollBarSpacing:
656     {
657         gint spacing = 3;
658         GtkWidget *gtkScrollWindow = d->gtkWidget("GtkScrolledWindow");
659         Q_ASSERT(gtkScrollWindow);
660         d->gtk_widget_style_get(gtkScrollWindow, "scrollbar-spacing", &spacing, NULL);
661         return spacing;
662     }
663     case PM_SubMenuOverlap: {
664         gint offset = 0;
665         GtkWidget *gtkMenu = d->gtkWidget("GtkMenu");
666         d->gtk_widget_style_get(gtkMenu, "horizontal-offset", &offset, NULL);
667         return offset;
668     }
669     case PM_ToolTipLabelFrameWidth:
670         return 2;
671     case PM_ButtonDefaultIndicator:
672         return 0;
673     case PM_ListViewIconSize:
674         return 24;
675     case PM_DialogButtonsSeparator:
676         return 6;
677     case PM_TitleBarHeight:
678         return 24;
679     case PM_SpinBoxFrameWidth:
680         return 3;
681     case PM_MenuBarItemSpacing:
682         return 6;
683     case PM_MenuBarHMargin:
684         return 0;
685     case PM_ToolBarItemMargin:
686         return 1;
687     case PM_SmallIconSize:
688         return 16;
689     case PM_MaximumDragDistance:
690         return -1;
691     case PM_TabCloseIndicatorWidth:
692     case PM_TabCloseIndicatorHeight:
693         return 20;
694     default:
695         return QWindowsStyle::pixelMetric(metric, option, widget);
696     }
697 }
698
699 /*!
700     \reimp
701 */
702 int QGtkStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget,
703
704                          QStyleHintReturn *returnData = 0) const
705 {
706     Q_D(const QGtkStyle);
707
708     if (!d->isThemeAvailable())
709         return QWindowsStyle::styleHint(hint, option, widget, returnData);
710
711     switch (hint) {
712     case SH_ScrollBar_MiddleClickAbsolutePosition:
713         return true;
714     case SH_Menu_AllowActiveAndDisabled:
715         return false;
716     case SH_MainWindow_SpaceBelowMenuBar:
717         return 0;
718     case SH_MenuBar_MouseTracking:
719         return true;
720     case SH_TitleBar_AutoRaise:
721         return true;
722     case SH_TitleBar_NoBorder:
723         return true;
724     case SH_ItemView_ShowDecorationSelected:
725         return true;
726     case SH_Table_GridLineColor:
727         if (option)
728             return option->palette.background().color().darker(120).rgb();
729         break;
730     case SH_WindowFrame_Mask:
731         if (QStyleHintReturnMask *mask = qstyleoption_cast<QStyleHintReturnMask *>(returnData)) {
732             //left rounded corner
733             mask->region = option->rect;
734             mask->region -= QRect(option->rect.left(), option->rect.top(), 5, 1);
735             mask->region -= QRect(option->rect.left(), option->rect.top() + 1, 3, 1);
736             mask->region -= QRect(option->rect.left(), option->rect.top() + 2, 2, 1);
737             mask->region -= QRect(option->rect.left(), option->rect.top() + 3, 1, 2);
738
739             //right rounded corner
740             mask->region -= QRect(option->rect.right() - 4, option->rect.top(), 5, 1);
741             mask->region -= QRect(option->rect.right() - 2, option->rect.top() + 1, 3, 1);
742             mask->region -= QRect(option->rect.right() - 1, option->rect.top() + 2, 2, 1);
743             mask->region -= QRect(option->rect.right() , option->rect.top() + 3, 1, 2);
744         }
745         return QWindowsStyle::styleHint(hint, option, widget, returnData);
746     case SH_MessageBox_TextInteractionFlags:
747         return Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse;
748     case SH_MessageBox_CenterButtons:
749         return false;
750     case SH_WizardStyle:
751         return  QWizard::ClassicStyle;
752     case SH_ItemView_ArrowKeysNavigateIntoChildren:
753         return false;
754     case SH_DialogButtonLayout: {
755         int ret = QDialogButtonBox::GnomeLayout;
756         gboolean alternateOrder = 0;
757         GtkSettings *settings = d->gtk_settings_get_default();
758         g_object_get(settings, "gtk-alternative-button-order", &alternateOrder, NULL);
759
760         if (alternateOrder)
761             ret = QDialogButtonBox::WinLayout;
762
763         return ret;
764     }
765     break;
766
767     case SH_ToolButtonStyle:
768     {
769         if (d->isKDE4Session())
770             return QWindowsStyle::styleHint(hint, option, widget, returnData);
771         GtkWidget *gtkToolbar = d->gtkWidget("GtkToolbar");
772         GtkToolbarStyle toolbar_style = GTK_TOOLBAR_ICONS;
773         g_object_get(gtkToolbar, "toolbar-style", &toolbar_style, NULL);
774         switch (toolbar_style) {
775         case GTK_TOOLBAR_TEXT:
776             return Qt::ToolButtonTextOnly;
777         case GTK_TOOLBAR_BOTH:
778             return Qt::ToolButtonTextUnderIcon;
779         case GTK_TOOLBAR_BOTH_HORIZ:
780             return Qt::ToolButtonTextBesideIcon;
781         case GTK_TOOLBAR_ICONS:
782         default:
783             return Qt::ToolButtonIconOnly;
784         }
785     }
786     break;
787     case SH_SpinControls_DisableOnBounds:
788         return int(true);
789
790     case SH_DitherDisabledText:
791         return int(false);
792
793     case SH_ComboBox_Popup: {
794         GtkWidget *gtkComboBox = d->gtkWidget("GtkComboBox");
795         gboolean appears_as_list;
796         d->gtk_widget_style_get((GtkWidget*)gtkComboBox, "appears-as-list", &appears_as_list, NULL);
797         return appears_as_list ? 0 : 1;
798     }
799
800     case SH_MenuBar_AltKeyNavigation:
801         return int(false);
802
803     case SH_EtchDisabledText:
804         return int(false);
805
806     case SH_Menu_SubMenuPopupDelay: {
807         gint delay = 225;
808         GtkSettings *settings = d->gtk_settings_get_default();
809         g_object_get(settings, "gtk-menu-popup-delay", &delay, NULL);
810         return delay;
811     }
812
813     case SH_ScrollView_FrameOnlyAroundContents: {
814         gboolean scrollbars_within_bevel = false;
815         if (widget && widget->isWindow())
816             scrollbars_within_bevel = true;
817         else if (!d->gtk_check_version(2, 12, 0)) {
818             GtkWidget *gtkScrollWindow = d->gtkWidget("GtkScrolledWindow");
819             d->gtk_widget_style_get(gtkScrollWindow, "scrollbars-within-bevel", &scrollbars_within_bevel, NULL);
820         }
821         return !scrollbars_within_bevel;
822     }
823
824     case SH_DialogButtonBox_ButtonsHaveIcons: {
825         static bool buttonsHaveIcons = d->getGConfBool(QLS("/desktop/gnome/interface/buttons_have_icons"));
826         return buttonsHaveIcons;
827     }
828
829     case SH_UnderlineShortcut: {
830         gboolean underlineShortcut = true;
831         if (!d->gtk_check_version(2, 12, 0)) {
832             GtkSettings *settings = d->gtk_settings_get_default();
833             g_object_get(settings, "gtk-enable-mnemonics", &underlineShortcut, NULL);
834         }
835         return underlineShortcut;
836     }
837
838     default:
839         break;
840     }
841     return QWindowsStyle::styleHint(hint, option, widget, returnData);
842 }
843
844 /*!
845     \reimp
846 */
847 void QGtkStyle::drawPrimitive(PrimitiveElement element,
848                               const QStyleOption *option,
849                               QPainter *painter,
850                               const QWidget *widget) const
851 {
852     Q_D(const QGtkStyle);
853
854     if (!d->isThemeAvailable()) {
855         QWindowsStyle::drawPrimitive(element, option, painter, widget);
856         return;
857     }
858
859     GtkStyle* style = d->gtkStyle();
860     QGtkPainter gtkPainter(painter);
861
862     switch (element) {
863       case PE_Frame: {
864         if (widget && widget->inherits("QComboBoxPrivateContainer")){
865             QStyleOption copy = *option;
866             copy.state |= State_Raised;
867             proxy()->drawPrimitive(PE_PanelMenu, &copy, painter, widget);
868             break;
869         }
870         // Drawing the entire itemview frame is very expensive, especially on the native X11 engine
871         // Instead we cheat a bit and draw a border image without the center part, hence only scaling
872         // thin rectangular images
873         const int pmSize = 64;
874         const int border = proxy()->pixelMetric(PM_DefaultFrameWidth, option, widget);
875         const QString pmKey = QLatin1String("windowframe") % HexString<uint>(option->state);
876
877         QPixmap pixmap;
878         QRect pmRect(QPoint(0,0), QSize(pmSize, pmSize));
879
880         // Only draw through style once
881         if (!QPixmapCache::find(pmKey, pixmap)) {
882             pixmap = QPixmap(pmSize, pmSize);
883             pixmap.fill(Qt::transparent);
884             QPainter pmPainter(&pixmap);
885             QGtkPainter gtkFramePainter(&pmPainter);
886             gtkFramePainter.setUsePixmapCache(false); // Don't cache twice
887
888             GtkShadowType shadow_type = GTK_SHADOW_NONE;
889             if (option->state & State_Sunken)
890                 shadow_type = GTK_SHADOW_IN;
891             else if (option->state & State_Raised)
892                 shadow_type = GTK_SHADOW_OUT;
893
894             GtkStyle *style = d->gtk_rc_get_style_by_paths(d->gtk_settings_get_default(),
895                                      "*.GtkScrolledWindow", "*.GtkScrolledWindow", d->gtk_window_get_type());
896             if (style)
897                 gtkFramePainter.paintShadow(d->gtkWidget("GtkFrame"), "viewport", pmRect,
898                                          option->state & State_Enabled ? GTK_STATE_NORMAL : GTK_STATE_INSENSITIVE,
899                                          shadow_type, style);
900             QPixmapCache::insert(pmKey, pixmap);
901         }
902
903         QRect rect = option->rect;
904         const int rw = rect.width() - border;
905         const int rh = rect.height() - border;
906         const int pw = pmRect.width() - border;
907         const int ph = pmRect.height() - border;
908
909         // Sidelines
910         painter->drawPixmap(rect.adjusted(border, 0, -border, -rh), pixmap, pmRect.adjusted(border, 0, -border,-ph));
911         painter->drawPixmap(rect.adjusted(border, rh, -border, 0), pixmap, pmRect.adjusted(border, ph,-border,0));
912         painter->drawPixmap(rect.adjusted(0, border, -rw, -border), pixmap, pmRect.adjusted(0, border, -pw, -border));
913         painter->drawPixmap(rect.adjusted(rw, border, 0, -border), pixmap, pmRect.adjusted(pw, border, 0, -border));
914
915         // Corners
916         painter->drawPixmap(rect.adjusted(0, 0, -rw, -rh), pixmap, pmRect.adjusted(0, 0, -pw,-ph));
917         painter->drawPixmap(rect.adjusted(rw, 0, 0, -rh), pixmap, pmRect.adjusted(pw, 0, 0,-ph));
918         painter->drawPixmap(rect.adjusted(0, rh, -rw, 0), pixmap, pmRect.adjusted(0, ph, -pw,0));
919         painter->drawPixmap(rect.adjusted(rw, rh, 0, 0), pixmap, pmRect.adjusted(pw, ph, 0,0));
920     }
921     break;
922     case PE_FrameWindow:
923         painter->save();
924         {
925             QRect rect= option->rect;
926             painter->setPen(QPen(option->palette.dark().color().darker(150), 0));
927             painter->drawRect(option->rect.adjusted(0, 0, -1, -1));
928             painter->setPen(QPen(option->palette.light(), 0));
929             painter->drawLine(QPoint(rect.left() + 1, rect.top() + 1),
930                               QPoint(rect.left() + 1, rect.bottom() - 1));
931             painter->setPen(QPen(option->palette.background().color().darker(120), 0));
932             painter->drawLine(QPoint(rect.left() + 1, rect.bottom() - 1),
933                               QPoint(rect.right() - 2, rect.bottom() - 1));
934             painter->drawLine(QPoint(rect.right() - 1, rect.top() + 1),
935                               QPoint(rect.right() - 1, rect.bottom() - 1));
936         }
937         painter->restore();
938         break;
939
940     case PE_PanelTipLabel: {
941         GtkWidget *gtkWindow = d->gtkWidget("GtkWindow"); // The Murrine Engine currently assumes a widget is passed
942         style = d->gtk_rc_get_style_by_paths(d->gtk_settings_get_default(), "gtk-tooltips", "GtkWindow",
943                 d->gtk_window_get_type());
944         gtkPainter.paintFlatBox(gtkWindow, "tooltip", option->rect, GTK_STATE_NORMAL, GTK_SHADOW_NONE, style);
945     }
946     break;
947
948     case PE_PanelStatusBar: {
949         if (widget && widget->testAttribute(Qt::WA_SetPalette) &&
950             option->palette.resolve() & (1 << QPalette::Window)) {
951             // Respect custom palette
952             painter->fillRect(option->rect, option->palette.window());
953             break;
954         }
955         GtkShadowType shadow_type;
956         GtkWidget *gtkStatusbarFrame = d->gtkWidget("GtkStatusbar.GtkFrame");
957         d->gtk_widget_style_get(d->gtk_widget_get_parent(gtkStatusbarFrame), "shadow-type", &shadow_type, NULL);
958         gtkPainter.paintShadow(gtkStatusbarFrame, "frame", option->rect, GTK_STATE_NORMAL,
959                                shadow_type, d->gtk_widget_get_style(gtkStatusbarFrame));
960     }
961     break;
962
963     case PE_IndicatorHeaderArrow:
964         if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) {
965             GtkWidget *gtkTreeHeader = d->gtkWidget("GtkTreeView.GtkButton");
966             GtkStateType state = gtkPainter.gtkState(option);
967             style = d->gtk_widget_get_style(gtkTreeHeader);
968             GtkArrowType type = GTK_ARROW_UP;
969             // This sorting indicator inversion is intentional, and follows the GNOME HIG.
970             // See http://library.gnome.org/devel/hig-book/stable/controls-lists.html.en#controls-lists-sortable
971             if (header->sortIndicator & QStyleOptionHeader::SortUp)
972                 type = GTK_ARROW_UP;
973             else if (header->sortIndicator & QStyleOptionHeader::SortDown)
974                 type = GTK_ARROW_DOWN;
975
976             gtkPainter.paintArrow(gtkTreeHeader, "button", option->rect.adjusted(1, 1, -1, -1), type, state,
977                                   GTK_SHADOW_NONE, false, style);
978         }
979         break;
980
981     case PE_FrameDefaultButton: // fall through
982     case PE_FrameFocusRect:
983         if ((widget && qobject_cast<const QAbstractItemView*>(widget))) {
984             if (option->state & State_KeyboardFocusChange)
985                 QWindowsStyle::drawPrimitive(element, option, painter, widget);
986         } else {
987             // ### this mess should move to subcontrolrect
988             QRect frameRect = option->rect.adjusted(1, 1, -2, -2);
989             if ( qobject_cast<const QTabBar*>(widget)) {
990                 GtkWidget *gtkNotebook = d->gtkWidget("GtkNotebook");
991                 style = gtkPainter.getStyle(gtkNotebook);
992                 gtkPainter.paintFocus(gtkNotebook, "tab", frameRect.adjusted(-1, 1, 1, 1), GTK_STATE_ACTIVE, style);
993             } else {
994                 GtkWidget *gtkRadioButton = d->gtkWidget("GtkRadioButton");
995                 gtkPainter.paintFocus(gtkRadioButton, "radiobutton", frameRect, GTK_STATE_ACTIVE, style);
996             }
997         }
998         break;
999
1000     case PE_IndicatorBranch:
1001         if (option->state & State_Children) {
1002             QRect rect = option->rect;
1003             rect = QRect(0, 0, 12, 12);
1004             rect.moveCenter(option->rect.center());
1005             rect.translate(2, 0);
1006             GtkExpanderStyle openState = GTK_EXPANDER_EXPANDED;
1007             GtkExpanderStyle closedState = GTK_EXPANDER_COLLAPSED;
1008             GtkWidget *gtkTreeView = d->gtkWidget("GtkTreeView");
1009
1010             GtkStateType state = GTK_STATE_NORMAL;
1011             if (!(option->state & State_Enabled))
1012                 state = GTK_STATE_INSENSITIVE;
1013             else if (option->state & State_MouseOver)
1014                 state = GTK_STATE_PRELIGHT;
1015
1016             gtkPainter.paintExpander(gtkTreeView, "treeview", rect, state,
1017                                      option->state & State_Open ? openState : closedState , d->gtk_widget_get_style(gtkTreeView));
1018         }
1019         break;
1020
1021     case PE_PanelItemViewRow:
1022         // This primitive is only used to draw selection behind selected expander arrows.
1023         // We try not to decorate the tree branch background unless you inherit from StyledItemDelegate
1024         // The reason for this is that a lot of code that relies on custom item delegates will look odd having
1025         // a gradient on the branch but a flat shaded color on the item itself.
1026         QCommonStyle::drawPrimitive(element, option, painter, widget);
1027         if (!option->state & State_Selected) {
1028             break;
1029         } else {
1030             if (const QAbstractItemView *view = qobject_cast<const QAbstractItemView*>(widget)) {
1031                 if (!qobject_cast<QStyledItemDelegate*>(view->itemDelegate()))
1032                     break;
1033             }
1034         } // fall through
1035
1036     case PE_PanelItemViewItem:
1037         if (const QStyleOptionViewItem *vopt = qstyleoption_cast<const QStyleOptionViewItem *>(option)) {
1038             uint resolve_mask = vopt->palette.resolve();
1039             if (vopt->backgroundBrush.style() != Qt::NoBrush
1040                     || (resolve_mask & (1 << QPalette::Base)))
1041             {
1042                 QPointF oldBO = painter->brushOrigin();
1043                 painter->setBrushOrigin(vopt->rect.topLeft());
1044                 painter->fillRect(vopt->rect, vopt->backgroundBrush);
1045                 painter->setBrushOrigin(oldBO);
1046                 if (!(option->state & State_Selected))
1047                     break;
1048             }
1049             if (GtkWidget *gtkTreeView = d->gtkWidget("GtkTreeView")) {
1050                 const char *detail = "cell_even_ruled";
1051                 if (vopt && vopt->features & QStyleOptionViewItem::Alternate)
1052                     detail = "cell_odd_ruled";
1053                 bool isActive = option->state & State_Active;
1054                 QString key;
1055                 if (isActive ) {
1056                     // Required for active/non-active window appearance
1057                     key = QLS("a");
1058                     GTK_WIDGET_SET_FLAGS(gtkTreeView, GTK_HAS_FOCUS);
1059                 }
1060                 bool isEnabled = (widget ? widget->isEnabled() : (vopt->state & QStyle::State_Enabled));
1061                 gtkPainter.paintFlatBox(gtkTreeView, detail, option->rect,
1062                                         option->state & State_Selected ? GTK_STATE_SELECTED :
1063                                         isEnabled ? GTK_STATE_NORMAL : GTK_STATE_INSENSITIVE,
1064                                         GTK_SHADOW_OUT, d->gtk_widget_get_style(gtkTreeView), key);
1065                 if (isActive )
1066                     GTK_WIDGET_UNSET_FLAGS(gtkTreeView, GTK_HAS_FOCUS);
1067             }
1068         }
1069         break;
1070     case PE_IndicatorToolBarSeparator:
1071         {
1072             const int margin = 6;
1073             GtkWidget *gtkSeparator = d->gtkWidget("GtkToolbar.GtkSeparatorToolItem");
1074             if (option->state & State_Horizontal) {
1075                 const int offset = option->rect.width()/2;
1076                 QRect rect = option->rect.adjusted(offset, margin, 0, -margin);
1077                 painter->setPen(QPen(option->palette.background().color().darker(110)));
1078                 gtkPainter.paintVline( gtkSeparator, "vseparator",
1079                                        rect, GTK_STATE_NORMAL, d->gtk_widget_get_style(gtkSeparator),
1080                                        0, rect.height(), 0);
1081             } else { //Draw vertical separator
1082                 const int offset = option->rect.height()/2;
1083                 QRect rect = option->rect.adjusted(margin, offset, -margin, 0);
1084                 painter->setPen(QPen(option->palette.background().color().darker(110)));
1085                 gtkPainter.paintHline( gtkSeparator, "hseparator",
1086                                        rect, GTK_STATE_NORMAL, d->gtk_widget_get_style(gtkSeparator),
1087                                        0, rect.width(), 0);
1088             }
1089        }
1090        break;
1091
1092     case PE_IndicatorToolBarHandle: {
1093         GtkWidget *gtkToolbar = d->gtkWidget("GtkToolbar");
1094         GtkShadowType shadow_type;
1095         d->gtk_widget_style_get(gtkToolbar, "shadow-type", &shadow_type, NULL);
1096         //Note when the toolbar is horizontal, the handle is vertical
1097         painter->setClipRect(option->rect);
1098         gtkPainter.paintHandle(gtkToolbar, "toolbar", option->rect.adjusted(-1, -1 ,0 ,1),
1099                                GTK_STATE_NORMAL, shadow_type, !(option->state & State_Horizontal) ?
1100                                GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL, d->gtk_widget_get_style(gtkToolbar));
1101     }
1102     break;
1103
1104     case PE_IndicatorArrowUp:
1105     case PE_IndicatorArrowDown:
1106     case PE_IndicatorArrowLeft:
1107     case PE_IndicatorArrowRight: {
1108
1109
1110         GtkArrowType type = GTK_ARROW_UP;
1111
1112         switch (element) {
1113
1114         case PE_IndicatorArrowDown:
1115             type = GTK_ARROW_DOWN;
1116             break;
1117
1118         case PE_IndicatorArrowLeft:
1119             type = GTK_ARROW_LEFT;
1120             break;
1121
1122         case PE_IndicatorArrowRight:
1123             type = GTK_ARROW_RIGHT;
1124             break;
1125
1126         default:
1127             break;
1128         }
1129         int size = qMin(option->rect.height(), option->rect.width());
1130         int border = (size > 9) ? (size/4) : 0; //Allow small arrows to have exact dimensions
1131         int bsx = 0, bsy = 0;
1132         if (option->state & State_Sunken) {
1133             bsx = proxy()->pixelMetric(PM_ButtonShiftHorizontal);
1134             bsy = proxy()->pixelMetric(PM_ButtonShiftVertical);
1135         }
1136         QRect arrowRect = option->rect.adjusted(border + bsx, border + bsy, -border + bsx, -border + bsy);
1137         GtkShadowType shadow = option->state & State_Sunken ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
1138         GtkStateType state = gtkPainter.gtkState(option);
1139
1140         QColor arrowColor = option->palette.buttonText().color();
1141         GtkWidget *gtkArrow = d->gtkWidget("GtkArrow");
1142         GdkColor color = fromQColor(arrowColor);
1143         d->gtk_widget_modify_fg (gtkArrow, state, &color);
1144         gtkPainter.paintArrow(gtkArrow, "button", arrowRect,
1145                               type, state, shadow, false, d->gtk_widget_get_style(gtkArrow),
1146                               QString::number(arrowColor.rgba(), 16));
1147         // Passing NULL will revert the color change
1148         d->gtk_widget_modify_fg (gtkArrow, state, NULL);
1149     }
1150     break;
1151
1152     case PE_FrameGroupBox:
1153         // Do nothing here, the GNOME groupboxes are flat
1154         break;
1155
1156     case PE_PanelMenu: {
1157             GtkWidget *gtkMenu = d->gtkWidget("GtkMenu");
1158             gtkPainter.setAlphaSupport(false); // Note, alpha disabled for performance reasons
1159             gtkPainter.paintBox(gtkMenu, "menu", option->rect, GTK_STATE_NORMAL, GTK_SHADOW_OUT, d->gtk_widget_get_style(gtkMenu), QString());
1160         }
1161         break;
1162
1163     case PE_FrameMenu:
1164         //This is actually done by PE_Widget due to a clipping issue
1165         //Otherwise Menu items will not be able to span the entire menu width
1166
1167         // This is only used by floating tool bars
1168         if (qobject_cast<const QToolBar *>(widget)) {
1169             GtkWidget *gtkMenubar = d->gtkWidget("GtkMenuBar");
1170             gtkPainter.paintBox( gtkMenubar, "toolbar",  option->rect,
1171                                  GTK_STATE_NORMAL, GTK_SHADOW_OUT, style);
1172             gtkPainter.paintBox( gtkMenubar, "menu",  option->rect,
1173                                  GTK_STATE_NORMAL, GTK_SHADOW_OUT, style);
1174         }
1175         break;
1176
1177     case PE_FrameLineEdit: {
1178         GtkWidget *gtkEntry = d->gtkWidget("GtkEntry");
1179
1180
1181         gboolean interior_focus;
1182         gint focus_line_width;
1183         QRect rect = option->rect;
1184         d->gtk_widget_style_get(gtkEntry,
1185                                "interior-focus", &interior_focus,
1186                                "focus-line-width", &focus_line_width, NULL);
1187
1188         // See https://bugzilla.mozilla.org/show_bug.cgi?id=405421 for info about this hack
1189         g_object_set_data(G_OBJECT(gtkEntry), "transparent-bg-hint", GINT_TO_POINTER(true));
1190
1191         if (!interior_focus && option->state & State_HasFocus)
1192             rect.adjust(focus_line_width, focus_line_width, -focus_line_width, -focus_line_width);
1193
1194         if (option->state & State_HasFocus)
1195             GTK_WIDGET_SET_FLAGS(gtkEntry, GTK_HAS_FOCUS);
1196         gtkPainter.paintShadow(gtkEntry, "entry", rect, option->state & State_Enabled ? 
1197                                GTK_STATE_NORMAL : GTK_STATE_INSENSITIVE, 
1198                                GTK_SHADOW_IN, d->gtk_widget_get_style(gtkEntry),
1199                                option->state & State_HasFocus ? QLS("focus") : QString());
1200         if (!interior_focus && option->state & State_HasFocus)
1201             gtkPainter.paintShadow(gtkEntry, "entry", option->rect, option->state & State_Enabled ? 
1202                                    GTK_STATE_ACTIVE : GTK_STATE_INSENSITIVE,
1203                                    GTK_SHADOW_IN, d->gtk_widget_get_style(gtkEntry), QLS("GtkEntryShadowIn"));
1204
1205         if (option->state & State_HasFocus)
1206             GTK_WIDGET_UNSET_FLAGS(gtkEntry, GTK_HAS_FOCUS);
1207     }
1208     break;
1209
1210     case PE_PanelLineEdit:
1211         if (const QStyleOptionFrame *panel = qstyleoption_cast<const QStyleOptionFrame *>(option)) {
1212             GtkWidget *gtkEntry = d->gtkWidget("GtkEntry");
1213             if (panel->lineWidth > 0)
1214                 proxy()->drawPrimitive(PE_FrameLineEdit, option, painter, widget);
1215             uint resolve_mask = option->palette.resolve();
1216             GtkStyle *gtkEntryStyle = d->gtk_widget_get_style(gtkEntry);
1217             QRect textRect = option->rect.adjusted(gtkEntryStyle->xthickness, gtkEntryStyle->ythickness,
1218                                                    -gtkEntryStyle->xthickness, -gtkEntryStyle->ythickness);
1219
1220             if (widget && widget->testAttribute(Qt::WA_SetPalette) &&
1221                 resolve_mask & (1 << QPalette::Base)) // Palette overridden by user
1222                 painter->fillRect(textRect, option->palette.base());
1223             else
1224                 gtkPainter.paintFlatBox( gtkEntry, "entry_bg", textRect,
1225                                          option->state & State_Enabled ? GTK_STATE_NORMAL : GTK_STATE_INSENSITIVE, GTK_SHADOW_NONE, gtkEntryStyle);
1226         }
1227         break;
1228
1229     case PE_FrameTabWidget:
1230         if (const QStyleOptionTabWidgetFrame *frame = qstyleoption_cast<const QStyleOptionTabWidgetFrame*>(option)) {
1231             GtkWidget *gtkNotebook = d->gtkWidget("GtkNotebook");
1232             style = gtkPainter.getStyle(gtkNotebook);
1233             gtkPainter.setAlphaSupport(false);
1234             GtkShadowType shadow = GTK_SHADOW_OUT;
1235             GtkStateType state = GTK_STATE_NORMAL; // Only state supported by gtknotebook
1236             bool reverse = (option->direction == Qt::RightToLeft);
1237             QGtkStylePrivate::gtk_widget_set_direction(gtkNotebook, reverse ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR);
1238             if (const QStyleOptionTabWidgetFrameV2 *tabframe = qstyleoption_cast<const QStyleOptionTabWidgetFrameV2*>(option)) {
1239                 GtkPositionType frameType = GTK_POS_TOP;
1240                 QTabBar::Shape shape = frame->shape;
1241                 int gapStart = 0;
1242                 int gapSize = 0;
1243                 if (shape == QTabBar::RoundedNorth || shape == QTabBar::RoundedSouth) {
1244                     frameType = (shape == QTabBar::RoundedNorth) ? GTK_POS_TOP : GTK_POS_BOTTOM;
1245                     gapStart = tabframe->selectedTabRect.left();
1246                     gapSize = tabframe->selectedTabRect.width();
1247                 } else {
1248                     frameType = (shape == QTabBar::RoundedWest) ? GTK_POS_LEFT : GTK_POS_RIGHT;
1249                     gapStart = tabframe->selectedTabRect.y();
1250                     gapSize = tabframe->selectedTabRect.height();
1251                 }
1252                 gtkPainter.paintBoxGap(gtkNotebook, "notebook",  option->rect, state, shadow, frameType,
1253                                         gapStart, gapSize, style);
1254                 break; // done
1255             }
1256
1257             // Note this is only the fallback option
1258             gtkPainter.paintBox(gtkNotebook, "notebook",  option->rect, state, shadow, style);
1259         }
1260         break;
1261
1262     case PE_PanelButtonCommand:
1263     case PE_PanelButtonTool: {
1264         bool isDefault = false;
1265         bool isTool = (element == PE_PanelButtonTool);
1266         if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton*>(option))
1267             isDefault = btn->features & QStyleOptionButton::DefaultButton;
1268
1269         // don't draw a frame for tool buttons that have the autoRaise flag and are not enabled or on
1270         if (isTool && !(option->state & State_Enabled || option->state & State_On) && (option->state & State_AutoRaise))
1271             break;
1272         // don't draw a frame for dock widget buttons, unless we are hovering
1273         if (widget && widget->inherits("QDockWidgetTitleButton") && !(option->state & State_MouseOver))
1274             break;
1275
1276         GtkStateType state = gtkPainter.gtkState(option);
1277         if (option->state & State_On || option->state & State_Sunken)
1278             state = GTK_STATE_ACTIVE;
1279         GtkWidget *gtkButton = isTool ? d->gtkWidget("GtkToolButton.GtkButton") : d->gtkWidget("GtkButton");
1280         gint focusWidth, focusPad;
1281         gboolean interiorFocus = false;
1282         d->gtk_widget_style_get (gtkButton,
1283                                 "focus-line-width", &focusWidth,
1284                                 "focus-padding", &focusPad,
1285                                 "interior-focus", &interiorFocus, NULL);
1286
1287         style = d->gtk_widget_get_style(gtkButton);
1288
1289         QRect buttonRect = option->rect;
1290
1291         QString key;
1292         if (isDefault) {
1293             key += QLS("def");
1294             GTK_WIDGET_SET_FLAGS(gtkButton, GTK_HAS_DEFAULT);
1295             gtkPainter.paintBox(gtkButton, "buttondefault", buttonRect, state, GTK_SHADOW_IN,
1296                                 style, isDefault ? QLS("d") : QString());
1297         }
1298
1299         bool hasFocus = option->state & State_HasFocus;
1300
1301         if (hasFocus) {
1302             key += QLS("def");
1303             GTK_WIDGET_SET_FLAGS(gtkButton, GTK_HAS_FOCUS);
1304         }
1305
1306         if (!interiorFocus)
1307             buttonRect = buttonRect.adjusted(focusWidth, focusWidth, -focusWidth, -focusWidth);
1308
1309         GtkShadowType shadow = (option->state & State_Sunken || option->state & State_On ) ?
1310                                GTK_SHADOW_IN : GTK_SHADOW_OUT;
1311
1312         gtkPainter.paintBox(gtkButton, "button", buttonRect, state, shadow,
1313                             style, key);
1314         if (isDefault)
1315             GTK_WIDGET_UNSET_FLAGS(gtkButton, GTK_HAS_DEFAULT);
1316         if (hasFocus)
1317             GTK_WIDGET_UNSET_FLAGS(gtkButton, GTK_HAS_FOCUS);
1318     }
1319     break;
1320
1321     case PE_IndicatorRadioButton: {
1322         GtkShadowType shadow = GTK_SHADOW_OUT;
1323         GtkStateType state = gtkPainter.gtkState(option);
1324
1325         if (option->state & State_Sunken)
1326             state = GTK_STATE_ACTIVE;
1327
1328         if (option->state & State_NoChange)
1329             shadow = GTK_SHADOW_ETCHED_IN;
1330         else if (option->state & State_On)
1331             shadow = GTK_SHADOW_IN;
1332         else
1333             shadow = GTK_SHADOW_OUT;
1334
1335         GtkWidget *gtkRadioButton = d->gtkWidget("GtkRadioButton");
1336         gint spacing;
1337         d->gtk_widget_style_get(gtkRadioButton, "indicator-spacing", &spacing, NULL);
1338         QRect buttonRect = option->rect.adjusted(spacing, spacing, -spacing, -spacing);
1339         gtkPainter.setClipRect(option->rect);
1340         // ### Note: Ubuntulooks breaks when the proper widget is passed
1341         //           Murrine engine requires a widget not to get RGBA check - warnings
1342         GtkWidget *gtkCheckButton = d->gtkWidget("GtkCheckButton");
1343         QString key(QLS("radiobutton"));
1344         if (option->state & State_HasFocus) { // Themes such as Nodoka check this flag
1345             key += QLatin1Char('f');
1346             GTK_WIDGET_SET_FLAGS(gtkCheckButton, GTK_HAS_FOCUS);
1347         }
1348         gtkPainter.paintOption(gtkCheckButton , buttonRect, state, shadow, d->gtk_widget_get_style(gtkRadioButton), key);
1349         if (option->state & State_HasFocus)
1350             GTK_WIDGET_UNSET_FLAGS(gtkCheckButton, GTK_HAS_FOCUS);
1351     }
1352     break;
1353
1354     case PE_IndicatorCheckBox: {
1355         GtkShadowType shadow = GTK_SHADOW_OUT;
1356         GtkStateType state = gtkPainter.gtkState(option);
1357
1358         if (option->state & State_Sunken)
1359             state = GTK_STATE_ACTIVE;
1360
1361         if (option->state & State_NoChange)
1362             shadow = GTK_SHADOW_ETCHED_IN;
1363         else if (option->state & State_On)
1364             shadow = GTK_SHADOW_IN;
1365         else
1366             shadow = GTK_SHADOW_OUT;
1367
1368         int spacing;
1369
1370         GtkWidget *gtkCheckButton = d->gtkWidget("GtkCheckButton");
1371         QString key(QLS("checkbutton"));
1372         if (option->state & State_HasFocus) { // Themes such as Nodoka checks this flag
1373             key += QLatin1Char('f');
1374             GTK_WIDGET_SET_FLAGS(gtkCheckButton, GTK_HAS_FOCUS);
1375         }
1376
1377         // Some styles such as aero-clone assume they can paint in the spacing area
1378         gtkPainter.setClipRect(option->rect);
1379
1380         d->gtk_widget_style_get(gtkCheckButton, "indicator-spacing", &spacing, NULL);
1381
1382         QRect checkRect = option->rect.adjusted(spacing, spacing, -spacing, -spacing);
1383
1384         gtkPainter.paintCheckbox(gtkCheckButton, checkRect, state, shadow, d->gtk_widget_get_style(gtkCheckButton),
1385                                  key);
1386         if (option->state & State_HasFocus)
1387             GTK_WIDGET_UNSET_FLAGS(gtkCheckButton, GTK_HAS_FOCUS);
1388
1389     }
1390     break;
1391
1392 #ifndef QT_NO_TABBAR
1393
1394     case PE_FrameTabBarBase:
1395         if (const QStyleOptionTabBarBase *tbb
1396                 = qstyleoption_cast<const QStyleOptionTabBarBase *>(option)) {
1397             QRect tabRect = tbb->rect;
1398             painter->save();
1399             painter->setPen(QPen(option->palette.dark().color().dark(110), 0));
1400             switch (tbb->shape) {
1401
1402             case QTabBar::RoundedNorth:
1403                 painter->drawLine(tabRect.topLeft(), tabRect.topRight());
1404                 break;
1405
1406             case QTabBar::RoundedWest:
1407                 painter->drawLine(tabRect.left(), tabRect.top(), tabRect.left(), tabRect.bottom());
1408                 break;
1409
1410             case QTabBar::RoundedSouth:
1411                 painter->drawLine(tbb->rect.left(), tbb->rect.bottom(),
1412                                   tabRect.right(), tabRect.bottom());
1413                 break;
1414
1415             case QTabBar::RoundedEast:
1416                 painter->drawLine(tabRect.topRight(), tabRect.bottomRight());
1417                 break;
1418
1419             case QTabBar::TriangularNorth:
1420             case QTabBar::TriangularEast:
1421             case QTabBar::TriangularWest:
1422             case QTabBar::TriangularSouth:
1423                 painter->restore();
1424                 QWindowsStyle::drawPrimitive(element, option, painter, widget);
1425                 return;
1426             }
1427
1428             painter->restore();
1429         }
1430         return;
1431
1432 #endif // QT_NO_TABBAR
1433
1434     case PE_Widget:
1435         break;
1436
1437     default:
1438         QWindowsStyle::drawPrimitive(element, option, painter, widget);
1439     }
1440 }
1441
1442 /*!
1443     \reimp
1444 */
1445 void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionComplex *option,
1446
1447                                    QPainter *painter, const QWidget *widget) const
1448 {
1449     Q_D(const QGtkStyle);
1450
1451     if (!d->isThemeAvailable()) {
1452         QWindowsStyle::drawComplexControl(control, option, painter, widget);
1453         return;
1454     }
1455
1456     GtkStyle* style = d->gtkStyle();
1457     QGtkPainter gtkPainter(painter);
1458     QColor button = option->palette.button().color();
1459     QColor dark;
1460     QColor grooveColor;
1461     QColor darkOutline;
1462     dark.setHsv(button.hue(),
1463                 qMin(255, (int)(button.saturation()*1.9)),
1464                 qMin(255, (int)(button.value()*0.7)));
1465     grooveColor.setHsv(button.hue(),
1466                        qMin(255, (int)(button.saturation()*2.6)),
1467                        qMin(255, (int)(button.value()*0.9)));
1468     darkOutline.setHsv(button.hue(),
1469                        qMin(255, (int)(button.saturation()*3.0)),
1470                        qMin(255, (int)(button.value()*0.6)));
1471
1472     QColor alphaCornerColor;
1473
1474     if (widget)
1475         alphaCornerColor = mergedColors(option->palette.color(widget->backgroundRole()), darkOutline);
1476     else
1477         alphaCornerColor = mergedColors(option->palette.background().color(), darkOutline);
1478
1479     switch (control) {
1480
1481     case CC_TitleBar:
1482         painter->save();
1483         if (const QStyleOptionTitleBar *titleBar = qstyleoption_cast<const QStyleOptionTitleBar *>(option)) {
1484             // Since this is drawn by metacity and not Gtk we
1485             // have to do custom drawing
1486
1487             GdkColor gdkBg = style->bg[GTK_STATE_SELECTED];
1488             QColor bgColor(gdkBg.red>>8, gdkBg.green>>8, gdkBg.blue>>8);
1489
1490             const int buttonMargin = 5;
1491             bool active = (titleBar->titleBarState & State_Active);
1492             QRect fullRect = titleBar->rect;
1493             QPalette palette = option->palette;
1494             QColor highlight = bgColor;
1495
1496             QColor titleBarFrameBorder(active ? highlight.darker(180): dark.darker(110));
1497             QColor titleBarHighlight(active ? highlight.lighter(120): palette.background().color().lighter(120));
1498             QColor textColor(active ? 0xffffff : 0xff000000);
1499             QColor textAlphaColor(active ? 0xffffff : 0xff000000 );
1500
1501             {
1502                 // Fill title bar gradient
1503                 QColor titlebarColor = QColor(active ? highlight: palette.background().color());
1504                 QLinearGradient gradient(option->rect.center().x(), option->rect.top(),
1505                                          option->rect.center().x(), option->rect.bottom());
1506
1507                 gradient.setColorAt(0, titlebarColor.lighter(114));
1508                 gradient.setColorAt(0.5, titlebarColor.lighter(102));
1509                 gradient.setColorAt(0.51, titlebarColor.darker(104));
1510                 gradient.setColorAt(1, titlebarColor);
1511                 painter->fillRect(option->rect.adjusted(1, 1, -1, 0), gradient);
1512
1513                 // Frame and rounded corners
1514                 painter->setPen(titleBarFrameBorder);
1515
1516                 // top outline
1517                 painter->drawLine(fullRect.left() + 5, fullRect.top(), fullRect.right() - 5, fullRect.top());
1518                 painter->drawLine(fullRect.left(), fullRect.top() + 4, fullRect.left(), fullRect.bottom());
1519                 const QPoint points[5] = {
1520                     QPoint(fullRect.left() + 4, fullRect.top() + 1),
1521                     QPoint(fullRect.left() + 3, fullRect.top() + 1),
1522                     QPoint(fullRect.left() + 2, fullRect.top() + 2),
1523                     QPoint(fullRect.left() + 1, fullRect.top() + 3),
1524                     QPoint(fullRect.left() + 1, fullRect.top() + 4)
1525                 };
1526                 painter->drawPoints(points, 5);
1527
1528                 painter->drawLine(fullRect.right(), fullRect.top() + 4, fullRect.right(), fullRect.bottom());
1529                 const QPoint points2[5] = {
1530                     QPoint(fullRect.right() - 3, fullRect.top() + 1),
1531                     QPoint(fullRect.right() - 4, fullRect.top() + 1),
1532                     QPoint(fullRect.right() - 2, fullRect.top() + 2),
1533                     QPoint(fullRect.right() - 1, fullRect.top() + 3),
1534                     QPoint(fullRect.right() - 1, fullRect.top() + 4)
1535                 };
1536                 painter->drawPoints(points2, 5);
1537
1538                 // draw bottomline
1539                 painter->drawLine(fullRect.right(), fullRect.bottom(), fullRect.left(), fullRect.bottom());
1540
1541                 // top highlight
1542                 painter->setPen(titleBarHighlight);
1543                 painter->drawLine(fullRect.left() + 6, fullRect.top() + 1, fullRect.right() - 6, fullRect.top() + 1);
1544             }
1545             // draw title
1546             QRect textRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarLabel, widget);
1547             QFont font = painter->font();
1548             font.setBold(true);
1549             painter->setFont(font);
1550             painter->setPen(active? (titleBar->palette.text().color().lighter(120)) :
1551                                      titleBar->palette.text().color() );
1552             // Note workspace also does elliding but it does not use the correct font
1553             QString title = QFontMetrics(font).elidedText(titleBar->text, Qt::ElideRight, textRect.width() - 14);
1554             painter->drawText(textRect.adjusted(1, 1, 1, 1), title, QTextOption(Qt::AlignHCenter | Qt::AlignVCenter));
1555             painter->setPen(Qt::white);
1556             if (active)
1557                 painter->drawText(textRect, title, QTextOption(Qt::AlignHCenter | Qt::AlignVCenter));
1558             // min button
1559             if ((titleBar->subControls & SC_TitleBarMinButton) && (titleBar->titleBarFlags & Qt::WindowMinimizeButtonHint) &&
1560                 !(titleBar->titleBarState& Qt::WindowMinimized)) {
1561                 QRect minButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarMinButton, widget);
1562                 if (minButtonRect.isValid()) {
1563                     bool hover = (titleBar->activeSubControls & SC_TitleBarMinButton) && (titleBar->state & State_MouseOver);
1564                     bool sunken = (titleBar->activeSubControls & SC_TitleBarMinButton) && (titleBar->state & State_Sunken);
1565                     qt_gtk_draw_mdibutton(painter, titleBar, minButtonRect, hover, sunken);
1566                     QRect minButtonIconRect = minButtonRect.adjusted(buttonMargin ,buttonMargin , -buttonMargin, -buttonMargin);
1567                     painter->setPen(textColor);
1568                     painter->drawLine(minButtonIconRect.center().x() - 2, minButtonIconRect.center().y() + 3,
1569                                     minButtonIconRect.center().x() + 3, minButtonIconRect.center().y() + 3);
1570                     painter->drawLine(minButtonIconRect.center().x() - 2, minButtonIconRect.center().y() + 4,
1571                                     minButtonIconRect.center().x() + 3, minButtonIconRect.center().y() + 4);
1572                     painter->setPen(textAlphaColor);
1573                     painter->drawLine(minButtonIconRect.center().x() - 3, minButtonIconRect.center().y() + 3,
1574                                     minButtonIconRect.center().x() - 3, minButtonIconRect.center().y() + 4);
1575                     painter->drawLine(minButtonIconRect.center().x() + 4, minButtonIconRect.center().y() + 3,
1576                                     minButtonIconRect.center().x() + 4, minButtonIconRect.center().y() + 4);
1577                 }
1578             }
1579             // max button
1580             if ((titleBar->subControls & SC_TitleBarMaxButton) && (titleBar->titleBarFlags & Qt::WindowMaximizeButtonHint) &&
1581                 !(titleBar->titleBarState & Qt::WindowMaximized)) {
1582                 QRect maxButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarMaxButton, widget);
1583                 if (maxButtonRect.isValid()) {
1584                     bool hover = (titleBar->activeSubControls & SC_TitleBarMaxButton) && (titleBar->state & State_MouseOver);
1585                     bool sunken = (titleBar->activeSubControls & SC_TitleBarMaxButton) && (titleBar->state & State_Sunken);
1586                     qt_gtk_draw_mdibutton(painter, titleBar, maxButtonRect, hover, sunken);
1587
1588                     QRect maxButtonIconRect = maxButtonRect.adjusted(buttonMargin, buttonMargin, -buttonMargin, -buttonMargin);
1589
1590                     painter->setPen(textColor);
1591                     painter->drawRect(maxButtonIconRect.adjusted(0, 0, -1, -1));
1592                     painter->drawLine(maxButtonIconRect.left() + 1, maxButtonIconRect.top() + 1,
1593                                     maxButtonIconRect.right() - 1, maxButtonIconRect.top() + 1);
1594                     painter->setPen(textAlphaColor);
1595                     const QPoint points[4] = {
1596                         maxButtonIconRect.topLeft(),
1597                         maxButtonIconRect.topRight(),
1598                         maxButtonIconRect.bottomLeft(),
1599                         maxButtonIconRect.bottomRight()
1600                     };
1601                     painter->drawPoints(points, 4);
1602                 }
1603             }
1604
1605             // close button
1606             if ((titleBar->subControls & SC_TitleBarCloseButton) && (titleBar->titleBarFlags & Qt::WindowSystemMenuHint)) {
1607                 QRect closeButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarCloseButton, widget);
1608                 if (closeButtonRect.isValid()) {
1609                     bool hover = (titleBar->activeSubControls & SC_TitleBarCloseButton) && (titleBar->state & State_MouseOver);
1610                     bool sunken = (titleBar->activeSubControls & SC_TitleBarCloseButton) && (titleBar->state & State_Sunken);
1611                     qt_gtk_draw_mdibutton(painter, titleBar, closeButtonRect, hover, sunken);
1612                     QRect closeIconRect = closeButtonRect.adjusted(buttonMargin, buttonMargin, -buttonMargin, -buttonMargin);
1613                     painter->setPen(textAlphaColor);
1614                     const QLine lines[4] = {
1615                         QLine(closeIconRect.left() + 1, closeIconRect.top(),
1616                               closeIconRect.right(), closeIconRect.bottom() - 1),
1617                         QLine(closeIconRect.left(), closeIconRect.top() + 1,
1618                               closeIconRect.right() - 1, closeIconRect.bottom()),
1619                         QLine(closeIconRect.right() - 1, closeIconRect.top(),
1620                               closeIconRect.left(), closeIconRect.bottom() - 1),
1621                         QLine(closeIconRect.right(), closeIconRect.top() + 1,
1622                               closeIconRect.left() + 1, closeIconRect.bottom())
1623                     };
1624                     painter->drawLines(lines, 4);
1625                     const QPoint points[4] = {
1626                         closeIconRect.topLeft(),
1627                         closeIconRect.topRight(),
1628                         closeIconRect.bottomLeft(),
1629                         closeIconRect.bottomRight()
1630                     };
1631                     painter->drawPoints(points, 4);
1632
1633                     painter->setPen(textColor);
1634                     painter->drawLine(closeIconRect.left() + 1, closeIconRect.top() + 1,
1635                                     closeIconRect.right() - 1, closeIconRect.bottom() - 1);
1636                     painter->drawLine(closeIconRect.left() + 1, closeIconRect.bottom() - 1,
1637                                     closeIconRect.right() - 1, closeIconRect.top() + 1);
1638                 }
1639             }
1640
1641             // normalize button
1642             if ((titleBar->subControls & SC_TitleBarNormalButton) &&
1643                (((titleBar->titleBarFlags & Qt::WindowMinimizeButtonHint) &&
1644                (titleBar->titleBarState & Qt::WindowMinimized)) ||
1645                ((titleBar->titleBarFlags & Qt::WindowMaximizeButtonHint) &&
1646                (titleBar->titleBarState & Qt::WindowMaximized)))) {
1647                 QRect normalButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarNormalButton, widget);
1648                 if (normalButtonRect.isValid()) {
1649
1650                     bool hover = (titleBar->activeSubControls & SC_TitleBarNormalButton) && (titleBar->state & State_MouseOver);
1651                     bool sunken = (titleBar->activeSubControls & SC_TitleBarNormalButton) && (titleBar->state & State_Sunken);
1652                     QRect normalButtonIconRect = normalButtonRect.adjusted(buttonMargin, buttonMargin, -buttonMargin, -buttonMargin);
1653                     qt_gtk_draw_mdibutton(painter, titleBar, normalButtonRect, hover, sunken);
1654
1655                     QRect frontWindowRect = normalButtonIconRect.adjusted(0, 3, -3, 0);
1656                     painter->setPen(textColor);
1657                     painter->drawRect(frontWindowRect.adjusted(0, 0, -1, -1));
1658                     painter->drawLine(frontWindowRect.left() + 1, frontWindowRect.top() + 1,
1659                                     frontWindowRect.right() - 1, frontWindowRect.top() + 1);
1660                     painter->setPen(textAlphaColor);
1661                     const QPoint points[4] = {
1662                         frontWindowRect.topLeft(),
1663                         frontWindowRect.topRight(),
1664                         frontWindowRect.bottomLeft(),
1665                         frontWindowRect.bottomRight()
1666                     };
1667                     painter->drawPoints(points, 4);
1668
1669                     QRect backWindowRect = normalButtonIconRect.adjusted(3, 0, 0, -3);
1670                     QRegion clipRegion = backWindowRect;
1671                     clipRegion -= frontWindowRect;
1672                     painter->save();
1673                     painter->setClipRegion(clipRegion);
1674                     painter->setPen(textColor);
1675                     painter->drawRect(backWindowRect.adjusted(0, 0, -1, -1));
1676                     painter->drawLine(backWindowRect.left() + 1, backWindowRect.top() + 1,
1677                                     backWindowRect.right() - 1, backWindowRect.top() + 1);
1678                     painter->setPen(textAlphaColor);
1679                     const QPoint points2[4] = {
1680                         backWindowRect.topLeft(),
1681                         backWindowRect.topRight(),
1682                         backWindowRect.bottomLeft(),
1683                         backWindowRect.bottomRight()
1684                     };
1685                     painter->drawPoints(points2, 4);
1686                     painter->restore();
1687                 }
1688             }
1689
1690             // context help button
1691             if (titleBar->subControls & SC_TitleBarContextHelpButton
1692                 && (titleBar->titleBarFlags & Qt::WindowContextHelpButtonHint)) {
1693                 QRect contextHelpButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarContextHelpButton, widget);
1694                 if (contextHelpButtonRect.isValid()) {
1695                     bool hover = (titleBar->activeSubControls & SC_TitleBarContextHelpButton) && (titleBar->state & State_MouseOver);
1696                     bool sunken = (titleBar->activeSubControls & SC_TitleBarContextHelpButton) && (titleBar->state & State_Sunken);
1697                     qt_gtk_draw_mdibutton(painter, titleBar, contextHelpButtonRect, hover, sunken);
1698
1699                     QColor blend;
1700                     QImage image(qt_titlebar_context_help);
1701                     QColor alpha = textColor;
1702                     alpha.setAlpha(128);
1703                     image.setColor(1, textColor.rgba());
1704                     image.setColor(2, alpha.rgba());
1705                     painter->setRenderHint(QPainter::SmoothPixmapTransform);
1706                     painter->drawImage(contextHelpButtonRect.adjusted(4, 4, -4, -4), image);
1707                 }
1708             }
1709
1710             // shade button
1711             if (titleBar->subControls & SC_TitleBarShadeButton && (titleBar->titleBarFlags & Qt::WindowShadeButtonHint)) {
1712                 QRect shadeButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarShadeButton, widget);
1713                 if (shadeButtonRect.isValid()) {
1714                     bool hover = (titleBar->activeSubControls & SC_TitleBarShadeButton) && (titleBar->state & State_MouseOver);
1715                     bool sunken = (titleBar->activeSubControls & SC_TitleBarShadeButton) && (titleBar->state & State_Sunken);
1716                     qt_gtk_draw_mdibutton(painter, titleBar, shadeButtonRect, hover, sunken);
1717                     QImage image(qt_scrollbar_button_arrow_up);
1718                     image.setColor(1, textColor.rgba());
1719                     painter->drawImage(shadeButtonRect.adjusted(5, 7, -5, -7), image);
1720                 }
1721             }
1722
1723             // unshade button
1724             if (titleBar->subControls & SC_TitleBarUnshadeButton && (titleBar->titleBarFlags & Qt::WindowShadeButtonHint)) {
1725                 QRect unshadeButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarUnshadeButton, widget);
1726                 if (unshadeButtonRect.isValid()) {
1727                     bool hover = (titleBar->activeSubControls & SC_TitleBarUnshadeButton) && (titleBar->state & State_MouseOver);
1728                     bool sunken = (titleBar->activeSubControls & SC_TitleBarUnshadeButton) && (titleBar->state & State_Sunken);
1729                     qt_gtk_draw_mdibutton(painter, titleBar, unshadeButtonRect, hover, sunken);
1730                     QImage image(qt_scrollbar_button_arrow_down);
1731                     image.setColor(1, textColor.rgba());
1732                     painter->drawImage(unshadeButtonRect.adjusted(5, 7, -5, -7), image);
1733                 }
1734             }
1735
1736             if ((titleBar->subControls & SC_TitleBarSysMenu) && (titleBar->titleBarFlags & Qt::WindowSystemMenuHint)) {
1737                 QRect iconRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarSysMenu, widget);
1738                 if (iconRect.isValid()) {
1739                     if (!titleBar->icon.isNull()) {
1740                         titleBar->icon.paint(painter, iconRect);
1741                     } else {
1742                         QStyleOption tool(0);
1743                         tool.palette = titleBar->palette;
1744                         QPixmap pm = standardIcon(SP_TitleBarMenuButton, &tool, widget).pixmap(16, 16);
1745                         tool.rect = iconRect;
1746                         painter->save();
1747                         proxy()->drawItemPixmap(painter, iconRect, Qt::AlignCenter, pm);
1748                         painter->restore();
1749                     }
1750                 }
1751             }
1752         }
1753         painter->restore();
1754         break;
1755
1756 #ifndef QT_NO_GROUPBOX
1757
1758     case CC_GroupBox:
1759         painter->save();
1760
1761         if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast<const QStyleOptionGroupBox *>(option)) {
1762             QRect textRect = proxy()->subControlRect(CC_GroupBox, groupBox, SC_GroupBoxLabel, widget);
1763             QRect checkBoxRect = proxy()->subControlRect(CC_GroupBox, groupBox, SC_GroupBoxCheckBox, widget);
1764             // Draw title
1765
1766             if ((groupBox->subControls & QStyle::SC_GroupBoxLabel) && !groupBox->text.isEmpty()) {
1767                 // Draw prelight background
1768                 GtkWidget *gtkCheckButton = d->gtkWidget("GtkCheckButton");
1769
1770                 if (option->state & State_MouseOver) {
1771                     QRect bgRect = textRect | checkBoxRect;
1772                     gtkPainter.paintFlatBox(gtkCheckButton, "checkbutton", bgRect.adjusted(0, 0, 0, -2),
1773                                             GTK_STATE_PRELIGHT, GTK_SHADOW_ETCHED_OUT, d->gtk_widget_get_style(gtkCheckButton));
1774                 }
1775
1776                 if (!groupBox->text.isEmpty()) {
1777                     int alignment = int(groupBox->textAlignment);
1778                     if (!proxy()->styleHint(QStyle::SH_UnderlineShortcut, option, widget))
1779                         alignment |= Qt::TextHideMnemonic;
1780                     QColor textColor = groupBox->textColor; // Note: custom textColor is currently ignored
1781                     int labelState = GTK_STATE_INSENSITIVE;
1782
1783                     if (option->state & State_Enabled)
1784                         labelState = (option->state & State_MouseOver) ? GTK_STATE_PRELIGHT : GTK_STATE_NORMAL;
1785
1786                     GdkColor gdkText = d->gtk_widget_get_style(gtkCheckButton)->fg[labelState];
1787                     textColor = QColor(gdkText.red>>8, gdkText.green>>8, gdkText.blue>>8);
1788                     painter->setPen(textColor);
1789                     QFont font = painter->font();
1790                     font.setBold(true);
1791                     painter->setFont(font);
1792                     painter->drawText(textRect, Qt::TextShowMnemonic | Qt::AlignLeft| alignment, groupBox->text);
1793
1794                     if (option->state & State_HasFocus)
1795                         gtkPainter.paintFocus(gtkCheckButton, "checkbutton", textRect.adjusted(-4, -1, 0, -3), GTK_STATE_ACTIVE, style);
1796                 }
1797             }
1798
1799             if (groupBox->subControls & SC_GroupBoxCheckBox) {
1800                 QStyleOptionButton box;
1801                 box.QStyleOption::operator=(*groupBox);
1802                 box.rect = checkBoxRect;
1803                 proxy()->drawPrimitive(PE_IndicatorCheckBox, &box, painter, widget);
1804             }
1805         }
1806
1807         painter->restore();
1808         break;
1809 #endif // QT_NO_GROUPBOX
1810
1811 #ifndef QT_NO_COMBOBOX
1812
1813     case CC_ComboBox:
1814         // See: http://live.gnome.org/GnomeArt/Tutorials/GtkThemes/GtkComboBox
1815         // and http://live.gnome.org/GnomeArt/Tutorials/GtkThemes/GtkComboBoxEntry
1816         if (const QStyleOptionComboBox *comboBox = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
1817             bool sunken = comboBox->state & State_On; // play dead, if combobox has no items
1818             BEGIN_STYLE_PIXMAPCACHE(QString::fromLatin1("cb-%0-%1").arg(sunken).arg(comboBox->editable));
1819             QGtkPainter gtkCachedPainter(p);
1820             gtkCachedPainter.setUsePixmapCache(false); // cached externally
1821
1822             bool isEnabled = (comboBox->state & State_Enabled);
1823             bool focus = isEnabled && (comboBox->state & State_HasFocus);
1824             GtkStateType state = gtkPainter.gtkState(option);
1825             int appears_as_list = !proxy()->styleHint(QStyle::SH_ComboBox_Popup, comboBox, widget);
1826             QStyleOptionComboBox comboBoxCopy = *comboBox;
1827             comboBoxCopy.rect = option->rect;
1828
1829             bool reverse = (option->direction == Qt::RightToLeft);
1830             QRect rect = option->rect;
1831             QRect arrowButtonRect = proxy()->subControlRect(CC_ComboBox, &comboBoxCopy,
1832                                                    SC_ComboBoxArrow, widget);
1833
1834             GtkShadowType shadow = (option->state & State_Sunken || option->state & State_On ) ?
1835                                    GTK_SHADOW_IN : GTK_SHADOW_OUT;
1836             const QHashableLatin1Literal comboBoxPath = comboBox->editable ? QHashableLatin1Literal("GtkComboBoxEntry") : QHashableLatin1Literal("GtkComboBox");
1837
1838             // We use the gtk widget to position arrows and separators for us
1839             GtkWidget *gtkCombo = d->gtkWidget(comboBoxPath);
1840             GtkAllocation geometry = {0, 0, option->rect.width(), option->rect.height()};
1841             d->gtk_widget_set_direction(gtkCombo, reverse ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR);
1842             d->gtk_widget_size_allocate(gtkCombo, &geometry);
1843
1844             QHashableLatin1Literal buttonPath = comboBox->editable ? QHashableLatin1Literal("GtkComboBoxEntry.GtkToggleButton")
1845                                 : QHashableLatin1Literal("GtkComboBox.GtkToggleButton");
1846             GtkWidget *gtkToggleButton = d->gtkWidget(buttonPath);
1847             d->gtk_widget_set_direction(gtkToggleButton, reverse ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR);
1848             if (gtkToggleButton && (appears_as_list || comboBox->editable)) {
1849                 if (focus)
1850                     GTK_WIDGET_SET_FLAGS(gtkToggleButton, GTK_HAS_FOCUS);
1851                 // Draw the combo box as a line edit with a button next to it
1852                 if (comboBox->editable || appears_as_list) {
1853                     GtkStateType frameState = (state == GTK_STATE_PRELIGHT) ? GTK_STATE_NORMAL : state;
1854                     QHashableLatin1Literal entryPath = comboBox->editable ? QHashableLatin1Literal("GtkComboBoxEntry.GtkEntry") : QHashableLatin1Literal("GtkComboBox.GtkFrame");
1855                     GtkWidget *gtkEntry = d->gtkWidget(entryPath);
1856                     d->gtk_widget_set_direction(gtkEntry, reverse ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR);
1857                     QRect frameRect = option->rect;
1858
1859                     if (reverse)
1860                         frameRect.setLeft(arrowButtonRect.right());
1861                     else
1862                         frameRect.setRight(arrowButtonRect.left());
1863
1864                     // Fill the line edit background
1865                     // We could have used flat_box with "entry_bg" but that is probably not worth the overhead
1866                     uint resolve_mask = option->palette.resolve();
1867                     GtkStyle *gtkEntryStyle = d->gtk_widget_get_style(gtkEntry);
1868                     QRect contentRect = frameRect.adjusted(gtkEntryStyle->xthickness, gtkEntryStyle->ythickness,
1869                                                            -gtkEntryStyle->xthickness, -gtkEntryStyle->ythickness);
1870                     // Required for inner blue highlight with clearlooks
1871                     if (focus)
1872                         GTK_WIDGET_SET_FLAGS(gtkEntry, GTK_HAS_FOCUS);
1873
1874                     if (widget && widget->testAttribute(Qt::WA_SetPalette) &&
1875                         resolve_mask & (1 << QPalette::Base)) // Palette overridden by user
1876                         p->fillRect(contentRect, option->palette.base().color());
1877                     else {
1878                         gtkCachedPainter.paintFlatBox(gtkEntry, "entry_bg", contentRect,
1879                                                 option->state & State_Enabled ? GTK_STATE_NORMAL : GTK_STATE_INSENSITIVE,
1880                                                 GTK_SHADOW_NONE, gtkEntryStyle, entryPath.toString() + QString::number(focus));
1881                     }
1882
1883                     gtkCachedPainter.paintShadow(gtkEntry, comboBox->editable ? "entry" : "frame", frameRect, frameState,
1884                                            GTK_SHADOW_IN, gtkEntryStyle, entryPath.toString() +
1885                                            QString::number(focus) + QString::number(comboBox->editable) +
1886                                            QString::number(option->direction));
1887                     if (focus)
1888                         GTK_WIDGET_UNSET_FLAGS(gtkEntry, GTK_HAS_FOCUS);
1889                 }
1890
1891                 GtkStateType buttonState = GTK_STATE_NORMAL;
1892
1893                 if (!(option->state & State_Enabled))
1894                     buttonState = GTK_STATE_INSENSITIVE;
1895                 else if (option->state & State_Sunken || option->state & State_On)
1896                     buttonState = GTK_STATE_ACTIVE;
1897                 else if (option->state & State_MouseOver && comboBox->activeSubControls & SC_ComboBoxArrow)
1898                     buttonState = GTK_STATE_PRELIGHT;
1899
1900                 Q_ASSERT(gtkToggleButton);
1901                 gtkCachedPainter.paintBox( gtkToggleButton, "button", arrowButtonRect, buttonState,
1902                                      shadow, d->gtk_widget_get_style(gtkToggleButton), buttonPath.toString() +
1903                                      QString::number(focus) + QString::number(option->direction));
1904                 if (focus)
1905                     GTK_WIDGET_UNSET_FLAGS(gtkToggleButton, GTK_HAS_FOCUS);
1906             } else {
1907                 // Draw combo box as a button
1908                 QRect buttonRect = option->rect;
1909                 GtkStyle *gtkToggleButtonStyle = d->gtk_widget_get_style(gtkToggleButton);
1910
1911                 if (focus) // Clearlooks actually check the widget for the default state
1912                     GTK_WIDGET_SET_FLAGS(gtkToggleButton, GTK_HAS_FOCUS);
1913                 gtkCachedPainter.paintBox(gtkToggleButton, "button",
1914                                     buttonRect, state,
1915                                     shadow, gtkToggleButtonStyle,
1916                                     buttonPath.toString() + QString::number(focus));
1917                 if (focus)
1918                     GTK_WIDGET_UNSET_FLAGS(gtkToggleButton, GTK_HAS_FOCUS);
1919
1920
1921                 // Draw the separator between label and arrows
1922                 QHashableLatin1Literal vSeparatorPath = comboBox->editable
1923                     ? QHashableLatin1Literal("GtkComboBoxEntry.GtkToggleButton.GtkHBox.GtkVSeparator")
1924                     : QHashableLatin1Literal("GtkComboBox.GtkToggleButton.GtkHBox.GtkVSeparator");
1925
1926                 if (GtkWidget *gtkVSeparator = d->gtkWidget(vSeparatorPath)) {
1927                     GtkAllocation allocation;
1928                     d->gtk_widget_get_allocation(gtkVSeparator, &allocation);
1929                     QRect vLineRect(allocation.x, allocation.y, allocation.width, allocation.height);
1930
1931                     gtkCachedPainter.paintVline( gtkVSeparator, "vseparator",
1932                                            vLineRect, state, d->gtk_widget_get_style(gtkVSeparator),
1933                                            0, vLineRect.height(), 0,  vSeparatorPath.toString());
1934
1935
1936                     gint interiorFocus = true;
1937                     d->gtk_widget_style_get(gtkToggleButton, "interior-focus", &interiorFocus, NULL);
1938                     GtkStyle *gtkToggleButtonStyle = gtkToggleButtonStyle;
1939                     int xt = interiorFocus ? gtkToggleButtonStyle->xthickness : 0;
1940                     int yt = interiorFocus ? gtkToggleButtonStyle->ythickness : 0;
1941                     if (focus && ((option->state & State_KeyboardFocusChange) || styleHint(SH_UnderlineShortcut, option, widget)))
1942                         gtkCachedPainter.paintFocus(gtkToggleButton, "button",
1943                                               option->rect.adjusted(xt, yt, -xt, -yt),
1944                                               option->state & State_Sunken ? GTK_STATE_ACTIVE : GTK_STATE_NORMAL,
1945                                               gtkToggleButtonStyle);
1946                 }
1947             }
1948
1949             if (comboBox->subControls & SC_ComboBoxArrow) {
1950                 if (!isEnabled)
1951                     state = GTK_STATE_INSENSITIVE;
1952                 else if (sunken)
1953                     state = GTK_STATE_ACTIVE;
1954                 else if (option->state & State_MouseOver)
1955                     state = GTK_STATE_PRELIGHT;
1956                 else
1957                     state = GTK_STATE_NORMAL;
1958
1959                 QHashableLatin1Literal arrowPath("");
1960                 if (comboBox->editable) {
1961                     if (appears_as_list)
1962                         arrowPath = QHashableLatin1Literal("GtkComboBoxEntry.GtkToggleButton.GtkArrow");
1963                     else
1964                         arrowPath = QHashableLatin1Literal("GtkComboBoxEntry.GtkToggleButton.GtkHBox.GtkArrow");
1965                 } else {
1966                     if (appears_as_list)
1967                         arrowPath = QHashableLatin1Literal("GtkComboBox.GtkToggleButton.GtkArrow");
1968                     else
1969                         arrowPath = QHashableLatin1Literal("GtkComboBox.GtkToggleButton.GtkHBox.GtkArrow");
1970                 }
1971
1972                 GtkWidget *gtkArrow = d->gtkWidget(arrowPath);
1973                 gfloat scale = 0.7;
1974                 gint minSize = 15;
1975                 QRect arrowWidgetRect;
1976
1977                 if (gtkArrow && !d->gtk_check_version(2, 12, 0)) {
1978                     d->gtk_widget_style_get(gtkArrow, "arrow-scaling", &scale, NULL);
1979                     d->gtk_widget_style_get(gtkCombo, "arrow-size", &minSize, NULL);
1980                 }
1981                 if (gtkArrow) {
1982                     GtkAllocation allocation;
1983                     d->gtk_widget_get_allocation(gtkArrow, &allocation);
1984                     arrowWidgetRect = QRect(allocation.x, allocation.y, allocation.width, allocation.height);
1985                     style = d->gtk_widget_get_style(gtkArrow);
1986                 }
1987
1988                 // Note that for some reason the arrow-size is not properly respected with Hildon
1989                 // Hence we enforce the minimum "arrow-size" ourselves
1990                 int arrowSize = qMax(qMin(rect.height() - d->gtk_widget_get_style(gtkCombo)->ythickness * 2, minSize),
1991                                      qMin(arrowWidgetRect.width(), arrowWidgetRect.height()));
1992                 QRect arrowRect(0, 0, static_cast<int>(arrowSize * scale), static_cast<int>(arrowSize * scale));
1993
1994                 arrowRect.moveCenter(arrowWidgetRect.center());
1995
1996                 if (sunken) {
1997                     int xoff, yoff;
1998                     const QHashableLatin1Literal toggleButtonPath = comboBox->editable
1999                             ? QHashableLatin1Literal("GtkComboBoxEntry.GtkToggleButton")
2000                             : QHashableLatin1Literal("GtkComboBox.GtkToggleButton");
2001
2002                     GtkWidget *gtkButton = d->gtkWidget(toggleButtonPath);
2003                     d->gtk_widget_style_get(gtkButton, "child-displacement-x", &xoff, NULL);
2004                     d->gtk_widget_style_get(gtkButton, "child-displacement-y", &yoff, NULL);
2005                     arrowRect = arrowRect.adjusted(xoff, yoff, xoff, yoff);
2006                 }
2007
2008                 // Some styles such as Nimbus paint outside the arrowRect
2009                 // hence we have provide the whole widget as the cliprect
2010                 if (gtkArrow) {
2011                     gtkCachedPainter.setClipRect(option->rect);
2012                     gtkCachedPainter.paintArrow( gtkArrow, "arrow", arrowRect,
2013                                            GTK_ARROW_DOWN, state, GTK_SHADOW_NONE, true,
2014                                            style, arrowPath.toString() + QString::number(option->direction));
2015                 }
2016             }
2017             END_STYLE_PIXMAPCACHE;
2018         }
2019         break;
2020 #endif // QT_NO_COMBOBOX
2021 #ifndef QT_NO_TOOLBUTTON
2022
2023     case CC_ToolButton:
2024         if (const QStyleOptionToolButton *toolbutton
2025                 = qstyleoption_cast<const QStyleOptionToolButton *>(option)) {
2026             QRect button, menuarea;
2027             button = proxy()->subControlRect(control, toolbutton, SC_ToolButton, widget);
2028             menuarea = proxy()->subControlRect(control, toolbutton, SC_ToolButtonMenu, widget);
2029             State bflags = toolbutton->state & ~(State_Sunken | State_MouseOver);
2030
2031             if (bflags & State_AutoRaise)
2032                 if (!(bflags & State_MouseOver))
2033                     bflags &= ~State_Raised;
2034
2035             State mflags = bflags;
2036
2037             if (toolbutton->state & State_Sunken) {
2038                 if (toolbutton->activeSubControls & SC_ToolButton)
2039                     bflags |= State_Sunken;
2040                 if (toolbutton->activeSubControls & SC_ToolButtonMenu)
2041                     mflags |= State_Sunken;
2042             } else if (toolbutton->state & State_MouseOver) {
2043                 if (toolbutton->activeSubControls & SC_ToolButton)
2044                     bflags |= State_MouseOver;
2045                 if (toolbutton->activeSubControls & SC_ToolButtonMenu)
2046                     mflags |= State_MouseOver;
2047             }
2048
2049             QStyleOption tool(0);
2050
2051             tool.palette = toolbutton->palette;
2052
2053             if (toolbutton->subControls & SC_ToolButton) {
2054                 if (bflags & (State_Sunken | State_On | State_Raised | State_MouseOver)) {
2055                     tool.rect = button;
2056                     tool.state = bflags;
2057                     proxy()->drawPrimitive(PE_PanelButtonTool, &tool, painter, widget);
2058                 }
2059             }
2060
2061             bool drawMenuArrow = toolbutton->features & QStyleOptionToolButton::HasMenu &&
2062                                  !(toolbutton->features & QStyleOptionToolButton::MenuButtonPopup);
2063             int popupArrowSize = drawMenuArrow ? 7 : 0;
2064
2065             if (toolbutton->state & State_HasFocus) {
2066                 QStyleOptionFocusRect fr;
2067                 fr.QStyleOption::operator=(*toolbutton);
2068                 fr.rect = proxy()->subControlRect(CC_ToolButton, toolbutton, SC_ToolButton, widget);
2069                 fr.rect.adjust(1, 1, -1, -1);
2070                 proxy()->drawPrimitive(PE_FrameFocusRect, &fr, painter, widget);
2071             }
2072
2073             QStyleOptionToolButton label = *toolbutton;
2074             label.state = bflags;
2075             GtkWidget *gtkButton = d->gtkWidget("GtkToolButton.GtkButton");
2076             QPalette pal = toolbutton->palette;
2077             if (option->state & State_Enabled && 
2078                 option->state & State_MouseOver && !(widget && widget->testAttribute(Qt::WA_SetPalette))) {
2079                 GdkColor gdkText = d->gtk_widget_get_style(gtkButton)->fg[GTK_STATE_PRELIGHT];
2080                 QColor textColor = QColor(gdkText.red>>8, gdkText.green>>8, gdkText.blue>>8);
2081                 pal.setBrush(QPalette::All, QPalette::ButtonText, textColor);
2082                 label.palette = pal;
2083             }
2084             label.rect = button.adjusted(style->xthickness, style->ythickness,
2085                                         -style->xthickness - popupArrowSize, -style->ythickness);
2086             proxy()->drawControl(CE_ToolButtonLabel, &label, painter, widget);
2087
2088             if (toolbutton->subControls & SC_ToolButtonMenu) {
2089                 tool.rect = menuarea;
2090                 tool.state = mflags;
2091                 if ((mflags & State_Enabled && (mflags & (State_Sunken | State_Raised | State_MouseOver))) || !(mflags & State_AutoRaise))
2092                     proxy()->drawPrimitive(PE_IndicatorButtonDropDown, &tool, painter, widget);
2093
2094                 proxy()->drawPrimitive(PE_IndicatorArrowDown, &tool, painter, widget);
2095
2096             } else if (drawMenuArrow) {
2097                 QRect ir = toolbutton->rect;
2098                 QStyleOptionToolButton newBtn = *toolbutton;
2099                 newBtn.rect = QRect(ir.right() - popupArrowSize - style->xthickness - 3, ir.height()/2 - 1, popupArrowSize, popupArrowSize);
2100                 proxy()->drawPrimitive(PE_IndicatorArrowDown, &newBtn, painter, widget);
2101             }
2102         }
2103         break;
2104
2105 #endif // QT_NO_TOOLBUTTON
2106 #ifndef QT_NO_SCROLLBAR
2107
2108     case CC_ScrollBar:
2109         if (const QStyleOptionSlider *scrollBar = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
2110             GtkWidget *gtkHScrollBar = d->gtkWidget("GtkHScrollbar");
2111             GtkWidget *gtkVScrollBar = d->gtkWidget("GtkVScrollbar");
2112
2113             // Fill background in case the scrollbar is partially transparent
2114             painter->fillRect(option->rect, option->palette.background());
2115
2116             QRect rect = scrollBar->rect;
2117             QRect scrollBarSubLine = proxy()->subControlRect(control, scrollBar, SC_ScrollBarSubLine, widget);
2118             QRect scrollBarAddLine = proxy()->subControlRect(control, scrollBar, SC_ScrollBarAddLine, widget);
2119             QRect scrollBarSlider = proxy()->subControlRect(control, scrollBar, SC_ScrollBarSlider, widget);
2120             QRect grooveRect = proxy()->subControlRect(control, scrollBar, SC_ScrollBarGroove, widget);
2121             bool horizontal = scrollBar->orientation == Qt::Horizontal;
2122             GtkWidget * scrollbarWidget = horizontal ? gtkHScrollBar : gtkVScrollBar;
2123             style = d->gtk_widget_get_style(scrollbarWidget);
2124             gboolean trough_under_steppers = true;
2125             gboolean trough_side_details = false;
2126             gboolean activate_slider = false;
2127             gboolean stepper_size = 14;
2128             gint trough_border = 1;
2129             if (!d->gtk_check_version(2, 10, 0)) {
2130                 d->gtk_widget_style_get((GtkWidget*)(scrollbarWidget),
2131                                            "trough-border",   &trough_border,
2132                                            "trough-side-details",   &trough_side_details,
2133                                            "trough-under-steppers", &trough_under_steppers,
2134                                            "activate-slider",       &activate_slider,
2135                                            "stepper-size",          &stepper_size, NULL);
2136             }
2137             if (trough_under_steppers) {
2138                 scrollBarAddLine.adjust(trough_border, trough_border, -trough_border, -trough_border);
2139                 scrollBarSubLine.adjust(trough_border, trough_border, -trough_border, -trough_border);
2140                 scrollBarSlider.adjust(horizontal ? -trough_border : 0, horizontal ? 0 : -trough_border,
2141                                        horizontal ? trough_border : 0, horizontal ? 0 : trough_border);
2142             }
2143
2144             // Some styles check the position of scrollbars in order to determine
2145             // if lines should be painted when the scrollbar is in max or min positions.
2146             int maximum = 2;
2147             int fakePos = 0;
2148             bool reverse = (option->direction == Qt::RightToLeft);
2149             if (scrollBar->minimum == scrollBar->maximum)
2150                 maximum = 0;
2151             if (scrollBar->sliderPosition == scrollBar->maximum)
2152                 fakePos = maximum;
2153             else if (scrollBar->sliderPosition > scrollBar->minimum)
2154                 fakePos = maximum - 1;
2155
2156
2157             GtkRange *range = (GtkRange*)(horizontal ? gtkHScrollBar : gtkVScrollBar);
2158             GtkAdjustment *adjustment = d->gtk_range_get_adjustment(range);
2159
2160             if (adjustment) {
2161                 d->gtk_adjustment_configure(adjustment, fakePos, 0, maximum, 0, 0, 0);
2162             } else {
2163                 adjustment = (GtkAdjustment*)d->gtk_adjustment_new(fakePos, 0, maximum, 0, 0, 0);
2164                 d->gtk_range_set_adjustment(range, adjustment);
2165             }
2166
2167             if (scrollBar->subControls & SC_ScrollBarGroove) {
2168                 GtkStateType state = GTK_STATE_ACTIVE;
2169
2170                 if (!(option->state & State_Enabled))
2171                     state = GTK_STATE_INSENSITIVE;
2172
2173                 if (trough_under_steppers)
2174                     grooveRect = option->rect;
2175
2176                 gtkPainter.paintBox( scrollbarWidget, "trough", grooveRect, state, GTK_SHADOW_IN, style);
2177             }
2178
2179             //paint slider
2180             if (scrollBar->subControls & SC_ScrollBarSlider) {
2181                 GtkStateType state = GTK_STATE_NORMAL;
2182
2183                 if (!(option->state & State_Enabled))
2184                     state = GTK_STATE_INSENSITIVE;
2185                 else if (activate_slider &&
2186                          option->state & State_Sunken && (scrollBar->activeSubControls & SC_ScrollBarSlider))
2187                     state = GTK_STATE_ACTIVE;
2188                 else if (option->state & State_MouseOver && (scrollBar->activeSubControls & SC_ScrollBarSlider))
2189                     state = GTK_STATE_PRELIGHT;
2190
2191                 GtkShadowType shadow = GTK_SHADOW_OUT;
2192
2193                 if (trough_under_steppers) {
2194                     if (!horizontal)
2195                         scrollBarSlider.adjust(trough_border, 0, -trough_border, 0);
2196                     else
2197                         scrollBarSlider.adjust(0, trough_border, 0, -trough_border);
2198                 }
2199
2200                 gtkPainter.paintSlider( scrollbarWidget, "slider", scrollBarSlider, state, shadow, style,
2201
2202                                         horizontal ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL, QString(QLS("%0%1")).arg(fakePos).arg(maximum));
2203             }
2204
2205             if (scrollBar->subControls & SC_ScrollBarAddLine) {
2206                 GtkAllocation vAllocation;
2207                 vAllocation.y = scrollBarAddLine.top();
2208                 vAllocation.height = scrollBarAddLine.height() - rect.height() + 6;
2209                 d->gtk_widget_set_allocation(gtkVScrollBar, &vAllocation);
2210
2211                 GtkAllocation hAllocation;
2212                 hAllocation.x = scrollBarAddLine.right();
2213                 hAllocation.width = scrollBarAddLine.width() - rect.width();
2214                 d->gtk_widget_set_allocation(gtkHScrollBar, &hAllocation);
2215
2216                 GtkShadowType shadow = GTK_SHADOW_OUT;
2217                 GtkStateType state = GTK_STATE_NORMAL;
2218
2219                 if (!(option->state & State_Enabled) || (fakePos == maximum))
2220                     state = GTK_STATE_INSENSITIVE;
2221                 else if (option->state & State_Sunken && (scrollBar->activeSubControls & SC_ScrollBarAddLine)) {
2222                     state = GTK_STATE_ACTIVE;
2223                     shadow = GTK_SHADOW_IN;
2224
2225                 } else if (option->state & State_MouseOver && (scrollBar->activeSubControls & SC_ScrollBarAddLine))
2226                     state = GTK_STATE_PRELIGHT;
2227
2228                 gtkPainter.paintBox( scrollbarWidget,
2229                                      horizontal ? "hscrollbar" : "vscrollbar", scrollBarAddLine,
2230                                      state, shadow, style, QLS("add"));
2231
2232                 gtkPainter.paintArrow( scrollbarWidget, horizontal ? "hscrollbar" : "vscrollbar", scrollBarAddLine.adjusted(4, 4, -4, -4),
2233                                        horizontal ? (reverse ? GTK_ARROW_LEFT : GTK_ARROW_RIGHT) :
2234                                        GTK_ARROW_DOWN, state, GTK_SHADOW_NONE, false, style);
2235             }
2236
2237             if (scrollBar->subControls & SC_ScrollBarSubLine) {
2238                 GtkAllocation vAllocation;
2239                 vAllocation.y = 0;
2240                 vAllocation.height = scrollBarSubLine.height();
2241                 d->gtk_widget_set_allocation(gtkVScrollBar, &vAllocation);
2242
2243                 GtkAllocation hAllocation;
2244                 hAllocation.x = 0;
2245                 hAllocation.width = scrollBarSubLine.width();
2246                 d->gtk_widget_set_allocation(gtkHScrollBar, &hAllocation);
2247
2248                 GtkShadowType shadow = GTK_SHADOW_OUT;
2249                 GtkStateType state = GTK_STATE_NORMAL;
2250
2251                 if (!(option->state & State_Enabled) || (fakePos == 0))
2252                     state = GTK_STATE_INSENSITIVE;
2253                 else if (option->state & State_Sunken && (scrollBar->activeSubControls & SC_ScrollBarSubLine)) {
2254                     shadow = GTK_SHADOW_IN;
2255                     state = GTK_STATE_ACTIVE;
2256
2257                 } else if (option->state & State_MouseOver && (scrollBar->activeSubControls & SC_ScrollBarSubLine))
2258                     state = GTK_STATE_PRELIGHT;
2259
2260                 gtkPainter.paintBox(scrollbarWidget, horizontal ? "hscrollbar" : "vscrollbar", scrollBarSubLine,
2261                                     state, shadow, style, QLS("sub"));
2262
2263                 gtkPainter.paintArrow(scrollbarWidget, horizontal ? "hscrollbar" : "vscrollbar", scrollBarSubLine.adjusted(4, 4, -4, -4),
2264                                       horizontal ? (reverse ? GTK_ARROW_RIGHT : GTK_ARROW_LEFT) :
2265                                       GTK_ARROW_UP, state, GTK_SHADOW_NONE, false, style);
2266             }
2267         }
2268         break;
2269
2270 #endif //QT_NO_SCROLLBAR
2271 #ifndef QT_NO_SPINBOX
2272
2273     case CC_SpinBox:
2274         if (const QStyleOptionSpinBox *spinBox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) {
2275
2276             GtkWidget *gtkSpinButton = spinBox->buttonSymbols == QAbstractSpinBox::NoButtons
2277                         ? d->gtkWidget("GtkEntry")
2278                         : d->gtkWidget("GtkSpinButton");
2279             bool isEnabled = (spinBox->state & State_Enabled);
2280             bool hover = isEnabled && (spinBox->state & State_MouseOver);
2281             bool sunken = (spinBox->state & State_Sunken);
2282             bool upIsActive = (spinBox->activeSubControls == SC_SpinBoxUp);
2283             bool downIsActive = (spinBox->activeSubControls == SC_SpinBoxDown);
2284             bool reverse = (spinBox->direction == Qt::RightToLeft);
2285
2286             QRect editArea = option->rect;
2287             QRect editRect = proxy()->subControlRect(CC_SpinBox, option, SC_SpinBoxEditField, widget);
2288             QRect upRect, downRect, buttonRect;
2289             if (spinBox->buttonSymbols != QAbstractSpinBox::NoButtons) {
2290                 upRect = proxy()->subControlRect(CC_SpinBox, option, SC_SpinBoxUp, widget);
2291                 downRect = proxy()->subControlRect(CC_SpinBox, option, SC_SpinBoxDown, widget);
2292
2293                 //### Move this to subControlRect
2294                 upRect.setTop(option->rect.top());
2295
2296                 if (reverse)
2297                     upRect.setLeft(option->rect.left());
2298                 else
2299                     upRect.setRight(option->rect.right());
2300
2301                 downRect.setBottom(option->rect.bottom());
2302
2303                 if (reverse)
2304                     downRect.setLeft(option->rect.left());
2305                 else
2306                     downRect.setRight(option->rect.right());
2307
2308                 buttonRect = upRect | downRect;
2309
2310                 if (reverse)
2311                     editArea.setLeft(upRect.right());
2312                 else
2313                     editArea.setRight(upRect.left());
2314             }
2315             if (spinBox->frame) {
2316                 GtkStateType state = gtkPainter.gtkState(option);
2317
2318                 if (!(option->state & State_Enabled))
2319                     state = GTK_STATE_INSENSITIVE;
2320                 else if (option->state & State_HasFocus)
2321                     state = GTK_STATE_NORMAL;
2322                 else if (state == GTK_STATE_PRELIGHT)
2323                     state = GTK_STATE_NORMAL;
2324
2325                 style = gtkPainter.getStyle(gtkSpinButton);
2326
2327
2328                 QString key;
2329
2330                 if (option->state & State_HasFocus) {
2331                     key += QLatin1Char('f');
2332                     GTK_WIDGET_SET_FLAGS(gtkSpinButton, GTK_HAS_FOCUS);
2333                 }
2334
2335                 uint resolve_mask = option->palette.resolve();
2336
2337                 if (resolve_mask & (1 << QPalette::Base)) // Palette overridden by user
2338                     painter->fillRect(editRect, option->palette.base().color());
2339                 else
2340                     gtkPainter.paintFlatBox(gtkSpinButton, "entry_bg", editArea.adjusted(style->xthickness, style->ythickness,
2341                                             -style->xthickness, -style->ythickness),
2342                                             option->state & State_Enabled ?
2343                                             GTK_STATE_NORMAL : GTK_STATE_INSENSITIVE, GTK_SHADOW_NONE, style, key);
2344
2345                 gtkPainter.paintShadow(gtkSpinButton, "entry", editArea, state, GTK_SHADOW_IN, d->gtk_widget_get_style(gtkSpinButton), key);
2346                 if (spinBox->buttonSymbols != QAbstractSpinBox::NoButtons) {
2347                     gtkPainter.paintBox(gtkSpinButton, "spinbutton", buttonRect, state, GTK_SHADOW_IN, style, key);
2348
2349                     upRect.setSize(downRect.size());
2350                     if (!(option->state & State_Enabled))
2351                         gtkPainter.paintBox( gtkSpinButton, "spinbutton_up", upRect, GTK_STATE_INSENSITIVE, GTK_SHADOW_IN, style, key);
2352                     else if (upIsActive && sunken)
2353                         gtkPainter.paintBox( gtkSpinButton, "spinbutton_up", upRect, GTK_STATE_ACTIVE, GTK_SHADOW_IN, style, key);
2354                     else if (upIsActive && hover)
2355                         gtkPainter.paintBox( gtkSpinButton, "spinbutton_up", upRect, GTK_STATE_PRELIGHT, GTK_SHADOW_OUT, style, key);
2356                     else
2357                         gtkPainter.paintBox( gtkSpinButton, "spinbutton_up", upRect, GTK_STATE_NORMAL, GTK_SHADOW_OUT, style, key);
2358
2359                     if (!(option->state & State_Enabled))
2360                         gtkPainter.paintBox( gtkSpinButton, "spinbutton_down", downRect, GTK_STATE_INSENSITIVE, GTK_SHADOW_IN, style, key);
2361                     else if (downIsActive && sunken)
2362                         gtkPainter.paintBox( gtkSpinButton, "spinbutton_down", downRect, GTK_STATE_ACTIVE, GTK_SHADOW_IN, style, key);
2363                     else if (downIsActive && hover)
2364                         gtkPainter.paintBox( gtkSpinButton, "spinbutton_down", downRect, GTK_STATE_PRELIGHT, GTK_SHADOW_OUT, style, key);
2365                     else
2366                         gtkPainter.paintBox( gtkSpinButton, "spinbutton_down", downRect, GTK_STATE_NORMAL, GTK_SHADOW_OUT, style, key);
2367
2368                     if (option->state & State_HasFocus)
2369                         GTK_WIDGET_UNSET_FLAGS(gtkSpinButton, GTK_HAS_FOCUS);
2370                 }
2371             }
2372
2373             if (spinBox->buttonSymbols == QAbstractSpinBox::PlusMinus) {
2374                 int centerX = upRect.center().x();
2375                 int centerY = upRect.center().y();
2376                 // plus/minus
2377
2378                 if (spinBox->activeSubControls == SC_SpinBoxUp && sunken) {
2379                     painter->drawLine(1 + centerX - 2, 1 + centerY, 1 + centerX + 2, 1 + centerY);
2380                     painter->drawLine(1 + centerX, 1 + centerY - 2, 1 + centerX, 1 + centerY + 2);
2381
2382                 } else {
2383                     painter->drawLine(centerX - 2, centerY, centerX + 2, centerY);
2384                     painter->drawLine(centerX, centerY - 2, centerX, centerY + 2);
2385                 }
2386                 centerX = downRect.center().x();
2387                 centerY = downRect.center().y();
2388
2389                 if (spinBox->activeSubControls == SC_SpinBoxDown && sunken) {
2390                     painter->drawLine(1 + centerX - 2, 1 + centerY, 1 + centerX + 2, 1 + centerY);
2391                 } else {
2392                     painter->drawLine(centerX - 2, centerY, centerX + 2, centerY);
2393                 }
2394
2395             } else if (spinBox->buttonSymbols == QAbstractSpinBox::UpDownArrows) {
2396                 int size = d->getSpinboxArrowSize();
2397                 int w = size / 2 - 1;
2398                 w -= w % 2 - 1; // force odd
2399                 int h = (w + 1)/2;
2400                 QRect arrowRect(0, 0, w, h);
2401                 arrowRect.moveCenter(upRect.center());
2402                 // arrows
2403                 GtkStateType state = GTK_STATE_NORMAL;
2404
2405                 if (!(option->state & State_Enabled) || !(spinBox->stepEnabled & QAbstractSpinBox::StepUpEnabled))
2406                     state = GTK_STATE_INSENSITIVE;
2407
2408                 gtkPainter.paintArrow( gtkSpinButton, "spinbutton", arrowRect, GTK_ARROW_UP, state,
2409                                        GTK_SHADOW_NONE, false, style);
2410
2411                 arrowRect.moveCenter(downRect.center());
2412
2413                 if (!(option->state & State_Enabled) || !(spinBox->stepEnabled & QAbstractSpinBox::StepDownEnabled))
2414                     state = GTK_STATE_INSENSITIVE;
2415
2416                 gtkPainter.paintArrow( gtkSpinButton, "spinbutton", arrowRect, GTK_ARROW_DOWN, state,
2417                                        GTK_SHADOW_NONE, false, style);
2418             }
2419         }
2420         break;
2421
2422 #endif // QT_NO_SPINBOX
2423
2424 #ifndef QT_NO_SLIDER
2425
2426     case CC_Slider:
2427         if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
2428             GtkWidget *hScaleWidget = d->gtkWidget("GtkHScale");
2429             GtkWidget *vScaleWidget = d->gtkWidget("GtkVScale");
2430
2431             QRect groove = proxy()->subControlRect(CC_Slider, option, SC_SliderGroove, widget);
2432             QRect handle = proxy()->subControlRect(CC_Slider, option, SC_SliderHandle, widget);
2433
2434             bool horizontal = slider->orientation == Qt::Horizontal;
2435             bool ticksAbove = slider->tickPosition & QSlider::TicksAbove;
2436             bool ticksBelow = slider->tickPosition & QSlider::TicksBelow;
2437
2438             QBrush oldBrush = painter->brush();
2439             QPen oldPen = painter->pen();
2440
2441             QColor shadowAlpha(Qt::black);
2442             shadowAlpha.setAlpha(10);
2443             QColor highlightAlpha(Qt::white);
2444             highlightAlpha.setAlpha(80);
2445
2446             QGtkStylePrivate::gtk_widget_set_direction(hScaleWidget, slider->upsideDown ?
2447                                                        GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR);
2448             GtkWidget *scaleWidget = horizontal ? hScaleWidget : vScaleWidget;
2449             style = d->gtk_widget_get_style(scaleWidget);
2450
2451             if ((option->subControls & SC_SliderGroove) && groove.isValid()) {
2452
2453                 GtkRange *range = (GtkRange*)scaleWidget;
2454                 GtkAdjustment *adjustment = d->gtk_range_get_adjustment(range);
2455                 if (adjustment) {
2456                     d->gtk_adjustment_configure(adjustment,
2457                                                 slider->sliderPosition,
2458                                                 slider->minimum,
2459                                                 slider->maximum,
2460                                                 slider->singleStep,
2461                                                 slider->singleStep,
2462                                                 slider->pageStep);
2463                 } else {
2464                     adjustment = (GtkAdjustment*)d->gtk_adjustment_new(slider->sliderPosition,
2465                                                                        slider->minimum,
2466                                                                        slider->maximum,
2467                                                                        slider->singleStep,
2468                                                                        slider->singleStep,
2469                                                                        slider->pageStep);
2470                     d->gtk_range_set_adjustment(range, adjustment);
2471                 }
2472
2473                 int outerSize;
2474                 d->gtk_range_set_inverted(range, !horizontal);
2475                 d->gtk_widget_style_get(scaleWidget, "trough-border", &outerSize, NULL);
2476                 outerSize++;
2477
2478                 GtkStateType state = gtkPainter.gtkState(option);
2479                 int focusFrameMargin = 2;
2480                 QRect grooveRect = option->rect.adjusted(focusFrameMargin, outerSize + focusFrameMargin,
2481                                    -focusFrameMargin, -outerSize - focusFrameMargin);
2482
2483                 gboolean trough_side_details = false; // Indicates if the upper or lower scale background differs
2484                 if (!d->gtk_check_version(2, 10, 0))
2485                     d->gtk_widget_style_get((GtkWidget*)(scaleWidget), "trough-side-details",   &trough_side_details, NULL);
2486
2487                 if (!trough_side_details) {
2488                     gtkPainter.paintBox( scaleWidget, "trough", grooveRect, state,
2489                                          GTK_SHADOW_IN, style, QString(QLS("p%0")).arg(slider->sliderPosition));
2490                 } else {
2491                     QRect upperGroove = grooveRect;
2492                     QRect lowerGroove = grooveRect;
2493
2494                     if (horizontal) {
2495                         if (slider->upsideDown) {
2496                             lowerGroove.setLeft(handle.center().x());
2497                             upperGroove.setRight(handle.center().x());
2498                         } else {
2499                             upperGroove.setLeft(handle.center().x());
2500                             lowerGroove.setRight(handle.center().x());
2501                         }
2502                     } else {
2503                         if (!slider->upsideDown) {
2504                             lowerGroove.setBottom(handle.center().y());
2505                             upperGroove.setTop(handle.center().y());
2506                         } else {
2507                             upperGroove.setBottom(handle.center().y());
2508                             lowerGroove.setTop(handle.center().y());
2509                         }
2510                     }
2511
2512                     gtkPainter.paintBox( scaleWidget, "trough-upper", upperGroove, state,
2513                                          GTK_SHADOW_IN, style, QString(QLS("p%0")).arg(slider->sliderPosition));
2514                     gtkPainter.paintBox( scaleWidget, "trough-lower", lowerGroove, state,
2515                                          GTK_SHADOW_IN, style, QString(QLS("p%0")).arg(slider->sliderPosition));
2516                 }
2517             }
2518
2519             if (option->subControls & SC_SliderTickmarks) {
2520                 painter->setPen(darkOutline);
2521                 int tickSize = proxy()->pixelMetric(PM_SliderTickmarkOffset, option, widget);
2522                 int available = proxy()->pixelMetric(PM_SliderSpaceAvailable, slider, widget);
2523                 int interval = slider->tickInterval;
2524
2525                 if (interval <= 0) {
2526                     interval = slider->singleStep;
2527
2528                     if (QStyle::sliderPositionFromValue(slider->minimum, slider->maximum, interval,
2529                                                         available)
2530                             - QStyle::sliderPositionFromValue(slider->minimum, slider->maximum,
2531                                                               0, available) < 3)
2532                         interval = slider->pageStep;
2533                 }
2534
2535                 if (interval <= 0)
2536                     interval = 1;
2537
2538                 int v = slider->minimum;
2539                 int len = proxy()->pixelMetric(PM_SliderLength, slider, widget);
2540                 while (v <= slider->maximum + 1) {
2541                     if (v == slider->maximum + 1 && interval == 1)
2542                         break;
2543                     const int v_ = qMin(v, slider->maximum);
2544                     int pos = sliderPositionFromValue(slider->minimum, slider->maximum,
2545                                                       v_, (horizontal
2546                                                            ? slider->rect.width()
2547                                                            : slider->rect.height()) - len,
2548                                                       slider->upsideDown) + len / 2;
2549                     int extra = 2 - ((v_ == slider->minimum || v_ == slider->maximum) ? 1 : 0);
2550                     if (horizontal) {
2551                         if (ticksAbove)
2552                             painter->drawLine(pos, slider->rect.top() + extra,
2553                                               pos, slider->rect.top() + tickSize);
2554                         if (ticksBelow)
2555                             painter->drawLine(pos, slider->rect.bottom() - extra,
2556                                               pos, slider->rect.bottom() - tickSize);
2557
2558                     } else {
2559                         if (ticksAbove)
2560                             painter->drawLine(slider->rect.left() + extra, pos,
2561                                               slider->rect.left() + tickSize, pos);
2562                         if (ticksBelow)
2563                             painter->drawLine(slider->rect.right() - extra, pos,
2564                                               slider->rect.right() - tickSize, pos);
2565                     }
2566
2567                     // In the case where maximum is max int
2568                     int nextInterval = v + interval;
2569                     if (nextInterval < v)
2570                         break;
2571                     v = nextInterval;
2572                 }
2573             }
2574
2575             // Draw slider handle
2576             if (option->subControls & SC_SliderHandle) {
2577                 GtkShadowType shadow =  GTK_SHADOW_OUT;
2578                 GtkStateType state = GTK_STATE_NORMAL;
2579
2580                 if (!(option->state & State_Enabled))
2581                     state = GTK_STATE_INSENSITIVE;
2582                 else if (option->state & State_MouseOver && option->activeSubControls & SC_SliderHandle)
2583                     state = GTK_STATE_PRELIGHT;
2584
2585                 bool horizontal = option->state & State_Horizontal;
2586
2587                 if (slider->state & State_HasFocus) {
2588                     QStyleOptionFocusRect fropt;
2589                     fropt.QStyleOption::operator=(*slider);
2590                     fropt.rect = slider->rect.adjusted(-1, -1 ,1, 1);
2591
2592                     if (horizontal) {
2593                         fropt.rect.setTop(handle.top() - 3);
2594                         fropt.rect.setBottom(handle.bottom() + 4);
2595
2596                     } else {
2597                         fropt.rect.setLeft(handle.left() - 3);
2598                         fropt.rect.setRight(handle.right() + 3);
2599                     }
2600                     proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget);
2601                 }
2602                 gtkPainter.paintSlider( scaleWidget, horizontal ? "hscale" : "vscale", handle, state, shadow, style,
2603
2604                                         horizontal ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL);
2605             }
2606             painter->setBrush(oldBrush);
2607             painter->setPen(oldPen);
2608         }
2609         break;
2610     case CC_Dial:
2611         if (const QStyleOptionSlider *dial = qstyleoption_cast<const QStyleOptionSlider *>(option))
2612             QStyleHelper::drawDial(dial, painter);
2613         break;
2614
2615 #endif // QT_NO_SLIDER
2616
2617     default:
2618         QWindowsStyle::drawComplexControl(control, option, painter, widget);
2619
2620         break;
2621     }
2622 }
2623
2624
2625 /*!
2626     \reimp
2627 */
2628 void QGtkStyle::drawControl(ControlElement element,
2629                             const QStyleOption *option,
2630                             QPainter *painter,
2631                             const QWidget *widget) const
2632 {
2633     Q_D(const QGtkStyle);
2634
2635     if (!d->isThemeAvailable()) {
2636         QWindowsStyle::drawControl(element, option, painter, widget);
2637         return;
2638     }
2639
2640     GtkStyle* style = d->gtkStyle();
2641     QGtkPainter gtkPainter(painter);
2642
2643     switch (element) {
2644     case CE_ProgressBarLabel:
2645         if (const QStyleOptionProgressBar *bar = qstyleoption_cast<const QStyleOptionProgressBar *>(option)) {
2646             GtkWidget *gtkProgressBar = d->gtkWidget("GtkProgressBar");
2647             if (!gtkProgressBar)
2648                 return;
2649
2650             QRect leftRect;
2651             QRect rect = bar->rect;
2652             GtkStyle *gtkProgressBarStyle = d->gtk_widget_get_style(gtkProgressBar);
2653             GdkColor gdkText = gtkProgressBarStyle->fg[GTK_STATE_NORMAL];
2654             QColor textColor = QColor(gdkText.red>>8, gdkText.green>>8, gdkText.blue>>8);
2655             gdkText = gtkProgressBarStyle->fg[GTK_STATE_PRELIGHT];
2656             QColor alternateTextColor= QColor(gdkText.red>>8, gdkText.green>>8, gdkText.blue>>8);
2657
2658             painter->save();
2659             bool vertical = false, inverted = false;
2660             if (const QStyleOptionProgressBarV2 *bar2 = qstyleoption_cast<const QStyleOptionProgressBarV2 *>(option)) {
2661                 vertical = (bar2->orientation == Qt::Vertical);
2662                 inverted = bar2->invertedAppearance;
2663             }
2664             if (vertical)
2665                 rect = QRect(rect.left(), rect.top(), rect.height(), rect.width()); // flip width and height
2666             const int progressIndicatorPos = (bar->progress - qreal(bar->minimum)) * rect.width() /
2667                                               qMax(qreal(1.0), qreal(bar->maximum) - bar->minimum);
2668             if (progressIndicatorPos >= 0 && progressIndicatorPos <= rect.width())
2669                 leftRect = QRect(rect.left(), rect.top(), progressIndicatorPos, rect.height());
2670             if (vertical)
2671                 leftRect.translate(rect.width() - progressIndicatorPos, 0);
2672
2673             bool flip = (!vertical && (((bar->direction == Qt::RightToLeft) && !inverted) ||
2674                                        ((bar->direction == Qt::LeftToRight) && inverted)));
2675
2676             QRegion rightRect = rect;
2677             rightRect = rightRect.subtracted(leftRect);
2678             painter->setClipRegion(rightRect);
2679             painter->setPen(flip ? alternateTextColor : textColor);
2680             painter->drawText(rect, bar->text, QTextOption(Qt::AlignAbsolute | Qt::AlignHCenter | Qt::AlignVCenter));
2681             if (!leftRect.isNull()) {
2682                 painter->setPen(flip ? textColor : alternateTextColor);
2683                 painter->setClipRect(leftRect);
2684                 painter->drawText(rect, bar->text, QTextOption(Qt::AlignAbsolute | Qt::AlignHCenter | Qt::AlignVCenter));
2685             }
2686             painter->restore();
2687         }
2688         break;
2689     case CE_PushButtonLabel:
2690         if (const QStyleOptionButton *button = qstyleoption_cast<const QStyleOptionButton *>(option)) {
2691             QRect ir = button->rect;
2692             uint tf = Qt::AlignVCenter | Qt::TextShowMnemonic;
2693             QPoint buttonShift;
2694
2695             if (option->state & State_Sunken)
2696                 buttonShift = QPoint(pixelMetric(PM_ButtonShiftHorizontal, option, widget),
2697                                      proxy()->pixelMetric(PM_ButtonShiftVertical, option, widget));
2698
2699             if (proxy()->styleHint(SH_UnderlineShortcut, button, widget))
2700                 tf |= Qt::TextShowMnemonic;
2701             else
2702                 tf |= Qt::TextHideMnemonic;
2703
2704             if (!button->icon.isNull()) {
2705                 //Center both icon and text
2706                 QPoint point;
2707
2708                 QIcon::Mode mode = button->state & State_Enabled ? QIcon::Normal : QIcon::Disabled;
2709                 if (mode == QIcon::Normal && button->state & State_HasFocus)
2710                     mode = QIcon::Active;
2711
2712                 QIcon::State state = QIcon::Off;
2713
2714                 if (button->state & State_On)
2715                     state = QIcon::On;
2716
2717                 QPixmap pixmap = button->icon.pixmap(button->iconSize, mode, state);
2718                 int w = pixmap.width();
2719                 int h = pixmap.height();
2720
2721                 if (!button->text.isEmpty())
2722                     w += button->fontMetrics.boundingRect(option->rect, tf, button->text).width() + 4;
2723
2724                 point = QPoint(ir.x() + ir.width() / 2 - w / 2,
2725                                ir.y() + ir.height() / 2 - h / 2);
2726
2727                 if (button->direction == Qt::RightToLeft)
2728                     point.rx() += pixmap.width();
2729
2730                 painter->drawPixmap(visualPos(button->direction, button->rect, point + buttonShift), pixmap);
2731
2732                 if (button->direction == Qt::RightToLeft)
2733                     ir.translate(-point.x() - 2, 0);
2734                 else
2735                     ir.translate(point.x() + pixmap.width() + 2, 0);
2736
2737                 // left-align text if there is
2738                 if (!button->text.isEmpty())
2739                     tf |= Qt::AlignLeft;
2740
2741             } else {
2742                 tf |= Qt::AlignHCenter;
2743             }
2744
2745             ir.translate(buttonShift);
2746
2747             if (button->features & QStyleOptionButton::HasMenu)
2748                 ir = ir.adjusted(0, 0, -pixelMetric(PM_MenuButtonIndicator, button, widget), 0);
2749
2750             GtkWidget *gtkButton = d->gtkWidget("GtkButton");
2751             QPalette pal = button->palette;
2752             int labelState = GTK_STATE_INSENSITIVE;
2753             if (option->state & State_Enabled)
2754                 labelState = (option->state & State_MouseOver && !(option->state & State_Sunken)) ?
2755                              GTK_STATE_PRELIGHT : GTK_STATE_NORMAL;
2756
2757             GdkColor gdkText = d->gtk_widget_get_style(gtkButton)->fg[labelState];
2758             QColor textColor = QColor(gdkText.red>>8, gdkText.green>>8, gdkText.blue>>8);
2759             pal.setBrush(QPalette::ButtonText, textColor);
2760             proxy()->drawItemText(painter, ir, tf, pal, (button->state & State_Enabled),
2761                          button->text, QPalette::ButtonText);
2762         }
2763         break;
2764
2765     case CE_RadioButton: // Fall through
2766     case CE_CheckBox:
2767         if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) {
2768             bool isRadio = (element == CE_RadioButton);
2769
2770             // Draw prelight background
2771             GtkWidget *gtkRadioButton = d->gtkWidget("GtkRadioButton");
2772
2773             if (option->state & State_MouseOver) {
2774                 gtkPainter.paintFlatBox(gtkRadioButton, "checkbutton", option->rect,
2775                                         GTK_STATE_PRELIGHT, GTK_SHADOW_ETCHED_OUT, d->gtk_widget_get_style(gtkRadioButton));
2776             }
2777
2778             QStyleOptionButton subopt = *btn;
2779             subopt.rect = subElementRect(isRadio ? SE_RadioButtonIndicator
2780                                          : SE_CheckBoxIndicator, btn, widget);
2781             proxy()->drawPrimitive(isRadio ? PE_IndicatorRadioButton : PE_IndicatorCheckBox,
2782                           &subopt, painter, widget);
2783             subopt.rect = subElementRect(isRadio ? SE_RadioButtonContents
2784                                          : SE_CheckBoxContents, btn, widget);
2785             // Get label text color
2786             QPalette pal = subopt.palette;
2787             int labelState = GTK_STATE_INSENSITIVE;
2788             if (option->state & State_Enabled)
2789                 labelState = (option->state & State_MouseOver) ? GTK_STATE_PRELIGHT : GTK_STATE_NORMAL;
2790
2791             GdkColor gdkText = d->gtk_widget_get_style(gtkRadioButton)->fg[labelState];
2792             QColor textColor = QColor(gdkText.red>>8, gdkText.green>>8, gdkText.blue>>8);
2793             pal.setBrush(QPalette::WindowText, textColor);
2794             subopt.palette = pal;
2795             proxy()->drawControl(isRadio ? CE_RadioButtonLabel : CE_CheckBoxLabel, &subopt, painter, widget);
2796
2797             if (btn->state & State_HasFocus) {
2798                 QStyleOptionFocusRect fropt;
2799                 fropt.QStyleOption::operator=(*btn);
2800                 fropt.rect = subElementRect(isRadio ? SE_RadioButtonFocusRect
2801                                             : SE_CheckBoxFocusRect, btn, widget);
2802                 proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget);
2803             }
2804         }
2805         break;
2806
2807 #ifndef QT_NO_COMBOBOX
2808
2809     case CE_ComboBoxLabel:
2810         if (const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
2811             QRect editRect = proxy()->subControlRect(CC_ComboBox, cb, SC_ComboBoxEditField, widget);
2812             bool appearsAsList = !proxy()->styleHint(QStyle::SH_ComboBox_Popup, cb, widget);
2813             painter->save();
2814             painter->setClipRect(editRect);
2815
2816             if (!cb->currentIcon.isNull()) {
2817                 QIcon::Mode mode = cb->state & State_Enabled ? QIcon::Normal
2818                                    : QIcon::Disabled;
2819                 QPixmap pixmap = cb->currentIcon.pixmap(cb->iconSize, mode);
2820                 QRect iconRect(editRect);
2821                 iconRect.setWidth(cb->iconSize.width() + 4);
2822
2823                 iconRect = alignedRect(cb->direction,
2824                                        Qt::AlignLeft | Qt::AlignVCenter,
2825                                        iconRect.size(), editRect);
2826
2827                 if (cb->editable)
2828                     painter->fillRect(iconRect, option->palette.brush(QPalette::Base));
2829
2830                 proxy()->drawItemPixmap(painter, iconRect, Qt::AlignCenter, pixmap);
2831
2832                 if (cb->direction == Qt::RightToLeft)
2833                     editRect.translate(-4 - cb->iconSize.width(), 0);
2834                 else
2835                     editRect.translate(cb->iconSize.width() + 4, 0);
2836             }
2837
2838             if (!cb->currentText.isEmpty() && !cb->editable) {
2839                 GtkWidget *gtkCombo = d->gtkWidget("GtkComboBox");
2840                 QPalette pal = cb->palette;
2841                 int labelState = GTK_STATE_INSENSITIVE;
2842
2843                 if (option->state & State_Enabled)
2844                     labelState = (option->state & State_MouseOver && !appearsAsList) ? GTK_STATE_PRELIGHT : GTK_STATE_NORMAL;
2845
2846                 GdkColor gdkText = d->gtk_widget_get_style(gtkCombo)->fg[labelState];
2847
2848                 QColor textColor = QColor(gdkText.red>>8, gdkText.green>>8, gdkText.blue>>8);
2849
2850                 pal.setBrush(QPalette::ButtonText, textColor);
2851
2852                 proxy()->drawItemText(painter, editRect.adjusted(1, 0, -1, 0),
2853                              visualAlignment(cb->direction, Qt::AlignLeft | Qt::AlignVCenter),
2854                              pal, cb->state & State_Enabled, cb->currentText, QPalette::ButtonText);
2855             }
2856
2857             painter->restore();
2858         }
2859         break;
2860
2861 #endif // QT_NO_COMBOBOX
2862
2863     case CE_DockWidgetTitle:
2864         painter->save();
2865         if (const QStyleOptionDockWidget *dwOpt = qstyleoption_cast<const QStyleOptionDockWidget *>(option)) {
2866             const QStyleOptionDockWidgetV2 *v2
2867                 = qstyleoption_cast<const QStyleOptionDockWidgetV2*>(dwOpt);
2868             bool verticalTitleBar = v2 == 0 ? false : v2->verticalTitleBar;
2869
2870             QRect rect = dwOpt->rect;
2871             QRect titleRect = subElementRect(SE_DockWidgetTitleBarText, option, widget).adjusted(-2, 0, -2, 0);
2872             QRect r = rect.adjusted(0, 0, -1, -1);
2873             if (verticalTitleBar)
2874                 r.adjust(0, 0, 0, -1);
2875
2876             if (verticalTitleBar) {
2877                 QRect r = rect;
2878                 QSize s = r.size();
2879                 s.transpose();
2880                 r.setSize(s);
2881
2882                 titleRect = QRect(r.left() + rect.bottom()
2883                                     - titleRect.bottom(),
2884                                 r.top() + titleRect.left() - rect.left(),
2885                                 titleRect.height(), titleRect.width());
2886
2887                 painter->translate(r.left(), r.top() + r.width());
2888                 painter->rotate(-90);
2889                 painter->translate(-r.left(), -r.top());
2890
2891                 rect = r;
2892             }
2893
2894             if (!dwOpt->title.isEmpty()) {
2895                 QString titleText
2896                     = painter->fontMetrics().elidedText(dwOpt->title,
2897                                             Qt::ElideRight, titleRect.width());
2898                 proxy()->drawItemText(painter,
2899                              titleRect,
2900                              Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic, dwOpt->palette,
2901                              dwOpt->state & State_Enabled, titleText,
2902                              QPalette::WindowText);
2903                 }
2904         }
2905         painter->restore();
2906         break;
2907
2908
2909
2910     case CE_HeaderSection:
2911         painter->save();
2912
2913         // Draws the header in tables.
2914         if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) {
2915             Q_UNUSED(header);
2916             GtkWidget *gtkTreeView = d->gtkWidget("GtkTreeView");
2917             // Get the middle column
2918             GtkTreeViewColumn *column = d->gtk_tree_view_get_column((GtkTreeView*)gtkTreeView, 1);
2919             Q_ASSERT(column);
2920
2921             GtkWidget *gtkTreeHeader = column->button;
2922             GtkStateType state = gtkPainter.gtkState(option);
2923             GtkShadowType shadow = GTK_SHADOW_OUT;
2924
2925             if (option->state & State_Sunken)
2926                 shadow = GTK_SHADOW_IN;
2927             
2928             gtkPainter.paintBox(gtkTreeHeader, "button",  option->rect.adjusted(-1, 0, 0, 0), state, shadow, d->gtk_widget_get_style(gtkTreeHeader));
2929         }
2930
2931         painter->restore();
2932         break;
2933
2934 #ifndef QT_NO_SIZEGRIP
2935
2936     case CE_SizeGrip: {
2937         GtkWidget *gtkStatusbar = d->gtkWidget("GtkStatusbar.GtkFrame");
2938         GtkStyle *gtkStatusbarStyle = d->gtk_widget_get_style(gtkStatusbar);
2939         QRect gripRect = option->rect.adjusted(0, 0, -gtkStatusbarStyle->xthickness, -gtkStatusbarStyle->ythickness);
2940         gtkPainter.paintResizeGrip( gtkStatusbar, "statusbar", gripRect, GTK_STATE_NORMAL,
2941                                     GTK_SHADOW_OUT, QApplication::isRightToLeft() ?
2942                                         GDK_WINDOW_EDGE_SOUTH_WEST : GDK_WINDOW_EDGE_SOUTH_EAST,
2943                                     gtkStatusbarStyle);
2944     }
2945     break;
2946
2947 #endif // QT_NO_SIZEGRIP
2948
2949     case CE_MenuBarEmptyArea: {
2950         GtkWidget *gtkMenubar = d->gtkWidget("GtkMenuBar");
2951         GdkColor gdkBg = d->gtk_widget_get_style(gtkMenubar)->bg[GTK_STATE_NORMAL]; // Theme can depend on transparency
2952         painter->fillRect(option->rect, QColor(gdkBg.red>>8, gdkBg.green>>8, gdkBg.blue>>8));
2953         if (widget) { // See CE_MenuBarItem
2954             QRect menuBarRect = widget->rect();
2955             QPixmap pixmap(menuBarRect.size());
2956             pixmap.fill(Qt::transparent);
2957             QPainter pmPainter(&pixmap);
2958             QGtkPainter gtkMenuBarPainter(&pmPainter);
2959             GtkShadowType shadow_type;
2960             d->gtk_widget_style_get(gtkMenubar, "shadow-type", &shadow_type, NULL);
2961             gtkMenuBarPainter.paintBox( gtkMenubar, "menubar",  menuBarRect,
2962                                         GTK_STATE_NORMAL, shadow_type, d->gtk_widget_get_style(gtkMenubar));
2963             pmPainter.end();
2964             painter->drawPixmap(option->rect, pixmap, option->rect);
2965         }
2966     }
2967     break;
2968
2969     case CE_MenuBarItem:
2970         painter->save();
2971
2972         if (const QStyleOptionMenuItem *mbi = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) {
2973             GtkWidget *gtkMenubarItem = d->gtkWidget("GtkMenuBar.GtkMenuItem");
2974             GtkWidget *gtkMenubar = d->gtkWidget("GtkMenuBar");
2975
2976             style = d->gtk_widget_get_style(gtkMenubarItem);
2977
2978             if (widget) {
2979                 // Since Qt does not currently allow filling the entire background
2980                 // we use a hack for this by making a complete menubar each time and
2981                 // paint with the correct offset inside it. Pixmap caching should resolve
2982                 // most of the performance penalty.
2983                 QRect menuBarRect = widget->rect();
2984                 QPixmap pixmap(menuBarRect.size());
2985                 pixmap.fill(Qt::transparent);
2986                 QPainter pmPainter(&pixmap);
2987                 QGtkPainter menubarPainter(&pmPainter);
2988                 GtkShadowType shadow_type;
2989                 d->gtk_widget_style_get(gtkMenubar, "shadow-type", &shadow_type, NULL);
2990                 GdkColor gdkBg = d->gtk_widget_get_style(gtkMenubar)->bg[GTK_STATE_NORMAL]; // Theme can depend on transparency
2991                 painter->fillRect(option->rect, QColor(gdkBg.red>>8, gdkBg.green>>8, gdkBg.blue>>8));
2992                 menubarPainter.paintBox(gtkMenubar, "menubar",  menuBarRect,
2993                                         GTK_STATE_NORMAL, shadow_type, d->gtk_widget_get_style(gtkMenubar));
2994                 pmPainter.end();
2995                 painter->drawPixmap(option->rect, pixmap, option->rect);
2996             }
2997
2998             QStyleOptionMenuItem item = *mbi;
2999             bool act = mbi->state & State_Selected && mbi->state & State_Sunken;
3000             bool dis = !(mbi->state & State_Enabled);
3001             item.rect = mbi->rect;
3002             GdkColor gdkText = style->fg[dis ? GTK_STATE_INSENSITIVE : GTK_STATE_NORMAL];
3003             GdkColor gdkHText = style->fg[GTK_STATE_PRELIGHT];
3004             QColor normalTextColor = QColor(gdkText.red>>8, gdkText.green>>8, gdkText.blue>>8);
3005             QColor highlightedTextColor = QColor(gdkHText.red>>8, gdkHText.green>>8, gdkHText.blue>>8);
3006             item.palette.setBrush(QPalette::HighlightedText, highlightedTextColor);
3007             item.palette.setBrush(QPalette::Text, normalTextColor);
3008             item.palette.setBrush(QPalette::ButtonText, normalTextColor);
3009             QCommonStyle::drawControl(element, &item, painter, widget);
3010
3011             if (act) {
3012                 GtkShadowType shadowType = GTK_SHADOW_NONE;
3013                 d->gtk_widget_style_get (gtkMenubarItem, "selected-shadow-type", &shadowType, NULL);
3014                 gtkPainter.paintBox(gtkMenubarItem, "menuitem",  option->rect.adjusted(0, 0, 0, 3),
3015                                     GTK_STATE_PRELIGHT, shadowType, style);
3016                 //draw text
3017                 QPalette::ColorRole textRole = dis ? QPalette::Text : QPalette::HighlightedText;
3018                 uint alignment = Qt::AlignCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine;
3019
3020                 if (!proxy()->styleHint(SH_UnderlineShortcut, mbi, widget))
3021                     alignment |= Qt::TextHideMnemonic;
3022
3023                 proxy()->drawItemText(painter, item.rect, alignment, item.palette, mbi->state & State_Enabled, mbi->text, textRole);
3024             }
3025         }
3026         painter->restore();
3027         break;
3028
3029     case CE_Splitter: {
3030         GtkWidget *gtkWindow = d->gtkWidget("GtkWindow"); // The Murrine Engine currently assumes a widget is passed
3031         gtkPainter.paintHandle(gtkWindow, "splitter", option->rect, gtkPainter.gtkState(option), GTK_SHADOW_NONE,
3032                                 !(option->state & State_Horizontal) ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL,
3033                                 style);
3034     }
3035     break;
3036
3037 #ifndef QT_NO_TOOLBAR
3038
3039     case CE_ToolBar:
3040         if (const QStyleOptionToolBar *toolbar = qstyleoption_cast<const QStyleOptionToolBar *>(option)) {
3041             // Reserve the beveled appearance only for mainwindow toolbars
3042             if (!(widget && qobject_cast<const QMainWindow*> (widget->parentWidget())))
3043                 break;
3044
3045             QRect rect = option->rect;
3046             // There is a 1 pixel gap between toolbar lines in some styles (i.e Human)
3047             if (toolbar->positionWithinLine != QStyleOptionToolBar::End)
3048                 rect.adjust(0, 0, 1, 0);
3049
3050             GtkWidget *gtkToolbar = d->gtkWidget("GtkToolbar");
3051             GtkShadowType shadow_type = GTK_SHADOW_NONE;
3052             d->gtk_widget_style_get(gtkToolbar, "shadow-type", &shadow_type, NULL);
3053             gtkPainter.paintBox( gtkToolbar, "toolbar",  rect,
3054                                  GTK_STATE_NORMAL, shadow_type, d->gtk_widget_get_style(gtkToolbar));
3055         }
3056         break;
3057
3058 #endif // QT_NO_TOOLBAR
3059
3060     case CE_MenuItem:
3061         painter->save();
3062
3063         // Draws one item in a popup menu.
3064         if (const QStyleOptionMenuItem *menuItem = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) {
3065             const int windowsItemFrame        =  2; // menu item frame width
3066             const int windowsItemHMargin      =  3; // menu item hor text margin
3067             const int windowsItemVMargin      = 26; // menu item ver text margin
3068             const int windowsRightBorder      = 15; // right border on windows
3069             GtkWidget *gtkMenuItem = menuItem->checked ? d->gtkWidget("GtkMenu.GtkCheckMenuItem") :
3070                                      d->gtkWidget("GtkMenu.GtkMenuItem");
3071
3072             style = gtkPainter.getStyle(gtkMenuItem);
3073             QColor shadow = option->palette.dark().color();
3074
3075             if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) {
3076                 GtkWidget *gtkMenuSeparator = d->gtkWidget("GtkMenu.GtkSeparatorMenuItem");
3077                 painter->setPen(shadow.lighter(106));
3078                 gboolean wide_separators = 0;
3079                 gint     separator_height = 0;
3080                 guint    horizontal_padding = 3;
3081                 QRect separatorRect = option->rect;
3082                 if (!d->gtk_check_version(2, 10, 0)) {
3083                     d->gtk_widget_style_get(gtkMenuSeparator,
3084                                            "wide-separators",    &wide_separators,
3085                                            "separator-height",   &separator_height,
3086                                            "horizontal-padding", &horizontal_padding,
3087                                            NULL);
3088                 }
3089                 GtkStyle *gtkMenuSeparatorStyle = d->gtk_widget_get_style(gtkMenuSeparator);
3090                 separatorRect.setHeight(option->rect.height() - 2 * gtkMenuSeparatorStyle->ythickness);
3091                 separatorRect.setWidth(option->rect.width() - 2 * (horizontal_padding + gtkMenuSeparatorStyle->xthickness));
3092                 separatorRect.moveCenter(option->rect.center());
3093                 if (wide_separators)
3094                    gtkPainter.paintBox( gtkMenuSeparator, "hseparator",
3095                                         separatorRect, GTK_STATE_NORMAL, GTK_SHADOW_NONE, gtkMenuSeparatorStyle);
3096                 else
3097                     gtkPainter.paintHline( gtkMenuSeparator, "hseparator",
3098                                            separatorRect, GTK_STATE_NORMAL, gtkMenuSeparatorStyle,
3099                                            0, option->rect.right() - 1, 1);
3100                 painter->restore();
3101                 break;
3102             }
3103
3104             bool selected = menuItem->state & State_Selected && menuItem->state & State_Enabled;
3105
3106             if (selected) {
3107                 QRect rect = option->rect;
3108 #ifndef QT_NO_COMBOBOX
3109                 if (qobject_cast<const QComboBox*>(widget))
3110                     rect = option->rect;
3111 #endif
3112                 gtkPainter.paintBox( gtkMenuItem, "menuitem", rect, GTK_STATE_PRELIGHT, GTK_SHADOW_OUT, style);
3113             }
3114
3115             bool checkable = menuItem->checkType != QStyleOptionMenuItem::NotCheckable;
3116             bool checked = menuItem->checked;
3117             bool enabled = menuItem->state & State_Enabled;
3118             bool ignoreCheckMark = false;
3119
3120             gint checkSize;
3121             d->gtk_widget_style_get(d->gtkWidget("GtkMenu.GtkCheckMenuItem"), "indicator-size", &checkSize, NULL);
3122
3123             int checkcol = qMax(menuItem->maxIconWidth, qMax(20, checkSize));
3124
3125 #ifndef QT_NO_COMBOBOX
3126
3127             if (qobject_cast<const QComboBox*>(widget))
3128                 ignoreCheckMark = true; // Ignore the checkmarks provided by the QComboMenuDelegate
3129
3130 #endif
3131             if (!ignoreCheckMark) {
3132                 // Check
3133                 QRect checkRect(option->rect.left() + 7, option->rect.center().y() - checkSize/2 + 1, checkSize, checkSize);
3134                 checkRect = visualRect(menuItem->direction, menuItem->rect, checkRect);
3135
3136                 if (checkable && menuItem->icon.isNull()) {
3137                     // Some themes such as aero-clone draw slightly outside the paint rect
3138                     int spacing = 1; // ### Consider using gtkCheckBox : "indicator-spacing" instead
3139
3140                     if (menuItem->checkType & QStyleOptionMenuItem::Exclusive) {
3141                         // Radio button
3142                         GtkShadowType shadow = GTK_SHADOW_OUT;
3143                         GtkStateType state = gtkPainter.gtkState(option);
3144
3145                         if (selected)
3146                             state = GTK_STATE_PRELIGHT;
3147                         if (checked)
3148                             shadow = GTK_SHADOW_IN;
3149
3150                         gtkPainter.setClipRect(checkRect.adjusted(-spacing, -spacing, spacing, spacing));
3151                         gtkPainter.paintOption(gtkMenuItem, checkRect.translated(-spacing, -spacing), state, shadow,
3152                                                style, QLS("option"));
3153                         gtkPainter.setClipRect(QRect());
3154
3155                     } else {
3156                         // Check box
3157                         if (menuItem->icon.isNull()) {
3158                             GtkShadowType shadow = GTK_SHADOW_OUT;
3159                             GtkStateType state = gtkPainter.gtkState(option);
3160
3161                             if (selected)
3162                                 state = GTK_STATE_PRELIGHT;
3163                             if (checked)
3164                                 shadow = GTK_SHADOW_IN;
3165
3166                             gtkPainter.setClipRect(checkRect.adjusted(-spacing, -spacing, -spacing, -spacing));
3167                             gtkPainter.paintCheckbox(gtkMenuItem, checkRect.translated(-spacing, -spacing), state, shadow,
3168                                                      style, QLS("check"));
3169                            gtkPainter.setClipRect(QRect());
3170                         }
3171                     }
3172                 }
3173
3174             } else {
3175                 // Ignore checkmark
3176                 if (menuItem->icon.isNull())
3177                     checkcol = 0;
3178                 else
3179                     checkcol = menuItem->maxIconWidth;
3180             }
3181
3182             bool dis = !(menuItem->state & State_Enabled);
3183             bool act = menuItem->state & State_Selected;
3184             const QStyleOption *opt = option;
3185             const QStyleOptionMenuItem *menuitem = menuItem;
3186             QPainter *p = painter;
3187             QRect vCheckRect = visualRect(opt->direction, menuitem->rect,
3188                                           QRect(menuitem->rect.x() + 3, menuitem->rect.y(),
3189                                                 checkcol, menuitem->rect.height()));
3190
3191             if (!menuItem->icon.isNull()) {
3192                 QIcon::Mode mode = dis ? QIcon::Disabled : QIcon::Normal;
3193
3194                 if (act && !dis)
3195                     mode = QIcon::Active;
3196
3197                 QPixmap pixmap;
3198                 int smallIconSize = proxy()->pixelMetric(PM_SmallIconSize, option, widget);
3199                 QSize iconSize(smallIconSize, smallIconSize);
3200
3201 #ifndef QT_NO_COMBOBOX
3202                 if (const QComboBox *combo = qobject_cast<const QComboBox*>(widget))
3203                     iconSize = combo->iconSize();
3204
3205 #endif // QT_NO_COMBOBOX
3206                 if (checked)
3207                     pixmap = menuItem->icon.pixmap(iconSize, mode, QIcon::On);
3208                 else
3209                     pixmap = menuItem->icon.pixmap(iconSize, mode);
3210
3211                 int pixw = pixmap.width();
3212                 int pixh = pixmap.height();
3213                 QRect pmr(0, 0, pixw, pixh);
3214                 pmr.moveCenter(vCheckRect.center() - QPoint(0, 1));
3215                 painter->setPen(menuItem->palette.text().color());
3216                 if (!ignoreCheckMark && checkable && checked) {
3217                     QStyleOption opt = *option;
3218
3219                     if (act) {
3220                         QColor activeColor = mergedColors(option->palette.background().color(),
3221                                                           option->palette.highlight().color());
3222                         opt.palette.setBrush(QPalette::Button, activeColor);
3223                     }
3224                     opt.state |= State_Sunken;
3225                     opt.rect = vCheckRect;
3226                     proxy()->drawPrimitive(PE_PanelButtonCommand, &opt, painter, widget);
3227                 }
3228                 painter->drawPixmap(pmr.topLeft(), pixmap);
3229             }
3230
3231             GdkColor gdkText = style->fg[GTK_STATE_NORMAL];
3232             GdkColor gdkDText = style->fg[GTK_STATE_INSENSITIVE];
3233             GdkColor gdkHText = style->fg[GTK_STATE_PRELIGHT];
3234             uint resolve_mask = option->palette.resolve();
3235             QColor textColor = QColor(gdkText.red>>8, gdkText.green>>8, gdkText.blue>>8);
3236             QColor disabledTextColor = QColor(gdkDText.red>>8, gdkDText.green>>8, gdkDText.blue>>8);
3237             if (resolve_mask & (1 << QPalette::ButtonText)) {
3238                 textColor = option->palette.buttonText().color();
3239                 disabledTextColor = option->palette.brush(QPalette::Disabled, QPalette::ButtonText).color();
3240             }
3241
3242             QColor highlightedTextColor = QColor(gdkHText.red>>8, gdkHText.green>>8, gdkHText.blue>>8);
3243             if (resolve_mask & (1 << QPalette::HighlightedText)) {
3244                 highlightedTextColor = option->palette.highlightedText().color();
3245             }
3246
3247             if (selected)
3248                 painter->setPen(highlightedTextColor);
3249             else
3250                 painter->setPen(textColor);
3251
3252             int x, y, w, h;
3253             menuitem->rect.getRect(&x, &y, &w, &h);
3254             int tab = menuitem->tabWidth;
3255             int xm = windowsItemFrame + checkcol + windowsItemHMargin;
3256             int xpos = menuitem->rect.x() + xm + 1;
3257             QRect textRect(xpos, y + windowsItemVMargin, w - xm - windowsRightBorder - tab + 1, h - 2 * windowsItemVMargin);
3258             QRect vTextRect = visualRect(opt->direction, menuitem->rect, textRect);
3259             QString s = menuitem->text;
3260
3261             if (!s.isEmpty()) { // Draw text
3262                 p->save();
3263                 int t = s.indexOf(QLatin1Char('\t'));
3264                 int text_flags = Qt::AlignVCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine;
3265
3266                 if (!proxy()->styleHint(SH_UnderlineShortcut, menuitem, widget))
3267                     text_flags |= Qt::TextHideMnemonic;
3268
3269                 // Draw shortcut right aligned
3270                 text_flags |= Qt::AlignRight;
3271
3272                 if (t >= 0) {
3273                     int rightMargin = 12; // Hardcode for now
3274                     QRect vShortcutRect = visualRect(opt->direction, menuitem->rect,
3275                                                      QRect(textRect.topRight(), QPoint(menuitem->rect.right() - rightMargin, textRect.bottom())));
3276
3277                     if (dis)
3278                         p->setPen(disabledTextColor);
3279                     p->drawText(vShortcutRect, text_flags , s.mid(t + 1));
3280                     s = s.left(t);
3281                 }
3282
3283                 text_flags &= ~Qt::AlignRight;
3284                 text_flags |= Qt::AlignLeft;
3285                 QFont font = menuitem->font;
3286                 if (menuitem->menuItemType == QStyleOptionMenuItem::DefaultItem)
3287                     font.setBold(true);
3288                 p->setFont(font);
3289
3290                 if (dis)
3291                     p->setPen(disabledTextColor);
3292                 p->drawText(vTextRect, text_flags, s.left(t));
3293                 p->restore();
3294             }
3295
3296             // Arrow
3297             if (menuItem->menuItemType == QStyleOptionMenuItem::SubMenu) {// draw sub menu arrow
3298
3299                 QFontMetrics fm(menuitem->font);
3300                 int arrow_size = fm.ascent() + fm.descent() - 2 * style->ythickness;
3301                 gfloat arrow_scaling = 0.8;
3302                 int extra = 0;
3303                 if (!d->gtk_check_version(2, 16, 0)) {
3304                     // "arrow-scaling" is actually hardcoded and fails on hardy (see gtk+-2.12/gtkmenuitem.c)
3305                     // though the current documentation states otherwise
3306                     d->gtk_widget_style_get(gtkMenuItem, "arrow-scaling", &arrow_scaling, NULL);
3307                     // in versions < 2.16 ythickness was previously subtracted from the arrow_size
3308                     extra = 2 * style->ythickness;
3309                 }
3310
3311                 int horizontal_padding;
3312                 d->gtk_widget_style_get(gtkMenuItem, "horizontal-padding", &horizontal_padding, NULL);
3313
3314                 const int dim = static_cast<int>(arrow_size * arrow_scaling) + extra;
3315                 int xpos = menuItem->rect.left() + menuItem->rect.width() - horizontal_padding - dim;
3316                 QRect  vSubMenuRect = visualRect(option->direction, menuItem->rect,
3317                                                  QRect(xpos, menuItem->rect.top() +
3318                                                        menuItem->rect.height() / 2 - dim / 2, dim, dim));
3319                 GtkStateType state = enabled ? (act ? GTK_STATE_PRELIGHT: GTK_STATE_NORMAL) : GTK_STATE_INSENSITIVE;
3320                 GtkShadowType shadowType = (state == GTK_STATE_PRELIGHT) ? GTK_SHADOW_OUT : GTK_SHADOW_IN;
3321                 gtkPainter.paintArrow(gtkMenuItem, "menuitem", vSubMenuRect, QApplication::isRightToLeft() ? GTK_ARROW_LEFT : GTK_ARROW_RIGHT, state,
3322                                       shadowType, false, style);
3323             }
3324         }
3325         painter->restore();
3326         break;
3327
3328     case CE_PushButton:
3329         if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) {
3330             GtkWidget *gtkButton = d->gtkWidget("GtkButton");
3331             proxy()->drawControl(CE_PushButtonBevel, btn, painter, widget);
3332             QStyleOptionButton subopt = *btn;
3333             subopt.rect = subElementRect(SE_PushButtonContents, btn, widget);
3334             gint interiorFocus = true;
3335             d->gtk_widget_style_get(gtkButton, "interior-focus", &interiorFocus, NULL);
3336             GtkStyle *gtkButtonStyle = d->gtk_widget_get_style(gtkButton);
3337             int xt = interiorFocus ? gtkButtonStyle->xthickness : 0;
3338             int yt = interiorFocus ? gtkButtonStyle->ythickness : 0;
3339
3340             if (btn->features & QStyleOptionButton::Flat && btn->state & State_HasFocus)
3341                 // The normal button focus rect does not work well for flat buttons in Clearlooks
3342                 proxy()->drawPrimitive(PE_FrameFocusRect, option, painter, widget);
3343             else if (btn->state & State_HasFocus)
3344                 gtkPainter.paintFocus(gtkButton, "button",
3345                                       option->rect.adjusted(xt, yt, -xt, -yt),
3346                                       btn->state & State_Sunken ? GTK_STATE_ACTIVE : GTK_STATE_NORMAL,
3347                                       gtkButtonStyle);
3348
3349             proxy()->drawControl(CE_PushButtonLabel, &subopt, painter, widget);
3350         }
3351         break;
3352
3353 #ifndef QT_NO_TABBAR
3354
3355     case CE_TabBarTabShape:
3356         if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(option)) {
3357             GtkWidget *gtkNotebook = d->gtkWidget("GtkNotebook");
3358             style = gtkPainter.getStyle(gtkNotebook);
3359
3360             QRect rect = option->rect;
3361             GtkShadowType shadow = GTK_SHADOW_OUT;
3362             GtkStateType state = GTK_STATE_ACTIVE;
3363             if (tab->state & State_Selected)
3364                 state = GTK_STATE_NORMAL;
3365
3366             bool selected = (tab->state & State_Selected);
3367             bool first = false, last = false;
3368             if (widget) {
3369                 // This is most accurate and avoids resizing tabs while moving
3370                 first = tab->rect.left() == widget->rect().left();
3371                 last = tab->rect.right() == widget->rect().right();
3372             } else if (option->direction == Qt::RightToLeft) {
3373                 bool tmp = first;
3374                 first = last;
3375                 last = tmp;
3376             }
3377             int topIndent = 3;
3378             int bottomIndent = 1;
3379             int tabOverlap = 1;
3380             painter->save();
3381
3382             switch (tab->shape) {
3383             case QTabBar::RoundedNorth:
3384                 if (!selected)
3385                     rect.adjust(first ? 0 : -tabOverlap, topIndent, last ? 0 : tabOverlap, -bottomIndent);
3386                 gtkPainter.paintExtention( gtkNotebook, "tab", rect,
3387                                            state, shadow, GTK_POS_BOTTOM, style);
3388                 break;
3389
3390             case QTabBar::RoundedSouth:
3391                 if (!selected)
3392                     rect.adjust(first ? 0 : -tabOverlap, 0, last ? 0 : tabOverlap, -topIndent);
3393                 gtkPainter.paintExtention( gtkNotebook, "tab", rect.adjusted(0, 1, 0, 0),
3394                                            state, shadow, GTK_POS_TOP, style);
3395                 break;
3396
3397             case QTabBar::RoundedWest:
3398                 if (!selected)
3399                     rect.adjust(topIndent, 0, -bottomIndent, 0);
3400                 gtkPainter.paintExtention( gtkNotebook, "tab", rect, state, shadow, GTK_POS_RIGHT, style);
3401                 break;
3402
3403             case QTabBar::RoundedEast:
3404                 if (!selected)
3405                     rect.adjust(bottomIndent, 0, -topIndent, 0);
3406                 gtkPainter.paintExtention( gtkNotebook, "tab", rect, state, shadow, GTK_POS_LEFT, style);
3407                 break;
3408
3409             default:
3410                 QWindowsStyle::drawControl(element, option, painter, widget);
3411                 break;
3412             }
3413
3414             painter->restore();
3415         }
3416
3417         break;
3418
3419 #endif //QT_NO_TABBAR
3420
3421     case CE_ProgressBarGroove:
3422         if (const QStyleOptionProgressBar *bar = qstyleoption_cast<const QStyleOptionProgressBar *>(option)) {
3423             Q_UNUSED(bar);
3424             GtkWidget *gtkProgressBar = d->gtkWidget("GtkProgressBar");
3425             GtkStateType state = gtkPainter.gtkState(option);
3426             gtkPainter.paintBox( gtkProgressBar, "trough",  option->rect, state, GTK_SHADOW_IN, d->gtk_widget_get_style(gtkProgressBar));
3427         }
3428
3429         break;
3430
3431     case CE_ProgressBarContents:
3432         if (const QStyleOptionProgressBar *bar = qstyleoption_cast<const QStyleOptionProgressBar *>(option)) {
3433             GtkStateType state = option->state & State_Enabled ? GTK_STATE_NORMAL : GTK_STATE_INSENSITIVE;
3434             GtkWidget *gtkProgressBar = d->gtkWidget("GtkProgressBar");
3435             style = d->gtk_widget_get_style(gtkProgressBar);
3436             gtkPainter.paintBox( gtkProgressBar, "trough",  option->rect, state, GTK_SHADOW_IN, style);
3437             int xt = style->xthickness;
3438             int yt = style->ythickness;
3439             QRect rect = bar->rect.adjusted(xt, yt, -xt, -yt);
3440             bool vertical = false;
3441             bool inverted = false;
3442             bool indeterminate = (bar->minimum == 0 && bar->maximum == 0);
3443             // Get extra style options if version 2
3444
3445             if (const QStyleOptionProgressBarV2 *bar2 = qstyleoption_cast<const QStyleOptionProgressBarV2 *>(option)) {
3446                 vertical = (bar2->orientation == Qt::Vertical);
3447                 inverted = bar2->invertedAppearance;
3448             }
3449
3450             // If the orientation is vertical, we use a transform to rotate
3451             // the progress bar 90 degrees clockwise.  This way we can use the
3452             // same rendering code for both orientations.
3453             if (vertical) {
3454                 rect.translate(xt, -yt * 2);
3455                 rect = QRect(rect.left(), rect.top(), rect.height(), rect.width()); // Flip width and height
3456                 QTransform m = QTransform::fromTranslate(rect.height(), 0);
3457                 m.rotate(90.0);
3458                 painter->setTransform(m);
3459             }
3460
3461             int maxWidth = rect.width();
3462             int minWidth = 4;
3463
3464             qint64 progress = (qint64)qMax(bar->progress, bar->minimum); // Workaround for bug in QProgressBar
3465             double vc6_workaround = ((progress - qint64(bar->minimum)) / double(qint64(bar->maximum) - qint64(bar->minimum))) * maxWidth;
3466             int progressBarWidth = (int(vc6_workaround) > minWidth ) ? int(vc6_workaround) : minWidth;
3467             int width = indeterminate ? maxWidth : progressBarWidth;
3468             bool reverse = (!vertical && (bar->direction == Qt::RightToLeft)) || vertical;
3469
3470             if (inverted)
3471                 reverse = !reverse;
3472
3473             int maximum = 2;
3474             int fakePos = 0;
3475             if (bar->minimum == bar->maximum)
3476                 maximum = 0;
3477             if (bar->progress == bar->maximum)
3478                 fakePos = maximum;
3479             else if (bar->progress > bar->minimum)
3480                 fakePos = maximum - 1;
3481
3482             d->gtk_progress_configure((GtkProgress*)gtkProgressBar, fakePos, 0, maximum);
3483
3484             QRect progressBar;
3485
3486             if (!indeterminate) {
3487                 if (!reverse)
3488                     progressBar.setRect(rect.left(), rect.top(), width, rect.height());
3489                 else
3490                     progressBar.setRect(rect.right() - width, rect.top(), width, rect.height());
3491
3492             } else {
3493                 Q_D(const QGtkStyle);
3494                 int slideWidth = ((rect.width() - 4) * 2) / 3;
3495                 int step = ((d->animateStep * slideWidth) / d->animationFps) % slideWidth;
3496                 if ((((d->animateStep * slideWidth) / d->animationFps) % (2 * slideWidth)) >= slideWidth)
3497                     step = slideWidth - step;
3498                 progressBar.setRect(rect.left() + step, rect.top(), slideWidth / 2, rect.height());
3499             }
3500
3501             QString key = QString(QLS("%0")).arg(fakePos);
3502             if (inverted) {
3503                 key += QLatin1String("inv");
3504                 gtkPainter.setFlipHorizontal(true);
3505             }
3506             gtkPainter.paintBox( gtkProgressBar, "bar",  progressBar, GTK_STATE_SELECTED, GTK_SHADOW_OUT, style, key);
3507         }
3508
3509         break;
3510
3511     default:
3512         QWindowsStyle::drawControl(element, option, painter, widget);
3513     }
3514 }
3515
3516 /*!
3517   \reimp
3518 */
3519 QRect QGtkStyle::subControlRect(ComplexControl control, const QStyleOptionComplex *option,
3520                                 SubControl subControl, const QWidget *widget) const
3521 {
3522     Q_D(const QGtkStyle);
3523
3524     QRect rect = QWindowsStyle::subControlRect(control, option, subControl, widget);
3525     if (!d->isThemeAvailable())
3526         return QWindowsStyle::subControlRect(control, option, subControl, widget);
3527
3528     switch (control) {
3529     case CC_ScrollBar:
3530         break;
3531     case CC_Slider:
3532         if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
3533             int tickSize = proxy()->pixelMetric(PM_SliderTickmarkOffset, option, widget);
3534             switch (subControl) {
3535             case SC_SliderHandle: {
3536                 if (slider->orientation == Qt::Horizontal) {
3537                     rect.setHeight(proxy()->pixelMetric(PM_SliderThickness));
3538                     rect.setWidth(proxy()->pixelMetric(PM_SliderLength));
3539                     int centerY = slider->rect.center().y() - rect.height() / 2;
3540                     if (slider->tickPosition & QSlider::TicksAbove)
3541                         centerY += tickSize;
3542                     if (slider->tickPosition & QSlider::TicksBelow)
3543                         centerY -= tickSize;
3544                     rect.moveTop(centerY);
3545                 } else {
3546                     rect.setWidth(proxy()->pixelMetric(PM_SliderThickness));
3547                     rect.setHeight(proxy()->pixelMetric(PM_SliderLength));
3548                     int centerX = slider->rect.center().x() - rect.width() / 2;
3549                     if (slider->tickPosition & QSlider::TicksAbove)
3550                         centerX += tickSize;
3551                     if (slider->tickPosition & QSlider::TicksBelow)
3552                         centerX -= tickSize;
3553                     rect.moveLeft(centerX);
3554                 }
3555             }
3556                 break;
3557             case SC_SliderGroove: {
3558                 QPoint grooveCenter = slider->rect.center();
3559                 if (slider->orientation == Qt::Horizontal) {
3560                     rect.setHeight(7);
3561                     if (slider->tickPosition & QSlider::TicksAbove)
3562                         grooveCenter.ry() += tickSize;
3563                     if (slider->tickPosition & QSlider::TicksBelow)
3564                         grooveCenter.ry() -= tickSize;
3565                 } else {
3566                     rect.setWidth(7);
3567                     if (slider->tickPosition & QSlider::TicksAbove)
3568                         grooveCenter.rx() += tickSize;
3569                     if (slider->tickPosition & QSlider::TicksBelow)
3570                         grooveCenter.rx() -= tickSize;
3571                 }
3572                 rect.moveCenter(grooveCenter);
3573                 break;
3574             }
3575             default:
3576                 break;
3577             }
3578         }
3579         break;
3580
3581 #ifndef QT_NO_GROUPBOX
3582
3583     case CC_GroupBox:
3584         if (qstyleoption_cast<const QStyleOptionGroupBox *>(option)) {
3585             rect = option->rect.adjusted(0, groupBoxTopMargin, 0, -groupBoxBottomMargin);
3586             int topMargin = 0;
3587             int topHeight = 0;
3588             topHeight = 10;
3589             QRect frameRect = rect;
3590             frameRect.setTop(topMargin);
3591
3592             if (subControl == SC_GroupBoxFrame)
3593                 return rect;
3594             else if (subControl == SC_GroupBoxContents) {
3595                 int margin = 0;
3596                 int leftMarginExtension = 8;
3597                 return frameRect.adjusted(leftMarginExtension + margin, margin + topHeight + groupBoxTitleMargin, -margin, -margin);
3598             }
3599
3600             if (const QGroupBox *groupBoxWidget = qobject_cast<const QGroupBox *>(widget)) {
3601                 //Prepare metrics for a bold font
3602                 QFont font = widget->font();
3603                 font.setBold(true);
3604                 QFontMetrics fontMetrics(font);
3605                 QSize textRect = fontMetrics.boundingRect(groupBoxWidget->title()).size() + QSize(4, 4);
3606                 int indicatorWidth = proxy()->pixelMetric(PM_IndicatorWidth, option, widget);
3607                 int indicatorHeight = proxy()->pixelMetric(PM_IndicatorHeight, option, widget);
3608
3609                 if (subControl == SC_GroupBoxCheckBox) {
3610                     rect.setWidth(indicatorWidth);
3611                     rect.setHeight(indicatorHeight);
3612                     rect.moveTop((textRect.height() - indicatorHeight) / 2);
3613
3614                 } else if (subControl == SC_GroupBoxLabel) {
3615                     if (groupBoxWidget->isCheckable())
3616                         rect.adjust(indicatorWidth + 4, 0, 0, 0);
3617                     rect.setSize(textRect);
3618                 }
3619                 rect = visualRect(option->direction, option->rect, rect);
3620             }
3621         }
3622
3623         return rect;
3624
3625 #endif
3626 #ifndef QT_NO_SPINBOX
3627
3628     case CC_SpinBox:
3629         if (const QStyleOptionSpinBox *spinbox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) {
3630             GtkWidget *gtkSpinButton = d->gtkWidget("GtkSpinButton");
3631             int center = spinbox->rect.height() / 2;
3632             GtkStyle *gtkSpinButtonStyle = d->gtk_widget_get_style(gtkSpinButton);
3633             int xt = spinbox->frame ? gtkSpinButtonStyle->xthickness : 0;
3634             int yt = spinbox->frame ? gtkSpinButtonStyle->ythickness : 0;
3635             int y = yt;
3636
3637             QSize bs;
3638             bs.setHeight(qMax(8, spinbox->rect.height()/2 - y));
3639             bs.setWidth(d->getSpinboxArrowSize());
3640             int x, lx, rx;
3641             x = spinbox->rect.width() - y - bs.width() + 2;
3642             lx = xt;
3643             rx = x - xt;
3644
3645             switch (subControl) {
3646
3647             case SC_SpinBoxUp:
3648                 if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons)
3649                     return QRect();
3650                 rect = QRect(x, xt, bs.width(), center - yt);
3651                 break;
3652
3653             case SC_SpinBoxDown:
3654                 if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons)
3655                     return QRect();
3656                 rect = QRect(x, center, bs.width(), spinbox->rect.bottom() - center - yt + 1);
3657                 break;
3658
3659             case SC_SpinBoxEditField:
3660                 if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons)
3661                     rect = QRect(lx, yt, spinbox->rect.width() - 2*xt, spinbox->rect.height() - 2*yt);
3662                 else
3663                     rect = QRect(lx, yt, rx - qMax(xt - 1, 0), spinbox->rect.height() - 2*yt);
3664                 break;
3665
3666             case SC_SpinBoxFrame:
3667                 rect = spinbox->rect;
3668
3669             default:
3670                 break;
3671             }
3672
3673             rect = visualRect(spinbox->direction, spinbox->rect, rect);
3674         }
3675
3676         break;
3677
3678 #endif // Qt_NO_SPINBOX
3679 #ifndef QT_NO_COMBOBOX
3680
3681     case CC_TitleBar:
3682     if (const QStyleOptionTitleBar *tb = qstyleoption_cast<const QStyleOptionTitleBar *>(option)) {
3683         SubControl sc = subControl;
3684         QRect &ret = rect;
3685         const int indent = 3;
3686         const int controlTopMargin = 3;
3687         const int controlBottomMargin = 3;
3688         const int controlWidthMargin = 2;
3689         const int controlHeight = tb->rect.height() - controlTopMargin - controlBottomMargin ;
3690         const int delta = controlHeight + controlWidthMargin;
3691         int offset = 0;
3692
3693         bool isMinimized = tb->titleBarState & Qt::WindowMinimized;
3694         bool isMaximized = tb->titleBarState & Qt::WindowMaximized;
3695
3696         switch (sc) {
3697         case SC_TitleBarLabel:
3698             if (tb->titleBarFlags & (Qt::WindowTitleHint | Qt::WindowSystemMenuHint)) {
3699                 ret = tb->rect;
3700                 if (tb->titleBarFlags & Qt::WindowSystemMenuHint)
3701                     ret.adjust(delta, 0, -delta, 0);
3702                 if (tb->titleBarFlags & Qt::WindowMinimizeButtonHint)
3703                     ret.adjust(0, 0, -delta, 0);
3704                 if (tb->titleBarFlags & Qt::WindowMaximizeButtonHint)
3705                     ret.adjust(0, 0, -delta, 0);
3706                 if (tb->titleBarFlags & Qt::WindowShadeButtonHint)
3707                     ret.adjust(0, 0, -delta, 0);
3708                 if (tb->titleBarFlags & Qt::WindowContextHelpButtonHint)
3709                     ret.adjust(0, 0, -delta, 0);
3710             }
3711             break;
3712         case SC_TitleBarContextHelpButton:
3713             if (tb->titleBarFlags & Qt::WindowContextHelpButtonHint)
3714                 offset += delta;
3715         case SC_TitleBarMinButton:
3716             if (!isMinimized && (tb->titleBarFlags & Qt::WindowMinimizeButtonHint))
3717                 offset += delta;
3718             else if (sc == SC_TitleBarMinButton)
3719                 break;
3720         case SC_TitleBarNormalButton:
3721             if (isMinimized && (tb->titleBarFlags & Qt::WindowMinimizeButtonHint))
3722                 offset += delta;
3723             else if (isMaximized && (tb->titleBarFlags & Qt::WindowMaximizeButtonHint))
3724                 offset += delta;
3725             else if (sc == SC_TitleBarNormalButton)
3726                 break;
3727         case SC_TitleBarMaxButton:
3728             if (!isMaximized && (tb->titleBarFlags & Qt::WindowMaximizeButtonHint))
3729                 offset += delta;
3730             else if (sc == SC_TitleBarMaxButton)
3731                 break;
3732         case SC_TitleBarShadeButton:
3733             if (!isMinimized && (tb->titleBarFlags & Qt::WindowShadeButtonHint))
3734                 offset += delta;
3735             else if (sc == SC_TitleBarShadeButton)
3736                 break;
3737         case SC_TitleBarUnshadeButton:
3738             if (isMinimized && (tb->titleBarFlags & Qt::WindowShadeButtonHint))
3739                 offset += delta;
3740             else if (sc == SC_TitleBarUnshadeButton)
3741                 break;
3742         case SC_TitleBarCloseButton:
3743             if (tb->titleBarFlags & Qt::WindowSystemMenuHint)
3744                 offset += delta;
3745             else if (sc == SC_TitleBarCloseButton)
3746                 break;
3747             ret.setRect(tb->rect.right() - indent - offset, tb->rect.top() + controlTopMargin,
3748                         controlHeight, controlHeight);
3749             break;
3750         case SC_TitleBarSysMenu:
3751             if (tb->titleBarFlags & Qt::WindowSystemMenuHint) {
3752                 ret.setRect(tb->rect.left() + controlWidthMargin + indent, tb->rect.top() + controlTopMargin,
3753                             controlHeight, controlHeight);
3754             }
3755             break;
3756         default:
3757             break;
3758         }
3759         ret = visualRect(tb->direction, tb->rect, ret);
3760     }
3761     break;
3762     case CC_ComboBox:
3763         if (const QStyleOptionComboBox *box = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
3764             // We employ the gtk widget to position arrows and separators for us
3765             GtkWidget *gtkCombo = box->editable ? d->gtkWidget("GtkComboBoxEntry")
3766                                                 : d->gtkWidget("GtkComboBox");
3767             d->gtk_widget_set_direction(gtkCombo, (option->direction == Qt::RightToLeft) ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR);
3768             GtkAllocation geometry = {0, 0, qMax(0, option->rect.width()), qMax(0, option->rect.height())};
3769             d->gtk_widget_size_allocate(gtkCombo, &geometry);
3770             int appears_as_list = !proxy()->styleHint(QStyle::SH_ComboBox_Popup, option, widget);
3771             QHashableLatin1Literal arrowPath("GtkComboBoxEntry.GtkToggleButton");
3772             if (!box->editable) {
3773                 if (appears_as_list)
3774                     arrowPath = "GtkComboBox.GtkToggleButton";
3775                 else
3776                     arrowPath = "GtkComboBox.GtkToggleButton.GtkHBox.GtkArrow";
3777             }
3778
3779             GtkWidget *arrowWidget = d->gtkWidget(arrowPath);
3780             if (!arrowWidget)
3781                 return QWindowsStyle::subControlRect(control, option, subControl, widget);
3782
3783             GtkAllocation allocation;
3784             d->gtk_widget_get_allocation(arrowWidget, &allocation);
3785             QRect buttonRect(option->rect.left() + allocation.x,
3786                              option->rect.top() + allocation.y,
3787                              allocation.width, allocation.height);
3788
3789             switch (subControl) {
3790
3791             case SC_ComboBoxArrow: // Note: this indicates the arrowbutton for editable combos
3792                 rect = buttonRect;
3793                 break;
3794
3795             case SC_ComboBoxEditField: {
3796                 rect = visualRect(option->direction, option->rect, rect);
3797                 int xMargin = box->editable ? 1 : 4, yMargin = 2;
3798                 GtkStyle *gtkComboStyle = d->gtk_widget_get_style(gtkCombo);
3799                 rect.setRect(option->rect.left() + gtkComboStyle->xthickness + xMargin,
3800                              option->rect.top()  + gtkComboStyle->ythickness + yMargin,
3801                              option->rect.width() - buttonRect.width() - 2*(gtkComboStyle->xthickness + xMargin),
3802                              option->rect.height() - 2*(gtkComboStyle->ythickness + yMargin));
3803                 rect = visualRect(option->direction, option->rect, rect);
3804                 break;
3805             }
3806
3807             default:
3808                 break;
3809             }
3810         }
3811
3812         break;
3813 #endif // QT_NO_COMBOBOX
3814
3815     default:
3816         break;
3817     }
3818
3819     return rect;
3820 }
3821
3822 /*!
3823   \reimp
3824 */
3825 QSize QGtkStyle::sizeFromContents(ContentsType type, const QStyleOption *option,
3826                                   const QSize &size, const QWidget *widget) const
3827 {
3828     Q_D(const QGtkStyle);
3829
3830     QSize newSize = QWindowsStyle::sizeFromContents(type, option, size, widget);
3831     if (!d->isThemeAvailable())
3832         return newSize;
3833
3834     switch (type) {
3835     case CT_GroupBox:
3836         // Since we use a bold font we have to recalculate base width
3837         if (const QGroupBox *gb = qobject_cast<const QGroupBox*>(widget)) {
3838             QFont font = gb->font();
3839             font.setBold(true);
3840             QFontMetrics metrics(font);
3841             int baseWidth = metrics.width(gb->title()) + metrics.width(QLatin1Char(' '));
3842             if (gb->isCheckable()) {
3843                 baseWidth += proxy()->pixelMetric(QStyle::PM_IndicatorWidth, option, widget);
3844                 baseWidth += proxy()->pixelMetric(QStyle::PM_CheckBoxLabelSpacing, option, widget);
3845             }
3846             newSize.setWidth(qMax(baseWidth, newSize.width()));
3847         }
3848         newSize += QSize(4, 1 + groupBoxBottomMargin + groupBoxTopMargin + groupBoxTitleMargin); // Add some space below the groupbox
3849         break;
3850     case CT_ToolButton:
3851         if (const QStyleOptionToolButton *toolbutton = qstyleoption_cast<const QStyleOptionToolButton *>(option)) {
3852             GtkWidget *gtkButton = d->gtkWidget("GtkToolButton.GtkButton");
3853             GtkStyle *gtkButtonStyle = d->gtk_widget_get_style(gtkButton);
3854             newSize = size + QSize(2 * gtkButtonStyle->xthickness, 2 + 2 * gtkButtonStyle->ythickness);
3855             if (widget && qobject_cast<QToolBar *>(widget->parentWidget())) {
3856                 QSize minSize(0, 25);
3857                 if (toolbutton->toolButtonStyle != Qt::ToolButtonTextOnly)
3858                     minSize = toolbutton->iconSize + QSize(12, 12);
3859                 newSize = newSize.expandedTo(minSize);
3860             }
3861
3862             if (toolbutton->features & QStyleOptionToolButton::HasMenu)
3863                 newSize += QSize(6, 0);
3864         }
3865         break;
3866     case CT_MenuItem:
3867         if (const QStyleOptionMenuItem *menuItem = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) {
3868             int textMargin = 8;
3869
3870             if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) {
3871                 GtkWidget *gtkMenuSeparator = d->gtkWidget("GtkMenu.GtkSeparatorMenuItem");
3872                 GtkRequisition sizeReq = {0, 0};
3873                 d->gtk_widget_size_request(gtkMenuSeparator, &sizeReq);
3874                 newSize = QSize(size.width(), sizeReq.height);
3875                 break;
3876             }
3877
3878             GtkWidget *gtkMenuItem = d->gtkWidget("GtkMenu.GtkCheckMenuItem");
3879             GtkStyle* style = d->gtk_widget_get_style(gtkMenuItem);
3880
3881             // Note we get the perfect height for the default font since we
3882             // set a fake text label on the gtkMenuItem
3883             // But if custom fonts are used on the widget we need a minimum size
3884             GtkRequisition sizeReq = {0, 0};
3885             d->gtk_widget_size_request(gtkMenuItem, &sizeReq);
3886             newSize.setHeight(qMax(newSize.height() - 4, sizeReq.height));
3887             newSize += QSize(textMargin + style->xthickness - 1, 0);
3888
3889             gint checkSize;
3890             d->gtk_widget_style_get(gtkMenuItem, "indicator-size", &checkSize, NULL);
3891             newSize.setWidth(newSize.width() + qMax(0, checkSize - 20));
3892         }
3893         break;
3894     case CT_SpinBox:
3895         // QSpinBox does some nasty things that depends on CT_LineEdit
3896         newSize = size + QSize(0, -d->gtk_widget_get_style(d->gtkWidget("GtkSpinButton"))->ythickness * 2);
3897         break;
3898     case CT_RadioButton:
3899     case CT_CheckBox:
3900         newSize += QSize(0, 1);
3901         break;
3902     case CT_PushButton:
3903         if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) {
3904             if (!btn->icon.isNull() && btn->iconSize.height() > 16)
3905                 newSize -= QSize(0, 2); // From cleanlooksstyle
3906             newSize += QSize(0, 1);
3907             GtkWidget *gtkButton = d->gtkWidget("GtkButton");
3908             gint focusPadding, focusWidth;
3909             d->gtk_widget_style_get(gtkButton, "focus-padding", &focusPadding, NULL);
3910             d->gtk_widget_style_get(gtkButton, "focus-line-width", &focusWidth, NULL);
3911             newSize = size;
3912             GtkStyle *gtkButtonStyle = d->gtk_widget_get_style(gtkButton);
3913             newSize += QSize(2*gtkButtonStyle->xthickness + 4, 2*gtkButtonStyle->ythickness);
3914             newSize += QSize(2*(focusWidth + focusPadding + 2), 2*(focusWidth + focusPadding));
3915
3916             GtkWidget *gtkButtonBox = d->gtkWidget("GtkHButtonBox");
3917             gint minWidth = 85, minHeight = 0;
3918             d->gtk_widget_style_get(gtkButtonBox, "child-min-width", &minWidth,
3919                                    "child-min-height", &minHeight, NULL);
3920             if (!btn->text.isEmpty() && newSize.width() < minWidth)
3921                 newSize.setWidth(minWidth);
3922             if (newSize.height() < minHeight)
3923                 newSize.setHeight(minHeight);
3924         }
3925         break;
3926     case CT_Slider: {
3927         GtkWidget *gtkSlider = d->gtkWidget("GtkHScale");
3928         GtkStyle *gtkSliderStyle = d->gtk_widget_get_style(gtkSlider);
3929         newSize = size + QSize(2*gtkSliderStyle->xthickness, 2*gtkSliderStyle->ythickness); }
3930         break;
3931     case CT_LineEdit: {
3932         GtkWidget *gtkEntry = d->gtkWidget("GtkEntry");
3933         GtkStyle *gtkEntryStyle = d->gtk_widget_get_style(gtkEntry);
3934         newSize = size + QSize(2*gtkEntryStyle->xthickness, 2 + 2*gtkEntryStyle->ythickness); }
3935         break;
3936     case CT_ItemViewItem:
3937         newSize += QSize(0, 2);
3938         break;
3939     case CT_ComboBox:
3940         if (const QStyleOptionComboBox *combo = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
3941             GtkWidget *gtkCombo = d->gtkWidget("GtkComboBox");
3942             QRect arrowButtonRect = proxy()->subControlRect(CC_ComboBox, combo, SC_ComboBoxArrow, widget);
3943             GtkStyle *gtkComboStyle = d->gtk_widget_get_style(gtkCombo);
3944             newSize = size + QSize(12 + arrowButtonRect.width() + 2*gtkComboStyle->xthickness, 4 + 2*gtkComboStyle->ythickness);
3945
3946             if (!(widget && qobject_cast<QToolBar *>(widget->parentWidget())))
3947                 newSize += QSize(0, 2);
3948         }
3949         break;
3950     case CT_TabBarTab:
3951         if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(option)) {
3952             if (!tab->icon.isNull())
3953                 newSize += QSize(6, 0);
3954         }
3955         newSize += QSize(1, 1);
3956         break;
3957     case CT_MenuBarItem:
3958         newSize += QSize(0, 2);
3959         break;
3960     case CT_SizeGrip:
3961         newSize += QSize(4, 4);
3962         break;
3963     case CT_MdiControls:
3964         if (const QStyleOptionComplex *styleOpt = qstyleoption_cast<const QStyleOptionComplex *>(option)) {
3965             int width = 0;
3966             if (styleOpt->subControls & SC_MdiMinButton)
3967                 width += 19 + 1;
3968             if (styleOpt->subControls & SC_MdiNormalButton)
3969                 width += 19 + 1;
3970             if (styleOpt->subControls & SC_MdiCloseButton)
3971                 width += 19 + 1;
3972             newSize = QSize(width, 19);
3973         } else {
3974             newSize = QSize(60, 19);
3975         }
3976     break;
3977     default:
3978         break;
3979     }
3980
3981     return newSize;
3982 }
3983
3984
3985 /*! \reimp */
3986 QPixmap QGtkStyle::standardPixmap(StandardPixmap sp, const QStyleOption *option,
3987                                   const QWidget *widget) const
3988 {
3989     Q_D(const QGtkStyle);
3990
3991     if (!d->isThemeAvailable())
3992         return QWindowsStyle::standardPixmap(sp, option, widget);
3993
3994     QPixmap pixmap;
3995     switch (sp) {
3996
3997     case SP_TitleBarNormalButton: {
3998         QImage restoreButton((const char **)dock_widget_restore_xpm);
3999         QColor alphaCorner = restoreButton.color(2);
4000         alphaCorner.setAlpha(80);
4001         restoreButton.setColor(2, alphaCorner.rgba());
4002         alphaCorner.setAlpha(180);
4003         restoreButton.setColor(4, alphaCorner.rgba());
4004         return QPixmap::fromImage(restoreButton);
4005     }
4006     break;
4007
4008     case SP_TitleBarCloseButton: // Fall through
4009     case SP_DockWidgetCloseButton: {
4010
4011         QImage closeButton((const char **)dock_widget_close_xpm);
4012         QColor alphaCorner = closeButton.color(2);
4013         alphaCorner.setAlpha(80);
4014         closeButton.setColor(2, alphaCorner.rgba());
4015         return QPixmap::fromImage(closeButton);
4016     }
4017     break;
4018
4019     case SP_DialogDiscardButton:
4020         return QGtkPainter::getIcon(GTK_STOCK_DELETE);
4021     case SP_DialogOkButton:
4022         return QGtkPainter::getIcon(GTK_STOCK_OK);
4023     case SP_DialogCancelButton:
4024         return QGtkPainter::getIcon(GTK_STOCK_CANCEL);
4025     case SP_DialogYesButton:
4026         return QGtkPainter::getIcon(GTK_STOCK_YES);
4027     case SP_DialogNoButton:
4028         return QGtkPainter::getIcon(GTK_STOCK_NO);
4029     case SP_DialogOpenButton:
4030         return QGtkPainter::getIcon(GTK_STOCK_OPEN);
4031     case SP_DialogCloseButton:
4032         return QGtkPainter::getIcon(GTK_STOCK_CLOSE);
4033     case SP_DialogApplyButton:
4034         return QGtkPainter::getIcon(GTK_STOCK_APPLY);
4035     case SP_DialogSaveButton:
4036         return QGtkPainter::getIcon(GTK_STOCK_SAVE);
4037     case SP_MessageBoxWarning:
4038         return QGtkPainter::getIcon(GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_DIALOG);
4039     case SP_MessageBoxQuestion:
4040         return QGtkPainter::getIcon(GTK_STOCK_DIALOG_QUESTION, GTK_ICON_SIZE_DIALOG);
4041     case SP_MessageBoxInformation:
4042         return QGtkPainter::getIcon(GTK_STOCK_DIALOG_INFO, GTK_ICON_SIZE_DIALOG);
4043     case SP_MessageBoxCritical:
4044         return QGtkPainter::getIcon(GTK_STOCK_DIALOG_ERROR, GTK_ICON_SIZE_DIALOG);
4045     default:
4046         return QWindowsStyle::standardPixmap(sp, option, widget);
4047     }
4048     return pixmap;
4049 }
4050
4051 /*!
4052     \reimp
4053 */
4054 QIcon QGtkStyle::standardIcon(StandardPixmap standardIcon,
4055                               const QStyleOption *option,
4056                               const QWidget *widget) const
4057 {
4058     Q_D(const QGtkStyle);
4059
4060     if (!d->isThemeAvailable())
4061         return QWindowsStyle::standardIcon(standardIcon, option, widget);
4062     switch (standardIcon) {
4063     case SP_DialogDiscardButton:
4064         return QGtkPainter::getIcon(GTK_STOCK_DELETE);
4065     case SP_DialogOkButton:
4066         return QGtkPainter::getIcon(GTK_STOCK_OK);
4067     case SP_DialogCancelButton:
4068         return QGtkPainter::getIcon(GTK_STOCK_CANCEL);
4069     case SP_DialogYesButton:
4070         return QGtkPainter::getIcon(GTK_STOCK_YES);
4071     case SP_DialogNoButton:
4072         return QGtkPainter::getIcon(GTK_STOCK_NO);
4073     case SP_DialogOpenButton:
4074         return QGtkPainter::getIcon(GTK_STOCK_OPEN);
4075     case SP_DialogCloseButton:
4076         return QGtkPainter::getIcon(GTK_STOCK_CLOSE);
4077     case SP_DialogApplyButton:
4078         return QGtkPainter::getIcon(GTK_STOCK_APPLY);
4079     case SP_DialogSaveButton:
4080         return QGtkPainter::getIcon(GTK_STOCK_SAVE);
4081     case SP_MessageBoxWarning:
4082         return QGtkPainter::getIcon(GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_DIALOG);
4083     case SP_MessageBoxQuestion:
4084         return QGtkPainter::getIcon(GTK_STOCK_DIALOG_QUESTION, GTK_ICON_SIZE_DIALOG);
4085     case SP_MessageBoxInformation:
4086         return QGtkPainter::getIcon(GTK_STOCK_DIALOG_INFO, GTK_ICON_SIZE_DIALOG);
4087     case SP_MessageBoxCritical:
4088         return QGtkPainter::getIcon(GTK_STOCK_DIALOG_ERROR, GTK_ICON_SIZE_DIALOG);
4089     default:
4090         return QWindowsStyle::standardIcon(standardIcon, option, widget);
4091     }
4092 }
4093
4094
4095 /*! \reimp */
4096 QRect QGtkStyle::subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const
4097 {
4098     Q_D(const QGtkStyle);
4099
4100     QRect r = QWindowsStyle::subElementRect(element, option, widget);
4101     if (!d->isThemeAvailable())
4102         return r;
4103
4104     switch (element) {
4105     case SE_PushButtonFocusRect:
4106         r.adjust(0, 1, 0, -1);
4107         break;
4108     case SE_DockWidgetTitleBarText: {
4109         const QStyleOptionDockWidgetV2 *v2
4110             = qstyleoption_cast<const QStyleOptionDockWidgetV2*>(option);
4111         bool verticalTitleBar = v2 == 0 ? false : v2->verticalTitleBar;
4112         if (verticalTitleBar) {
4113             r.adjust(0, 0, 0, -4);
4114         } else {
4115             if (option->direction == Qt::LeftToRight)
4116                 r.adjust(4, 0, 0, 0);
4117             else
4118                 r.adjust(0, 0, -4, 0);
4119         }
4120
4121         break;
4122     }
4123     case SE_ProgressBarLabel:
4124     case SE_ProgressBarContents:
4125     case SE_ProgressBarGroove:
4126         return option->rect;
4127     case SE_PushButtonContents:
4128         if (!d->gtk_check_version(2, 10, 0)) {
4129             GtkWidget *gtkButton = d->gtkWidget("GtkButton");
4130             GtkBorder *border = 0;
4131             d->gtk_widget_style_get(gtkButton, "inner-border", &border, NULL);
4132             if (border) {
4133                 r = option->rect.adjusted(border->left, border->top, -border->right, -border->bottom);
4134                 d->gtk_border_free(border);
4135             } else {
4136                 r = option->rect.adjusted(1, 1, -1, -1);
4137             }
4138             r = visualRect(option->direction, option->rect, r);
4139         }
4140         break;
4141     default:
4142         break;
4143     }
4144
4145     return r;
4146 }
4147
4148 /*!
4149   \reimp
4150 */
4151 QRect QGtkStyle::itemPixmapRect(const QRect &r, int flags, const QPixmap &pixmap) const
4152 {
4153     return QWindowsStyle::itemPixmapRect(r, flags, pixmap);
4154 }
4155
4156 /*!
4157   \reimp
4158 */
4159 void QGtkStyle::drawItemPixmap(QPainter *painter, const QRect &rect,
4160                             int alignment, const QPixmap &pixmap) const
4161 {
4162     QWindowsStyle::drawItemPixmap(painter, rect, alignment, pixmap);
4163 }
4164
4165 /*!
4166   \reimp
4167 */
4168 QStyle::SubControl QGtkStyle::hitTestComplexControl(ComplexControl cc, const QStyleOptionComplex *opt,
4169                               const QPoint &pt, const QWidget *w) const
4170 {
4171     return QWindowsStyle::hitTestComplexControl(cc, opt, pt, w);
4172 }
4173
4174 /*!
4175   \reimp
4176 */
4177 QPixmap QGtkStyle::generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap,
4178                                         const QStyleOption *opt) const
4179 {
4180     return QWindowsStyle::generatedIconPixmap(iconMode, pixmap, opt);
4181 }
4182
4183 /*!
4184   \reimp
4185 */
4186 void QGtkStyle::drawItemText(QPainter *painter, const QRect &rect, int alignment, const QPalette &pal,
4187                                     bool enabled, const QString& text, QPalette::ColorRole textRole) const
4188 {
4189     return QWindowsStyle::drawItemText(painter, rect, alignment, pal, enabled, text, textRole);
4190 }
4191
4192 QT_END_NAMESPACE
4193
4194 #endif //!defined(QT_NO_STYLE_QGTK)