1/*
2 SPDX-FileCopyrightText: 2013 Marco Martin <notmart@gmail.com>
3 SPDX-FileCopyrightText: 2020 David Edmundson <davidedmundson@kde.org>
4 SPDX-FileCopyrightText: 2021 Alexander Lohnau <alexander.lohnau@gmx.de>
5
6 SPDX-License-Identifier: LGPL-2.0-or-later
7*/
8
9#include "kconfigpropertymap.h"
10
11#include <KCoreConfigSkeleton>
12#include <QJSValue>
13#include <QPointer>
14
15class KConfigPropertyMapPrivate
16{
17public:
18 KConfigPropertyMapPrivate(KConfigPropertyMap *map)
19 : q(map)
20 {
21 }
22
23 enum LoadConfigOption {
24 DontEmitValueChanged,
25 EmitValueChanged,
26 };
27
28 void loadConfig(LoadConfigOption option);
29 void writeConfig();
30 void writeConfigValue(const QString &key, const QVariant &value);
31
32 KConfigPropertyMap *q;
33 QPointer<KCoreConfigSkeleton> config;
34 bool updatingConfigValue = false;
35 bool notify = false;
36};
37
38KConfigPropertyMap::KConfigPropertyMap(KCoreConfigSkeleton *config, QObject *parent)
39 : QQmlPropertyMap(this, parent)
40 , d(new KConfigPropertyMapPrivate(this))
41{
42 Q_ASSERT(config);
43 d->config = config;
44
45 // Reload the config only if the change signal has *not* been emitted by ourselves updating the config
46 connect(sender: config, signal: &KCoreConfigSkeleton::configChanged, context: this, slot: [this]() {
47 if (!d->updatingConfigValue) {
48 d->loadConfig(option: KConfigPropertyMapPrivate::EmitValueChanged);
49 }
50 });
51 connect(sender: this, signal: &KConfigPropertyMap::valueChanged, context: this, slot: [this](const QString &key, const QVariant &value) {
52 d->writeConfigValue(key, value);
53 });
54
55 d->loadConfig(option: KConfigPropertyMapPrivate::DontEmitValueChanged);
56}
57
58KConfigPropertyMap::~KConfigPropertyMap() = default;
59
60bool KConfigPropertyMap::isNotify() const
61{
62 return d->notify;
63}
64
65void KConfigPropertyMap::setNotify(bool notify)
66{
67 d->notify = notify;
68}
69
70void KConfigPropertyMap::writeConfig()
71{
72 d->writeConfig();
73}
74
75QVariant KConfigPropertyMap::updateValue(const QString &key, const QVariant &input)
76{
77 Q_UNUSED(key);
78 if (input.userType() == qMetaTypeId<QJSValue>()) {
79 return input.value<QJSValue>().toVariant();
80 }
81 return input;
82}
83
84bool KConfigPropertyMap::isImmutable(const QString &key) const
85{
86 KConfigSkeletonItem *item = d->config->findItem(name: key);
87 if (item) {
88 return item->isImmutable();
89 }
90
91 return false;
92}
93
94void KConfigPropertyMapPrivate::loadConfig(KConfigPropertyMapPrivate::LoadConfigOption option)
95{
96 if (!config) {
97 return;
98 }
99
100 const auto &items = config->items();
101 for (KConfigSkeletonItem *item : items) {
102 q->insert(key: item->key() + QStringLiteral("Default"), value: item->getDefault());
103 q->insert(key: item->key(), value: item->property());
104 if (option == EmitValueChanged) {
105 Q_EMIT q->valueChanged(key: item->key(), value: item->property());
106 }
107 }
108}
109
110void KConfigPropertyMapPrivate::writeConfig()
111{
112 if (!config) {
113 return;
114 }
115
116 const auto lstItems = config->items();
117 for (KConfigSkeletonItem *item : lstItems) {
118 item->setWriteFlags(notify ? KConfigBase::Notify : KConfigBase::Normal);
119 item->setProperty(q->value(key: item->key()));
120 }
121 // Internally sync the config. This way we ensure the config file is written, even if the process crashed
122 config->save();
123}
124
125void KConfigPropertyMapPrivate::writeConfigValue(const QString &key, const QVariant &value)
126{
127 if (KConfigSkeletonItem *item = config->findItem(name: key)) {
128 updatingConfigValue = true;
129 item->setWriteFlags(notify ? KConfigBase::Notify : KConfigBase::Normal);
130 item->setProperty(value);
131 updatingConfigValue = false;
132 }
133}
134
135#include "moc_kconfigpropertymap.cpp"
136

source code of kconfig/src/qml/kconfigpropertymap.cpp