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