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