aboutsummaryrefslogtreecommitdiff
path: root/src/qml/kconfigpropertymap.cpp
diff options
context:
space:
mode:
authorAlexander Lohnau <alexander.lohnau@gmx.de>2021-11-07 21:34:18 +0100
committerAlexander Lohnau <alexander.lohnau@gmx.de>2021-11-22 09:36:02 +0000
commit3f29f3d6452f735757cb8f84dfc20cdcba791613 (patch)
tree11f40ed6a40cc3368fedfea193f4994c3447348b /src/qml/kconfigpropertymap.cpp
parentc3be6d02f6c061707c6d93e06889a2e56b994d87 (diff)
downloadkconfig-3f29f3d6452f735757cb8f84dfc20cdcba791613.tar.gz
kconfig-3f29f3d6452f735757cb8f84dfc20cdcba791613.tar.bz2
Copy ConfigPropertyMap from KDeclarative to new KConfig QML module
This way consumers which want to use the ConfigPropertyMap don't have to pull in KDeclarative's entire dependency tree. Also we can remove the automatic saving of the config, previously this was opt-out - which makes is difficult to deprecate anything. This way the API design is also more clear, since the object only takes care of exposing the data to QML. The writing has to be done manually, which makes more sense anyways when we have the notify opt-in. As discussed on the KF6 weekly thread, an optional QML submodule is seen as the best way to handle the QML dependency. Task: https://phabricator.kde.org/T12131 Relates to https://phabricator.kde.org/T12126, after his change the KDeclarative stuff can be deprecated. Because we don't register the property map in any QML plugin, there is no conflict in duplicating and modifying it now.
Diffstat (limited to 'src/qml/kconfigpropertymap.cpp')
-rw-r--r--src/qml/kconfigpropertymap.cpp148
1 files changed, 148 insertions, 0 deletions
diff --git a/src/qml/kconfigpropertymap.cpp b/src/qml/kconfigpropertymap.cpp
new file mode 100644
index 00000000..55b2991d
--- /dev/null
+++ b/src/qml/kconfigpropertymap.cpp
@@ -0,0 +1,148 @@
+/*
+ SPDX-FileCopyrightText: 2013 Marco Martin <notmart@gmail.com>
+ SPDX-FileCopyrightText: 2020 David Edmundson <davidedmundson@kde.org>
+ SPDX-FileCopyrightText: 2021 Alexander Lohnau <alexander.lohnau@gmx.de>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#include "kconfigpropertymap.h"
+
+#include <KCoreConfigSkeleton>
+#include <QJSValue>
+#include <QPointer>
+
+#include <functional>
+
+class KConfigPropertyMapPrivate
+{
+public:
+ KConfigPropertyMapPrivate(KConfigPropertyMap *map)
+ : q(map)
+ {
+ }
+
+ enum LoadConfigOption {
+ DontEmitValueChanged,
+ EmitValueChanged,
+ };
+
+ void loadConfig(LoadConfigOption option);
+ void writeConfig();
+ void writeConfigValue(const QString &key, const QVariant &value);
+
+ KConfigPropertyMap *q;
+ QPointer<KCoreConfigSkeleton> config;
+ bool updatingConfigValue = false;
+ bool autosave = true;
+ bool notify = false;
+};
+
+KConfigPropertyMap::KConfigPropertyMap(KCoreConfigSkeleton *config, QObject *parent)
+ : QQmlPropertyMap(this, parent)
+ , d(new KConfigPropertyMapPrivate(this))
+{
+ Q_ASSERT(config);
+ d->config = config;
+
+ // Reload the config only if the change signal has *not* been emitted by ourselves updating the config
+ connect(config, &KCoreConfigSkeleton::configChanged, this, [this]() {
+ if (!d->updatingConfigValue) {
+ d->loadConfig(KConfigPropertyMapPrivate::EmitValueChanged);
+ }
+ });
+ connect(this, &KConfigPropertyMap::valueChanged, this, [this](const QString &key, const QVariant &value) {
+ d->writeConfigValue(key, value);
+ });
+
+ d->loadConfig(KConfigPropertyMapPrivate::DontEmitValueChanged);
+}
+
+KConfigPropertyMap::~KConfigPropertyMap() = default;
+
+bool KConfigPropertyMap::isNotify() const
+{
+ return d->notify;
+}
+
+void KConfigPropertyMap::setNotify(bool notify)
+{
+ d->notify = notify;
+}
+
+void KConfigPropertyMap::writeConfig()
+{
+ d->writeConfig();
+}
+
+QVariant KConfigPropertyMap::updateValue(const QString &key, const QVariant &input)
+{
+ Q_UNUSED(key);
+ if (input.userType() == qMetaTypeId<QJSValue>()) {
+ return input.value<QJSValue>().toVariant();
+ }
+ return input;
+}
+
+bool KConfigPropertyMap::isImmutable(const QString &key) const
+{
+ KConfigSkeletonItem *item = d->config.data()->findItem(key);
+ if (item) {
+ return item->isImmutable();
+ }
+
+ return false;
+}
+
+void KConfigPropertyMapPrivate::loadConfig(KConfigPropertyMapPrivate::LoadConfigOption option)
+{
+ if (!config) {
+ return;
+ }
+
+ const auto &items = config.data()->items();
+ for (KConfigSkeletonItem *item : items) {
+ q->insert(item->key() + QStringLiteral("Default"), item->getDefault());
+ q->insert(item->key(), item->property());
+ if (option == EmitValueChanged) {
+ Q_EMIT q->valueChanged(item->key(), item->property());
+ }
+ }
+}
+
+void KConfigPropertyMapPrivate::writeConfig()
+{
+ if (!config) {
+ return;
+ }
+
+ const auto lstItems = config.data()->items();
+ for (KConfigSkeletonItem *item : lstItems) {
+ item->setWriteFlags(notify ? KConfigBase::Notify : KConfigBase::Normal);
+ item->setProperty(q->value(item->key()));
+ }
+
+ if (autosave) {
+ updatingConfigValue = true;
+ config.data()->save();
+ updatingConfigValue = false;
+ }
+}
+
+void KConfigPropertyMapPrivate::writeConfigValue(const QString &key, const QVariant &value)
+{
+ KConfigSkeletonItem *item = config.data()->findItem(key);
+ if (item) {
+ updatingConfigValue = true;
+ item->setWriteFlags(notify ? KConfigBase::Notify : KConfigBase::Normal);
+ item->setProperty(value);
+ if (autosave) {
+ config.data()->save();
+ // why read? read will update KConfigSkeletonItem::mLoadedValue,
+ // allowing a write operation to be performed next time
+ config.data()->read();
+ }
+ updatingConfigValue = false;
+ }
+}
+