Chris@668: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@668: Chris@668: /* Chris@668: Vect Chris@668: An experimental audio player for plural recordings of a work Chris@668: Centre for Digital Music, Queen Mary, University of London. Chris@668: Chris@668: This file is taken from Rosegarden, a MIDI and audio sequencer and Chris@668: musical notation editor. Copyright 2000-2018 the Rosegarden Chris@668: development team. Thorn style developed in stylesheet form by Chris@668: D. Michael McIntyre and reimplemented as a class by David Faure. Chris@668: Chris@668: This program is free software; you can redistribute it and/or Chris@668: modify it under the terms of the GNU General Public License as Chris@668: published by the Free Software Foundation; either version 2 of the Chris@668: License, or (at your option) any later version. See the file Chris@668: COPYING included with this distribution for more information. Chris@668: */ Chris@668: Chris@668: #include "ThornStyle.h" Chris@668: #include "AppEventFilter.h" Chris@668: Chris@668: #include Chris@668: #include Chris@668: #include Chris@668: #include Chris@668: #include Chris@668: #include Chris@668: #include Chris@668: #include Chris@668: #include Chris@668: #include Chris@668: #include Chris@668: #include Chris@668: Chris@668: // Apply the style to widget and its children, recursively Chris@668: // Even though every widget goes through the event filter, this is needed Chris@668: // for the case where a whole widget hierarchy is suddenly reparented into the file dialog. Chris@668: // Then we need to apply the app style again. Testcase: scrollbars in file dialog. Chris@668: static void applyStyleRecursive(QWidget* widget, QStyle *style) Chris@668: { Chris@668: if (widget->style() != style) { Chris@668: widget->setStyle(style); Chris@668: } Chris@668: foreach (QObject* obj, widget->children()) { Chris@668: if (obj->isWidgetType()) { Chris@668: QWidget *w = static_cast(obj); Chris@668: applyStyleRecursive(w, style); Chris@668: } Chris@668: } Chris@668: } Chris@668: Chris@668: AppEventFilter::AppEventFilter() : Chris@668: m_systemPalette(qApp->palette()), Chris@668: m_systemStyle(qApp->style()) { Chris@668: } Chris@668: Chris@668: bool Chris@668: AppEventFilter::shouldIgnoreThornStyle(QWidget *widget) const { Chris@668: return qobject_cast(widget) Chris@668: || widget->inherits("KDEPlatformFileDialog") Chris@668: || widget->inherits("KDirSelectDialog"); Chris@668: } Chris@668: Chris@668: // when we ditch Qt4, we can switch to qCDebug... Chris@668: //#define DEBUG_EVENTFILTER Chris@668: Chris@668: bool AppEventFilter::eventFilter(QObject *watched, QEvent *event) Chris@668: { Chris@668: static bool s_insidePolish = false; // setStyle calls polish again, so skip doing the work twice Chris@668: if (!s_insidePolish && watched->isWidgetType() && event->type() == QEvent::Polish) { Chris@668: s_insidePolish = true; Chris@668: // This is called after every widget is created and just before being shown Chris@668: // (we use this so that it has a proper parent widget already) Chris@668: QWidget *widget = static_cast(watched); Chris@668: if (shouldIgnoreThornStyle(widget)) { Chris@668: // The palette from the mainwindow propagated to the dialog, restore it. Chris@668: widget->setPalette(m_systemPalette); Chris@668: #ifdef DEBUG_EVENTFILTER Chris@668: qDebug() << widget << "now using app style (recursive)"; Chris@668: #endif Chris@668: applyStyleRecursive(widget, qApp->style()); Chris@668: s_insidePolish = false; Chris@668: return false; Chris@668: } Chris@668: QWidget *toplevel = widget->window(); Chris@668: #ifdef DEBUG_EVENTFILTER Chris@668: qDebug() << widget << "current widget style=" << widget->style() << "shouldignore=" << shouldIgnoreThornStyle(toplevel); Chris@668: #endif Chris@668: if (shouldIgnoreThornStyle(toplevel)) { Chris@668: // Here we should apply qApp->style() recursively on widget and its children, in case one was reparented Chris@668: #ifdef DEBUG_EVENTFILTER Chris@668: qDebug() << widget << widget->objectName() << "in" << toplevel << "now using app style (recursive)"; Chris@668: #endif Chris@668: applyStyleRecursive(widget, qApp->style()); Chris@668: } else if (widget->style() != &m_style) { Chris@668: #ifdef DEBUG_EVENTFILTER Chris@668: //qDebug() << " ToolTipBase=" << widget->palette().color(QPalette::ToolTipBase).name(); Chris@668: #endif Chris@668: // Apply style recursively because some child widgets (e.g. QHeaderView in QTreeWidget, in DeviceManagerDialog) don't seem to get here. Chris@668: if (qobject_cast(widget)) { Chris@668: applyStyleRecursive(widget, &m_style); Chris@668: } else { Chris@668: widget->setStyle(&m_style); Chris@668: } Chris@668: #ifdef DEBUG_EVENTFILTER Chris@668: qDebug() << " now using style" << widget->style(); Chris@668: #endif Chris@668: if (widget->windowType() != Qt::Widget) { // window, tooltip, ... Chris@668: widget->setPalette(m_style.standardPalette()); Chris@668: #ifdef DEBUG_EVENTFILTER Chris@668: qDebug() << " after setPalette: ToolTipBase=" << widget->palette().color(QPalette::ToolTipBase).name(); Chris@668: #endif Chris@668: } else { Chris@668: #ifdef DEBUG_EVENTFILTER Chris@668: //qDebug() << " not a toplevel. ToolTipBase=" << widget->palette().color(QPalette::ToolTipBase).name(); Chris@668: #endif Chris@668: } Chris@668: polishWidget(widget); Chris@668: } Chris@668: s_insidePolish = false; Chris@668: } Chris@668: return false; // don't eat the event Chris@668: } Chris@668: Chris@668: void AppEventFilter::polishWidget(QWidget *widget) Chris@668: { Chris@668: if (QLabel *label = qobject_cast(widget)) { Chris@668: if (qobject_cast(widget->parentWidget())) { Chris@668: /* Toolbars must be light enough for black icons, therefore black text on their Chris@668: QLabels, rather than white, is more appropriate. Chris@668: QToolBar QLabel { color: #000000; } */ Chris@668: QPalette pal = label->palette(); Chris@668: pal.setColor(label->foregroundRole(), Qt::black); Chris@668: label->setPalette(pal); Chris@668: //qDebug() << "made label black:" << label << label->text(); Chris@668: } Chris@668: if (widget->objectName() == "SPECIAL_LABEL") { Chris@668: widget->setAutoFillBackground(true); Chris@668: // QWidget#SPECIAL_LABEL { color: #000000; background-color: #999999; } Chris@668: QPalette palette = widget->palette(); Chris@668: palette.setColor(QPalette::WindowText, Qt::black); Chris@668: palette.setColor(QPalette::Window, QColor(0x99, 0x99, 0x99)); Chris@668: widget->setPalette(palette); Chris@668: } Chris@668: } else if (widget->objectName() == "Rosegarden Transport") { Chris@668: // Give the non-LED parts of the dialog the groupbox "lighter black" Chris@668: // background for improved contrast. Chris@668: QPalette transportPalette = widget->palette(); Chris@668: transportPalette.setColor(widget->backgroundRole(), QColor(0x40, 0x40, 0x40)); Chris@668: widget->setPalette(transportPalette); Chris@668: widget->setAutoFillBackground(true); Chris@668: } else if (QCheckBox *cb = qobject_cast(widget)) { Chris@668: cb->setAttribute(Qt::WA_Hover); Chris@668: } else if (QRadioButton *rb = qobject_cast(widget)) { Chris@668: rb->setAttribute(Qt::WA_Hover); Chris@668: } else if (QPushButton *pb = qobject_cast(widget)) { Chris@668: pb->setAttribute(Qt::WA_Hover); Chris@668: if (qobject_cast(widget->parentWidget())) { Chris@668: // Bug in QDialogButtonBox: if the app style sets QStyle::SH_DialogButtonBox_ButtonsHaveIcons Chris@668: // a later call to setStyle() doesn't remove the button icon again. Chris@668: // Fix submitted at https://codereview.qt-project.org/183788 Chris@668: pb->setIcon(QIcon()); Chris@668: } Chris@668: } else if (QComboBox *cb = qobject_cast(widget)) { Chris@668: cb->setAttribute(Qt::WA_Hover); Chris@668: } else if (QAbstractSpinBox *sb = qobject_cast(widget)) { Chris@668: sb->setAttribute(Qt::WA_Hover); Chris@668: } Chris@668: }