File indexing completed on 2024-05-12 03:54:31

0001 /*
0002     SPDX-FileCopyrightText: 2013 Marco Martin <notmart@gmail.com>
0003     SPDX-FileCopyrightText: 2020 David Edmundson <davidedmundson@kde.org>
0004     SPDX-FileCopyrightText: 2021 Alexander Lohnau <alexander.lohnau@gmx.de>
0005 
0006     SPDX-License-Identifier: LGPL-2.0-or-later
0007 */
0008 
0009 #include "kconfigpropertymap.h"
0010 
0011 #include <KCoreConfigSkeleton>
0012 #include <QJSValue>
0013 #include <QPointer>
0014 
0015 #include <functional>
0016 
0017 class KConfigPropertyMapPrivate
0018 {
0019 public:
0020     KConfigPropertyMapPrivate(KConfigPropertyMap *map)
0021         : q(map)
0022     {
0023     }
0024 
0025     enum LoadConfigOption {
0026         DontEmitValueChanged,
0027         EmitValueChanged,
0028     };
0029 
0030     void loadConfig(LoadConfigOption option);
0031     void writeConfig();
0032     void writeConfigValue(const QString &key, const QVariant &value);
0033 
0034     KConfigPropertyMap *q;
0035     QPointer<KCoreConfigSkeleton> config;
0036     bool updatingConfigValue = false;
0037     bool notify = false;
0038 };
0039 
0040 KConfigPropertyMap::KConfigPropertyMap(KCoreConfigSkeleton *config, QObject *parent)
0041     : QQmlPropertyMap(this, parent)
0042     , d(new KConfigPropertyMapPrivate(this))
0043 {
0044     Q_ASSERT(config);
0045     d->config = config;
0046 
0047     // Reload the config only if the change signal has *not* been emitted by ourselves updating the config
0048     connect(config, &KCoreConfigSkeleton::configChanged, this, [this]() {
0049         if (!d->updatingConfigValue) {
0050             d->loadConfig(KConfigPropertyMapPrivate::EmitValueChanged);
0051         }
0052     });
0053     connect(this, &KConfigPropertyMap::valueChanged, this, [this](const QString &key, const QVariant &value) {
0054         d->writeConfigValue(key, value);
0055     });
0056 
0057     d->loadConfig(KConfigPropertyMapPrivate::DontEmitValueChanged);
0058 }
0059 
0060 KConfigPropertyMap::~KConfigPropertyMap() = default;
0061 
0062 bool KConfigPropertyMap::isNotify() const
0063 {
0064     return d->notify;
0065 }
0066 
0067 void KConfigPropertyMap::setNotify(bool notify)
0068 {
0069     d->notify = notify;
0070 }
0071 
0072 void KConfigPropertyMap::writeConfig()
0073 {
0074     d->writeConfig();
0075 }
0076 
0077 QVariant KConfigPropertyMap::updateValue(const QString &key, const QVariant &input)
0078 {
0079     Q_UNUSED(key);
0080     if (input.userType() == qMetaTypeId<QJSValue>()) {
0081         return input.value<QJSValue>().toVariant();
0082     }
0083     return input;
0084 }
0085 
0086 bool KConfigPropertyMap::isImmutable(const QString &key) const
0087 {
0088     KConfigSkeletonItem *item = d->config.data()->findItem(key);
0089     if (item) {
0090         return item->isImmutable();
0091     }
0092 
0093     return false;
0094 }
0095 
0096 void KConfigPropertyMapPrivate::loadConfig(KConfigPropertyMapPrivate::LoadConfigOption option)
0097 {
0098     if (!config) {
0099         return;
0100     }
0101 
0102     const auto &items = config.data()->items();
0103     for (KConfigSkeletonItem *item : items) {
0104         q->insert(item->key() + QStringLiteral("Default"), item->getDefault());
0105         q->insert(item->key(), item->property());
0106         if (option == EmitValueChanged) {
0107             Q_EMIT q->valueChanged(item->key(), item->property());
0108         }
0109     }
0110 }
0111 
0112 void KConfigPropertyMapPrivate::writeConfig()
0113 {
0114     if (!config) {
0115         return;
0116     }
0117 
0118     const auto lstItems = config.data()->items();
0119     for (KConfigSkeletonItem *item : lstItems) {
0120         item->setWriteFlags(notify ? KConfigBase::Notify : KConfigBase::Normal);
0121         item->setProperty(q->value(item->key()));
0122     }
0123     // Internally sync the config. This way we ensure the config file is written, even if the process crashed
0124     config.data()->save();
0125 }
0126 
0127 void KConfigPropertyMapPrivate::writeConfigValue(const QString &key, const QVariant &value)
0128 {
0129     KConfigSkeletonItem *item = config.data()->findItem(key);
0130     if (item) {
0131         updatingConfigValue = true;
0132         item->setWriteFlags(notify ? KConfigBase::Notify : KConfigBase::Normal);
0133         item->setProperty(value);
0134         updatingConfigValue = false;
0135     }
0136 }
0137 
0138 #include "moc_kconfigpropertymap.cpp"