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 | |
15 | class KConfigPropertyMapPrivate |
16 | { |
17 | public: |
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 | |
38 | KConfigPropertyMap::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 | |
58 | KConfigPropertyMap::~KConfigPropertyMap() = default; |
59 | |
60 | bool KConfigPropertyMap::isNotify() const |
61 | { |
62 | return d->notify; |
63 | } |
64 | |
65 | void KConfigPropertyMap::setNotify(bool notify) |
66 | { |
67 | d->notify = notify; |
68 | } |
69 | |
70 | void KConfigPropertyMap::writeConfig() |
71 | { |
72 | d->writeConfig(); |
73 | } |
74 | |
75 | QVariant 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 | |
84 | bool 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 | |
94 | void 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 | |
110 | void 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 | |
125 | void 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 | |