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"