File indexing completed on 2024-05-12 17:07:45

0001 // SPDX-FileCopyrightText: 2022 Devin Lin <devin@kde.org>
0002 // SPDX-License-Identifier: LGPL-2.0-or-later
0003 
0004 #include "savedquicksettings.h"
0005 
0006 #include <KPackage/PackageLoader>
0007 
0008 #include <QFileInfo>
0009 
0010 SavedQuickSettings::SavedQuickSettings(QObject *parent)
0011     : QObject{parent}
0012     , m_settings{new MobileShellSettings{this}}
0013     , m_validPackages{}
0014     , m_enabledPackages{}
0015     , m_disabledPackages{}
0016     , m_enabledQSModel{new SavedQuickSettingsModel{this}}
0017     , m_disabledQSModel{new SavedQuickSettingsModel{this}}
0018     , m_updateTimer{new QTimer{this}}
0019     , m_saveTimer{new QTimer{this}}
0020 {
0021     // throttle model updates from config, to avoid performance issues with fast reloading
0022     m_updateTimer->setInterval(2000);
0023     m_updateTimer->setSingleShot(true);
0024     connect(m_updateTimer, &QTimer::timeout, this, [this]() {
0025         refreshModel();
0026     });
0027 
0028     // throttle saving so that we don't have conflicts while writing and then getting notified about updates
0029     m_saveTimer->setInterval(1000);
0030     m_saveTimer->setSingleShot(true);
0031     connect(m_saveTimer, &QTimer::timeout, this, [this]() {
0032         saveModel();
0033     });
0034 
0035     // load quicksettings packages
0036     auto packages = KPackage::PackageLoader::self()->listPackages(QStringLiteral("KPackage/GenericQML"), "plasma/quicksettings");
0037 
0038     for (auto &metaData : packages) {
0039         KPackage::Package package = KPackage::PackageLoader::self()->loadPackage("KPackage/GenericQML", QFileInfo(metaData.fileName()).path());
0040         if (!package.isValid()) {
0041             qWarning() << "Quick setting package invalid:" << metaData.fileName();
0042             continue;
0043         }
0044         m_validPackages.push_back(new KPluginMetaData{metaData});
0045     }
0046 
0047     // subscribe to config changes
0048     connect(m_settings, &MobileShellSettings::enabledQuickSettingsChanged, this, [this]() {
0049         m_updateTimer->start();
0050     });
0051     connect(m_settings, &MobileShellSettings::disabledQuickSettingsChanged, this, [this]() {
0052         m_updateTimer->start();
0053     });
0054 
0055     // subscribe to model changes
0056     connect(m_enabledQSModel, &SavedQuickSettingsModel::dataUpdated, this, [this](QList<KPluginMetaData *> data) -> void {
0057         m_enabledPackages.clear();
0058         for (auto metaData : data) {
0059             m_enabledPackages.push_back(metaData);
0060         }
0061 
0062         m_saveTimer->start();
0063         if (m_updateTimer->isActive()) {
0064             m_updateTimer->start(); // reset update timer if it's running
0065         }
0066     });
0067     connect(m_disabledQSModel, &SavedQuickSettingsModel::dataUpdated, this, [this](QList<KPluginMetaData *> data) -> void {
0068         m_disabledPackages.clear();
0069         for (auto metaData : data) {
0070             m_disabledPackages.push_back(metaData);
0071         }
0072 
0073         m_saveTimer->start();
0074         if (m_updateTimer->isActive()) {
0075             m_updateTimer->start(); // reset update timer if it's running
0076         }
0077     });
0078 
0079     // load
0080     refreshModel();
0081 }
0082 
0083 SavedQuickSettings::~SavedQuickSettings()
0084 {
0085     // save immediately if was requested
0086     if (m_saveTimer->isActive()) {
0087         saveModel();
0088     }
0089 }
0090 
0091 SavedQuickSettingsModel *SavedQuickSettings::enabledQuickSettingsModel() const
0092 {
0093     return m_enabledQSModel;
0094 }
0095 
0096 SavedQuickSettingsModel *SavedQuickSettings::disabledQuickSettingsModel() const
0097 {
0098     return m_disabledQSModel;
0099 }
0100 
0101 void SavedQuickSettings::refreshModel()
0102 {
0103     QList<QString> enabledQS = m_settings->enabledQuickSettings();
0104     QList<QString> disabledQS = m_settings->disabledQuickSettings();
0105 
0106     m_enabledPackages.clear();
0107     m_disabledPackages.clear();
0108 
0109     // add enabled quick settings in order
0110     for (const QString &pluginId : enabledQS) {
0111         for (auto &metaData : m_validPackages) {
0112             if (pluginId == metaData->pluginId()) {
0113                 m_enabledPackages.push_back(metaData);
0114                 break;
0115             }
0116         }
0117     }
0118 
0119     // add disabled quick settings in order
0120     for (const QString &pluginId : disabledQS) {
0121         for (auto &metaData : m_validPackages) {
0122             if (pluginId == metaData->pluginId()) {
0123                 m_disabledPackages.push_back(metaData);
0124                 break;
0125             }
0126         }
0127     }
0128 
0129     // add undefined quick settings to the back of enabled quick settings
0130     for (auto &metaData : m_validPackages) {
0131         if (!enabledQS.contains(metaData->pluginId()) && !disabledQS.contains(metaData->pluginId())) {
0132             m_enabledPackages.push_back(metaData);
0133         }
0134     }
0135 
0136     m_enabledQSModel->updateData(m_enabledPackages);
0137     m_disabledQSModel->updateData(m_disabledPackages);
0138 }
0139 
0140 void SavedQuickSettings::saveModel()
0141 {
0142     QList<QString> enabledQS;
0143     QList<QString> disabledQS;
0144 
0145     for (auto &metaData : m_enabledPackages) {
0146         enabledQS.push_back(metaData->pluginId());
0147     }
0148     for (auto &metaData : m_disabledPackages) {
0149         disabledQS.push_back(metaData->pluginId());
0150     }
0151 
0152     m_settings->setEnabledQuickSettings(enabledQS);
0153     m_settings->setDisabledQuickSettings(disabledQS);
0154 }