From c1af38584f74d411a0792151e5bc0d706bffa2c4 Mon Sep 17 00:00:00 2001 From: zty199 <46324746+zty199@users.noreply.github.com> Date: Sat, 28 Oct 2023 18:30:40 +0800 Subject: [PATCH] =?UTF-8?q?chore:=20=E4=BC=98=E5=8C=96=20KDE=20=E6=B7=B1?= =?UTF-8?q?=E8=89=B2=E6=A8=A1=E5=BC=8F=E6=94=AF=E6=8C=81=E5=AE=9E=E7=8E=B0?= =?UTF-8?q?=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修改 ThemeChecker 为单例类,去除定时器频繁获取 color-scheme 操作,改为监听 SettingChanged 信号,仅在初始化时获取 color-scheme;Dtk 主题色变化信号监听合入 ThemeChecker 统一处理,判断主题需要变化时设置 Dtk 调色板,并发送 themeChanged 信号通知主窗口更新 qss Log: 修改 ThemeChecker 为单例类,监听 xdg-desktop-portal SettingChanged 信号和 Dtk 主题色变化信号进行统一处理 --- src/backend/ThemeChecker.cpp | 171 ++++++++++++++++++++++++++++------- src/backend/ThemeChecker.h | 26 ++++-- src/mainwindow-dtk.cpp | 37 +------- src/mainwindow-dtk.h | 4 +- 4 files changed, 161 insertions(+), 77 deletions(-) mode change 100644 => 100755 src/backend/ThemeChecker.cpp mode change 100644 => 100755 src/backend/ThemeChecker.h mode change 100644 => 100755 src/mainwindow-dtk.cpp mode change 100644 => 100755 src/mainwindow-dtk.h diff --git a/src/backend/ThemeChecker.cpp b/src/backend/ThemeChecker.cpp old mode 100644 new mode 100755 index 3d57b1c..754c3bb --- a/src/backend/ThemeChecker.cpp +++ b/src/backend/ThemeChecker.cpp @@ -1,44 +1,147 @@ #include "ThemeChecker.h" -#include -#include + +#include #include -ThemeChecker::ThemeChecker(QObject *parent) : QObject(parent), lastColorSchema(-1) { - timer = new QTimer(this); - connect(timer, SIGNAL(timeout()), this, SLOT(checkThemeChange())); - timer->start(1000); +Q_GLOBAL_STATIC(ThemeChecker, m_instance) + +constexpr char kFreedesktopPortalServiceName[] = "org.freedesktop.portal.Desktop"; +constexpr char kFreedesktopPortalServicePath[] = "/org/freedesktop/portal/desktop"; +constexpr char kFreedesktopPortalSettingsInterface[] = "org.freedesktop.portal.Settings"; + +ThemeChecker::ThemeChecker(QObject *parent) + : QObject(parent) + , m_paletteType(Dtk::Gui::DGuiApplicationHelper::instance()->paletteType()) +{ + m_interface = new QDBusInterface(kFreedesktopPortalServiceName, + kFreedesktopPortalServicePath, + kFreedesktopPortalSettingsInterface, + QDBusConnection::sessionBus(), + this); + + initThemeType(); + initConnections(); } -void ThemeChecker::checkThemeChange() { +ThemeChecker *ThemeChecker::instance() +{ + return m_instance; +} - - QProcess process; - QStringList parameters; - parameters << "-c" << "dbus-send --session --print-reply=literal --reply-timeout=1000 --dest=org.freedesktop.portal.Desktop /org/freedesktop/portal/desktop org.freedesktop.portal.Settings.Read string:'org.freedesktop.appearance' string:'color-scheme'"; - process.start("/bin/sh", parameters); - - if (process.waitForFinished(-1)) { - QString errorOutput = QString(process.readAllStandardError()).trimmed(); - if (!errorOutput.isEmpty()) { - qWarning() << "检测到DBus错误:" << errorOutput; - return; - } - - QString output = QString(process.readAll()).trimmed(); - int systemColorSchema = output.right(1).toInt(); - - if(systemColorSchema != lastColorSchema) { - lastColorSchema = systemColorSchema; - qDebug() << "主题已更改,新的主题是:" << systemColorSchema; - if(systemColorSchema == 1){ - emit themeChanged(true); - } - else if(systemColorSchema == 0 || systemColorSchema == 2){ - emit themeChanged(false); - } - } +bool ThemeChecker::useDarkTheme() +{ + if (m_paletteType == Dtk::Gui::DGuiApplicationHelper::ColorType::UnknownType) { + return m_themeType == Dtk::Gui::DGuiApplicationHelper::ColorType::DarkType; } else { - qWarning() << "DBus调用未能完成"; + return m_paletteType == Dtk::Gui::DGuiApplicationHelper::ColorType::DarkType; } } +void ThemeChecker::initThemeType() +{ + QVariantList args { "org.freedesktop.appearance", "color-scheme" }; + QDBusMessage msg = m_interface->callWithArgumentList(QDBus::Block, "Read", args); + if (msg.type() != QDBusMessage::MessageType::ReplyMessage || msg.arguments().size() < 1) { + qWarning().noquote() << "Init color-scheme from D-Bus failed:" << msg.errorName() << msg.errorMessage(); + m_themeType = Dtk::Gui::DGuiApplicationHelper::toColorType(Dtk::Gui::DGuiApplicationHelper::fetchPalette(Dtk::Gui::DGuiApplicationHelper::instance()->applicationTheme())); + return; + } + + quint32 colorScheme = qvariant_cast(qvariant_cast(msg.arguments().first()).variant()).variant().toUInt(); + switch (colorScheme) { + case 1: + m_themeType = Dtk::Gui::DGuiApplicationHelper::ColorType::DarkType; + break; + case 2: + m_themeType = Dtk::Gui::DGuiApplicationHelper::ColorType::LightType; + break; + default: + qInfo().noquote() << QString("color-scheme: %1, fetching themeType according to QPalette::Window").arg(colorScheme); + m_themeType = Dtk::Gui::DGuiApplicationHelper::toColorType(Dtk::Gui::DGuiApplicationHelper::fetchPalette(Dtk::Gui::DGuiApplicationHelper::instance()->applicationTheme())); + break; + } + + if (m_paletteType == Dtk::Gui::DGuiApplicationHelper::ColorType::UnknownType) { + Dtk::Gui::DGuiApplicationHelper::instance()->setApplicationPalette(Dtk::Gui::DGuiApplicationHelper::standardPalette(m_themeType)); + } +} + +void ThemeChecker::initConnections() +{ + QDBusConnection::sessionBus().connect(kFreedesktopPortalServiceName, + kFreedesktopPortalServicePath, + kFreedesktopPortalSettingsInterface, + "SettingChanged", + this, + SLOT(slotSettingChanged(const QString &, const QString &, const QDBusVariant &))); + + connect(Dtk::Gui::DGuiApplicationHelper::instance()->applicationTheme(), &Dtk::Gui::DPlatformTheme::themeNameChanged, this, &ThemeChecker::slotThemeNameChanged); + connect(Dtk::Gui::DGuiApplicationHelper::instance(), &Dtk::Gui::DGuiApplicationHelper::paletteTypeChanged, this, &ThemeChecker::slotPaletteTypeChanged); +} + +void ThemeChecker::slotSettingChanged(const QString &_namespace, const QString &key, const QDBusVariant &variant) +{ + if (_namespace != "org.freedesktop.appearance" || key != "color-scheme") { + return; + } + + Dtk::Gui::DGuiApplicationHelper::ColorType colorType = Dtk::Gui::DGuiApplicationHelper::ColorType::UnknownType; + + quint32 colorScheme = variant.variant().toUInt(); + switch (colorScheme) { + case 1: + colorType = Dtk::Gui::DGuiApplicationHelper::ColorType::DarkType; + break; + case 2: + colorType = Dtk::Gui::DGuiApplicationHelper::ColorType::LightType; + break; + default: + qInfo().noquote() << QString("color-scheme: %1, fetching themeType according to QPalette::Window").arg(colorScheme); + colorType = Dtk::Gui::DGuiApplicationHelper::toColorType(Dtk::Gui::DGuiApplicationHelper::fetchPalette(Dtk::Gui::DGuiApplicationHelper::instance()->applicationTheme())); + break; + } + + if (m_paletteType != Dtk::Gui::DGuiApplicationHelper::ColorType::UnknownType) { + m_themeType = colorType; + return; + } + + if (m_themeType != colorType) { + Dtk::Gui::DGuiApplicationHelper::instance()->setApplicationPalette(Dtk::Gui::DGuiApplicationHelper::standardPalette(colorType)); + emit themeChanged(colorType == Dtk::Gui::DGuiApplicationHelper::ColorType::DarkType); + m_themeType = colorType; + } +} + +void ThemeChecker::slotThemeNameChanged(const QByteArray &theme) +{ + Dtk::Gui::DGuiApplicationHelper::ColorType themeType = Dtk::Gui::DGuiApplicationHelper::ColorType::LightType; + if (theme.endsWith("dark")) { + themeType = Dtk::Gui::DGuiApplicationHelper::ColorType::DarkType; + } + + if (m_paletteType != Dtk::Gui::DGuiApplicationHelper::ColorType::UnknownType) { + m_themeType = themeType; + return; + } + + if (m_themeType != themeType) { + Dtk::Gui::DGuiApplicationHelper::instance()->setApplicationPalette(Dtk::Gui::DGuiApplicationHelper::standardPalette(themeType)); + emit themeChanged(themeType == Dtk::Gui::DGuiApplicationHelper::ColorType::DarkType); + m_themeType = themeType; + } +} + +void ThemeChecker::slotPaletteTypeChanged(Dtk::Gui::DGuiApplicationHelper::ColorType paletteType) +{ + m_paletteType = paletteType; + + if (m_paletteType != Dtk::Gui::DGuiApplicationHelper::ColorType::UnknownType) { + Dtk::Gui::DGuiApplicationHelper::instance()->setApplicationPalette(Dtk::Gui::DGuiApplicationHelper::standardPalette(m_paletteType)); + emit themeChanged(m_paletteType == Dtk::Gui::DGuiApplicationHelper::ColorType::DarkType); + return; + } + + Dtk::Gui::DGuiApplicationHelper::instance()->setApplicationPalette(Dtk::Gui::DGuiApplicationHelper::standardPalette(m_themeType)); + emit themeChanged(m_themeType == Dtk::Gui::DGuiApplicationHelper::ColorType::DarkType); +} diff --git a/src/backend/ThemeChecker.h b/src/backend/ThemeChecker.h old mode 100644 new mode 100755 index 4ca29f2..f74ae44 --- a/src/backend/ThemeChecker.h +++ b/src/backend/ThemeChecker.h @@ -2,25 +2,39 @@ #define THEMECHECKER_H #include -#include +#include +#include +#include +#include class ThemeChecker : public QObject { Q_OBJECT + public: explicit ThemeChecker(QObject *parent = nullptr); + static ThemeChecker *instance(); + + bool useDarkTheme(); + +private: + void initThemeType(); + void initConnections(); signals: void themeChanged(bool isDark); -public slots: - void checkThemeChange(); - +private slots: + void slotSettingChanged(const QString &_namespace, const QString &key, const QDBusVariant &variant); + void slotThemeNameChanged(const QByteArray &theme); + void slotPaletteTypeChanged(Dtk::Gui::DGuiApplicationHelper::ColorType paletteType); private: - int lastColorSchema; - QTimer *timer; + QDBusInterface *m_interface = nullptr; + + Dtk::Gui::DGuiApplicationHelper::ColorType m_paletteType; + Dtk::Gui::DGuiApplicationHelper::ColorType m_themeType; }; #endif // THEMECHECKER_H diff --git a/src/mainwindow-dtk.cpp b/src/mainwindow-dtk.cpp old mode 100644 new mode 100755 index 1e1e210..151a758 --- a/src/mainwindow-dtk.cpp +++ b/src/mainwindow-dtk.cpp @@ -41,8 +41,6 @@ MainWindow::MainWindow(QWidget *parent) initTmpDir(); ui->appintopage->setDownloadWidget(downloadlistwidget); - - emit DGuiApplicationHelper::instance()->themeTypeChanged(DGuiApplicationHelper::instance()->themeType()); } MainWindow::~MainWindow() @@ -135,13 +133,14 @@ void MainWindow::initUI() updateUi(0); initTrayIcon(); + + refreshTheme(ThemeChecker::instance()->useDarkTheme()); } void MainWindow::initTitleBar() { ui->titlebar->setIcon(QIcon::fromTheme("spark-store")); ui->titlebar->setBackgroundTransparent(true); - ui->titlebar->setSwitchThemeMenuVisible(false); // 去除 dtk 标题栏主题切换菜单 // 初始化标题栏控件 DLabel *title = new DLabel(ui->titlebar); @@ -320,40 +319,10 @@ void MainWindow::refreshTheme(bool isDarkMode) ui->settingspage->setTheme(isDarkMode); } -void MainWindow::onThemeChanged(bool isDark) { - DGuiApplicationHelper::ColorType currentTheme = DGuiApplicationHelper::instance()->themeType(); - - // 检查当前外观设置 - bool isUserSetDark = (currentTheme == DGuiApplicationHelper::DarkType); //当前已经是深色模式 - bool isUserSetWhite = (currentTheme == DGuiApplicationHelper::LightType); //当前已经是浅色模式 - - // 检查 isDark 为 true 时, isUserSetDark 是否为 true - // 检查 isDark 为 false , isUserSetWhite 是否为 ture - qDebug() << isUserSetDark << isUserSetWhite << isDark; - - - if ((isUserSetDark != isDark) || (isUserSetWhite == !isDark)) { - // 否则,根据传入的 isDark 值设置 - refreshTheme(isDark); - } - -} - - void MainWindow::initConnections() { - // 主题切换 - connect(DGuiApplicationHelper::instance(), &DGuiApplicationHelper::themeTypeChanged, this, [=](DGuiApplicationHelper::ColorType themeType) - { - bool isDarkMode = (themeType == DGuiApplicationHelper::ColorType::DarkType); - refreshTheme(isDarkMode); - }); - - ThemeChecker *themeChecker = new ThemeChecker(this); - connect(themeChecker, SIGNAL(themeChanged(bool)), this, SLOT(onThemeChanged(bool))); - - + connect(ThemeChecker::instance(), &ThemeChecker::themeChanged, this, &MainWindow::refreshTheme); // appintopage按下下载按钮时标题栏下载列表按钮抖动 connect(ui->appintopage, &AppIntoPage::clickedDownloadBtn, [=]() diff --git a/src/mainwindow-dtk.h b/src/mainwindow-dtk.h old mode 100644 new mode 100755 index 4831a59..a5621c3 --- a/src/mainwindow-dtk.h +++ b/src/mainwindow-dtk.h @@ -30,8 +30,7 @@ public: void openUrl(const QString &url); bool isCloseWindowAnimation(); - void refreshTheme(bool isDarkMode); - + Q_INVOKABLE void refreshTheme(bool isDarkMode); protected: void closeEvent(QCloseEvent *event) override; @@ -50,7 +49,6 @@ private: public slots: void notify(QObject *receiver, QEvent *event); - void onThemeChanged(bool isDark); private slots: //接受来自dbus的url