From 2a8e39999cb3f5be9bb16ffb5ddfe118d18f9ef1 Mon Sep 17 00:00:00 2001 From: Jens Bache-Wiig Date: Fri, 3 Apr 2009 18:19:47 +0200 Subject: QGtkStyle: Fix styling and palette issues related to combo box Well actually this change is a bit bigger than just that. *We no longer override the palette you provide in polish so it should be a bit more frienly toward custom application changes. * Another issue was that we would generate the palette information when we got the style callback from gtkButton but then the line edits might not yet have been polished. Hence we now return from the callback and instead post the update for later. * We had to modify the PE_Frame entry to draw a raised menu when the custom combo box delegate was used. * We now simply ignore custom qtconfig palette entries when using GtkStyle since they only cause trouble with it. Task-number: 250142 Reviewed-by: nrc --- src/gui/kernel/qapplication_x11.cpp | 7 ++-- src/gui/styles/gtksymbols.cpp | 68 +++++++++++++++++++++---------------- src/gui/styles/gtksymbols_p.h | 11 +++++- src/gui/styles/qgtkstyle.cpp | 40 +++++++++++++++++++--- src/gui/widgets/qcombobox_p.h | 2 +- 5 files changed, 89 insertions(+), 39 deletions(-) diff --git a/src/gui/kernel/qapplication_x11.cpp b/src/gui/kernel/qapplication_x11.cpp index 260a9a4..10fb886 100644 --- a/src/gui/kernel/qapplication_x11.cpp +++ b/src/gui/kernel/qapplication_x11.cpp @@ -829,8 +829,11 @@ bool QApplicationPrivate::x11_apply_settings() QColor(strlist[i])); } - if (groupCount == QPalette::NColorGroups) - QApplicationPrivate::setSystemPalette(pal); + // ### Fix properly for 4.6 + if (!(QApplicationPrivate::app_style && QApplicationPrivate::app_style->inherits("QGtkStyle"))) { + if (groupCount == QPalette::NColorGroups) + QApplicationPrivate::setSystemPalette(pal); + } int kdeSessionVersion = QString::fromLocal8Bit(qgetenv("KDE_SESSION_VERSION")).toInt(); diff --git a/src/gui/styles/gtksymbols.cpp b/src/gui/styles/gtksymbols.cpp index f60c980..8123d32 100644 --- a/src/gui/styles/gtksymbols.cpp +++ b/src/gui/styles/gtksymbols.cpp @@ -75,6 +75,7 @@ QT_BEGIN_NAMESPACE static bool displayDepth = -1; +Q_GLOBAL_STATIC(QGtkStyleUpdateScheduler, styleScheduler) typedef QHash WidgetMap; Q_GLOBAL_STATIC(WidgetMap, gtkWidgetMap) @@ -486,11 +487,11 @@ static void init_gtk_menu() } // Updates window/windowtext palette based on the indicated gtk widget -static void ensureWidgetPalette(QWidget* widget, const QString >kWidgetName) +static QPalette gtkWidgetPalette(const QString >kWidgetName) { GtkWidget *gtkWidget = QGtk::gtkWidget(gtkWidgetName); Q_ASSERT(gtkWidget); - QPalette pal = widget->palette(); + QPalette pal = QApplication::palette(); GdkColor gdkBg = gtkWidget->style->bg[GTK_STATE_NORMAL]; GdkColor gdkText = gtkWidget->style->fg[GTK_STATE_NORMAL]; GdkColor gdkDisabledText = gtkWidget->style->fg[GTK_STATE_INSENSITIVE]; @@ -503,8 +504,14 @@ static void ensureWidgetPalette(QWidget* widget, const QString >kWidgetName) pal.setBrush(QPalette::Disabled, QPalette::WindowText, disabledTextColor); pal.setBrush(QPalette::All, QPalette::ButtonText, textColor); pal.setBrush(QPalette::Disabled, QPalette::ButtonText, disabledTextColor); - widget->setPalette(pal); - widget->setAttribute(Qt::WA_SetPalette, false); + if (gtkWidgetName == QLS("GtkMenu")) { + // This really applies to the combo box rendering since + // QComboBox copies the palette from a QMenu + GdkColor gdkBg = gtkWidget->style->bg[GTK_STATE_NORMAL]; + QColor bgColor(gdkBg.red>>8, gdkBg.green>>8, gdkBg.blue>>8); + pal.setBrush(QPalette::Base, bgColor); + } + return pal; } bool QGtk::isKDE4Session() @@ -515,44 +522,45 @@ bool QGtk::isKDE4Session() return (version == 4); } -// Maps a Gtk widget palettes to a Qt widget -void QGtk::applyGtkSystemPalette(QWidget *widget) +void QGtk::applyCustomPaletteHash() { - // Do not apply if the widget has a custom palette; - if (widget->testAttribute(Qt::WA_SetPalette)) - return; + QPalette menuPal = gtkWidgetPalette(QLS("GtkMenu")); + GdkColor gdkBg = QGtk::gtkWidget(QLS("GtkMenu"))->style->bg[GTK_STATE_NORMAL]; + QColor bgColor(gdkBg.red>>8, gdkBg.green>>8, gdkBg.blue>>8); + menuPal.setBrush(QPalette::Base, bgColor); + qApp->setPalette(menuPal, "QMenu"); - QPalette pal; - if (QStatusBar *statusbar = qobject_cast (widget)) - ensureWidgetPalette(statusbar, QLS("GtkStatusbar")); - else if (QMenuBar *menubar = qobject_cast (widget)) - ensureWidgetPalette(menubar, QLS("GtkMenuBar")); - else if (QToolBar *toolbar = qobject_cast (widget)) - ensureWidgetPalette(toolbar, QLS("GtkToolbar")); - else if (QMenu *menu = qobject_cast (widget)) { - // This really applies to the combo box rendering since - // QComboBox copies the palette from a QMenu - QPalette pal = widget->palette(); - GdkColor gdkBg = QGtk::gtkWidget(QLS("GtkMenu"))->style->bg[GTK_STATE_NORMAL]; - QColor bgColor(gdkBg.red>>8, gdkBg.green>>8, gdkBg.blue>>8); - pal.setBrush(QPalette::Base, bgColor); - menu->setPalette(pal); - } - widget->setAttribute(Qt::WA_SetPalette, false); + QPalette toolbarPal = gtkWidgetPalette(QLS("GtkToolbar")); + qApp->setPalette(toolbarPal, "QToolBar"); + + QPalette menuBarPal = gtkWidgetPalette(QLS("GtkMenuBar")); + qApp->setPalette(menuBarPal, "QMenuBar"); } static void gtkStyleSetCallback(GtkWidget*, GtkStyle*, void*) { + // We have to let this function return and complete the event + // loop to ensure that all gtk widgets have been styled before + // updating + QMetaObject::invokeMethod(styleScheduler(), "updateTheme", Qt::QueuedConnection); +} + +void QGtkStyleUpdateScheduler::updateTheme() +{ static QString oldTheme(QLS("qt_not_set")); QPixmapCache::clear(); - qApp->setFont(QGtk::getThemeFont()); - QGtk::initGtkWidgets(); if (oldTheme != getThemeName()) { oldTheme = getThemeName(); - QApplicationPrivate::setSystemPalette(qApp->style()->standardPalette()); + qApp->setFont(QGtk::getThemeFont()); + QPalette newPalette = qApp->style()->standardPalette(); + QApplicationPrivate::setSystemPalette(newPalette); + QApplication::setPalette(newPalette); + QGtk::applyCustomPaletteHash(); QList widgets = QApplication::allWidgets(); + // Notify all widgets that size metrics might have changed foreach (QWidget *widget, widgets) { - QGtk::applyGtkSystemPalette(widget); + QEvent e(QEvent::StyleChange); + QApplication::sendEvent(widget, &e); } } } diff --git a/src/gui/styles/gtksymbols_p.h b/src/gui/styles/gtksymbols_p.h index 0cea542..74c5dc3 100644 --- a/src/gui/styles/gtksymbols_p.h +++ b/src/gui/styles/gtksymbols_p.h @@ -204,7 +204,7 @@ public: static void cleanup_gtk_widgets(); static void initGtkWidgets(); static bool isKDE4Session(); - static void applyGtkSystemPalette(QWidget* widget); + static void applyCustomPaletteHash(); static QFont getThemeFont(); static bool isThemeAvailable() { return gtkStyle() != 0; } @@ -329,6 +329,15 @@ public: static Ptr_gconf_client_get_string gconf_client_get_string; }; +// Helper to ensure that we have polished all our gtk widgets +// before updating our own palettes +class QGtkStyleUpdateScheduler : public QObject +{ + Q_OBJECT +public slots: + void updateTheme(); +}; + QT_END_NAMESPACE #endif // !QT_NO_STYLE_GTK diff --git a/src/gui/styles/qgtkstyle.cpp b/src/gui/styles/qgtkstyle.cpp index 81d7cb8..6354ce7 100644 --- a/src/gui/styles/qgtkstyle.cpp +++ b/src/gui/styles/qgtkstyle.cpp @@ -38,7 +38,6 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ - #include "qgtkstyle.h" #if !defined(QT_NO_STYLE_GTK) @@ -138,6 +137,30 @@ static const char * const dock_widget_restore_xpm[] = }; +class QGtkStyleFilter : public QObject +{ +public: + QGtkStyleFilter() { + qApp->installEventFilter(this); + } + +private: + bool eventFilter(QObject *obj, QEvent *e); +}; + +bool QGtkStyleFilter::eventFilter(QObject *obj, QEvent *e) +{ + if (e->type() == QEvent::ApplicationPaletteChange) { + // Only do this the first time since this will also + // generate applicationPaletteChange events + extern QHash *qt_app_palettes_hash(); //qapplication.cpp + if (!qt_app_palettes_hash() || qt_app_palettes_hash()->isEmpty()) { + QGtk::applyCustomPaletteHash(); + } + } + return QObject::eventFilter(obj, e); +} + class QGtkStylePrivate : public QCleanlooksStylePrivate { Q_DECLARE_PUBLIC(QGtkStyle) @@ -145,6 +168,7 @@ public: QGtkStylePrivate() : QCleanlooksStylePrivate() {} + QGtkStyleFilter filter; }; static const int groupBoxBottomMargin = 2; // space below the groupbox @@ -217,6 +241,7 @@ static QString uniqueName(const QString &key, const QStyleOption *option, const Constructs a QGtkStyle object. */ QGtkStyle::QGtkStyle() + : QCleanlooksStyle(*new QGtkStylePrivate) { QGtk::initGtkWidgets(); } @@ -313,7 +338,7 @@ void QGtkStyle::polish(QPalette &palette) if (!QGtk::isThemeAvailable()) QCleanlooksStyle::polish(palette); else - palette = standardPalette(); + palette = palette.resolve(standardPalette()); } /*! @@ -328,6 +353,7 @@ void QGtkStyle::polish(QApplication *app) if (app->desktopSettingsAware() && QGtk::isThemeAvailable()) { QApplicationPrivate::setSystemPalette(standardPalette()); QApplicationPrivate::setSystemFont(QGtk::getThemeFont()); + QGtk::applyCustomPaletteHash(); if (!QGtk::isKDE4Session()) { qt_filedialog_open_filename_hook = &QGtk::openFilename; qt_filedialog_save_filename_hook = &QGtk::saveFilename; @@ -357,12 +383,12 @@ void QGtkStyle::unpolish(QApplication *app) /*! \reimp */ + void QGtkStyle::polish(QWidget *widget) { QCleanlooksStyle::polish(widget); if (!QGtk::isThemeAvailable()) return; - if (qobject_cast(widget) || qobject_cast(widget) || qobject_cast(widget) @@ -375,8 +401,6 @@ void QGtkStyle::polish(QWidget *widget) widget->setAttribute(Qt::WA_Hover); else if (QTreeView *tree = qobject_cast (widget)) tree->viewport()->setAttribute(Qt::WA_Hover); - - QGtk::applyGtkSystemPalette(widget); } /*! @@ -647,6 +671,12 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element, switch (element) { case PE_Frame: { + if (widget && widget->inherits("QComboBoxPrivateContainer")){ + QStyleOption copy = *option; + copy.state |= State_Raised; + drawPrimitive(PE_PanelMenu, ©, painter, widget); + break; + } // Drawing the entire itemview frame is very expensive, especially on the native X11 engine // Instead we cheat a bit and draw a border image without the center part, hence only scaling // thin rectangular images diff --git a/src/gui/widgets/qcombobox_p.h b/src/gui/widgets/qcombobox_p.h index f1203dc..c39a231 100644 --- a/src/gui/widgets/qcombobox_p.h +++ b/src/gui/widgets/qcombobox_p.h @@ -265,7 +265,7 @@ protected: const QStyleOptionViewItem &option, const QModelIndex &index) const { QStyleOptionMenuItem opt = getStyleOption(option, index); - painter->eraseRect(option.rect); + painter->fillRect(option.rect, opt.palette.background()); mCombo->style()->drawControl(QStyle::CE_MenuItem, &opt, painter, mCombo); } QSize sizeHint(const QStyleOptionViewItem &option, -- cgit v0.12