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);
+    }
+}