From 5bf22c1117f99d5d1b08f90bd3123526fb80f5de Mon Sep 17 00:00:00 2001 From: zccrs Date: Mon, 22 Jan 2018 14:48:14 +0800 Subject: [PATCH] fix: can not be fixed widget style Change-Id: I34b0b6bd83940b042c5c07387b398e282c66359e --- src/dtkwidget_global.h | 10 +++- src/widgets/dthememanager.cpp | 102 +++++++++++++++++++++++++++++----- src/widgets/dthememanager.h | 4 +- 3 files changed, 99 insertions(+), 17 deletions(-) diff --git a/src/dtkwidget_global.h b/src/dtkwidget_global.h index c56841d71..cf1876b0b 100644 --- a/src/dtkwidget_global.h +++ b/src/dtkwidget_global.h @@ -59,10 +59,16 @@ namespace Widget #define D_THEME_INIT_WIDGET(className, ...) do{\ DThemeManager * manager = DThemeManager::instance(); \ - this->setStyleSheet(this->styleSheet() + manager->getQssForWidget(#className, this)); \ + {const QString &sheet = this->styleSheet() + manager->getQssForWidget(#className, this); \ + if (!sheet.isEmpty()) this->setStyleSheet(sheet); \ + } \ connect(manager, &DThemeManager::themeChanged, this, [this, manager] (QString) { \ - this->setStyleSheet(manager->getQssForWidget(#className, this)); \ + const QString &sheet = manager->getQssForWidget(#className, this); \ + if (!sheet.isEmpty()) this->setStyleSheet(sheet); \ });\ + connect(manager, &DThemeManager::widgetThemeChanged, this, [this, manager] (QWidget *w, QString) { \ + if (w == this) this->setStyleSheet(manager->getQssForWidget(#className, this)); \ + }); \ QStringList list = QString(#__VA_ARGS__).replace(" ", "").split(",");\ const QMetaObject *self = metaObject();\ Q_FOREACH (const QString &str, list) {\ diff --git a/src/widgets/dthememanager.cpp b/src/widgets/dthememanager.cpp index dfb6cf1dc..8e9747a9e 100644 --- a/src/widgets/dthememanager.cpp +++ b/src/widgets/dthememanager.cpp @@ -22,6 +22,8 @@ #include +#include + #include "dthememanager.h" #include "dapplication.h" @@ -61,6 +63,27 @@ QString DThemeManager::theme() const return m_theme; } +QString DThemeManager::theme(const QWidget *widget, QWidget **baseWidget) const +{ + QString theme; + + if (baseWidget) + *baseWidget = nullptr; + + do { + theme = widget->property("_d_dtk_theme").toString(); + if (!theme.isEmpty()) { + if (baseWidget) + *baseWidget = const_cast(widget); + + break; + } + widget = widget->isWindow() ? 0 : widget->parentWidget(); + } while (widget); + + return theme.isEmpty() ? m_theme : theme; +} + /*! * \brief DThemeManager::setTheme sets the application theme. * \param theme is the theme name to be set. @@ -68,7 +91,6 @@ QString DThemeManager::theme() const void DThemeManager::setTheme(const QString theme) { if (m_theme != theme) { - QStyle *style = Q_NULLPTR; // TODO: remove this shit in the future. @@ -105,6 +127,48 @@ static QString getObjectClassName(const QObject *obj) return widget_type_list.isEmpty() ? type_name : widget_type_list.last(); } +static void emitThemeChanged(DThemeManager *manager, QWidget *widget, const QString &theme) +{ + Q_EMIT manager->widgetThemeChanged(widget, theme); + + for (QObject *child : widget->children()) { + if (QWidget *cw = qobject_cast(child)) { + if (cw->property("_d_dtk_theme").isValid()) + continue; + + emitThemeChanged(manager, cw, theme); + } + } +} + +static void setStyle(QWidget *widget, QStyle *style) +{ + widget->setStyle(style); + + for (QObject *child : widget->children()) { + if (QWidget *cw = qobject_cast(child)) { + if (cw->property("_d_dtk_theme").isValid()) + continue; + + setStyle(cw, style); + } + } +} + +static void inseritStyle(QWidget *widget, const QWidget *baseWidget) +{ + if (widget == baseWidget) + return; + + QStyle *base_style = baseWidget ? baseWidget->style() : qApp->style(); + + if (base_style->inherits("QStyleSheetStyle")) { + base_style = static_cast(base_style)->base; + } + + widget->setStyle(base_style); +} + /*! * \brief DThemeManager::setTheme sets theme on a widget. * \param widget is the target widget. @@ -114,6 +178,23 @@ void DThemeManager::setTheme(QWidget *widget, const QString theme) { Q_ASSERT(widget); + if (theme.isEmpty()) { + QString old_theme = this->theme(widget); + + widget->setProperty("_d_dtk_theme", QVariant()); + + QWidget *baseWidget = nullptr; + + if (this->theme(widget, &baseWidget) != old_theme) { + emitThemeChanged(this, widget, this->theme(widget)); + } + + inseritStyle(widget, baseWidget); + + return; + } + + const QString &old_theme = this->theme(widget); QStyle *style = Q_NULLPTR; // TODO: remove this shit in the future. @@ -135,10 +216,11 @@ void DThemeManager::setTheme(QWidget *widget, const QString theme) } if (style) { - widget->setStyle(style); + setStyle(widget, style); } - widget->setStyleSheet(getQssForWidget(getObjectClassName(widget), theme)); + if (old_theme != theme) + emitThemeChanged(this, widget, theme); } /*! @@ -160,9 +242,9 @@ QString DThemeManager::getQssForWidget(const QString className, const QString &t if (themeFile.open(QIODevice::ReadOnly | QIODevice::Text)) { qss = themeFile.readAll(); themeFile.close(); - } else { + } /*else { qWarning() << "open qss file failed" << themeURL << themeFile.errorString(); - } + }*/ return qss; } @@ -179,15 +261,7 @@ QString DThemeManager::getQssForWidget(const QString className, const QWidget *w { Q_ASSERT(widget); - QString theme; - - do { - theme = widget->property("_d_dtk_theme").toString(); - if (!theme.isEmpty()) { break; } - widget = widget->parentWidget(); - } while (widget); - - return getQssForWidget(className, theme); + return getQssForWidget(className, theme(widget)); } /*! diff --git a/src/widgets/dthememanager.h b/src/widgets/dthememanager.h index 20174de59..d92f88083 100644 --- a/src/widgets/dthememanager.h +++ b/src/widgets/dthememanager.h @@ -34,10 +34,11 @@ class DThemeManager : public QObject static DThemeManager *instance(); QString theme() const; + QString theme(const QWidget *widget, QWidget **baseWidget = nullptr) const; void setTheme(const QString theme); void setTheme(QWidget *widget, const QString theme); - QString getQssForWidget(const QString className, const QString &theme = "") const; + QString getQssForWidget(const QString className, const QString &theme = QString()) const; QString getQssForWidget(const QString className, const QWidget *widget) const; QString getQssForWidget(const QWidget *widget) const; @@ -48,6 +49,7 @@ public Q_SLOTS: Q_SIGNALS: void themeChanged(QString theme); + void widgetThemeChanged(QWidget *widget, QString theme); protected: DThemeManager();