aboutsummaryrefslogtreecommitdiff
path: root/src/core/kconfigwatcher.cpp
diff options
context:
space:
mode:
authorDavid Edmundson <kde@davidedmundson.co.uk>2018-10-10 14:48:49 +0100
committerDavid Edmundson <kde@davidedmundson.co.uk>2018-10-10 14:51:04 +0100
commit8579ec54838b7188ed016f7adb4a69bbf2e39712 (patch)
treeb9614b014ba779dae40e96069fc2cadeeecea9de /src/core/kconfigwatcher.cpp
parent8e56083463374fa6525b5feff4373b5ab58914bb (diff)
downloadkconfig-8579ec54838b7188ed016f7adb4a69bbf2e39712.tar.gz
kconfig-8579ec54838b7188ed016f7adb4a69bbf2e39712.tar.bz2
Add mechanism to notify other clients of config changes over DBus
Summary: Intention is not to create a registry like system, but to replace KDElibs4Support::KGlobalSettings and to replace other system settingss -> some app communication in a more generic way. writeEntry gains an additional flag Notify which if set, will notify clients of what has actually changed when we sync. Rationale to put this into KConfig was so that we could have everything batched and sychronised to the file sync and to get the fine detailed exposure of what has actually changed which we don't get with a file watcher. Default behaviour remains identical without any broadcast messages. As it is a new dependency it is purely optional and anything referencing DBus is not in the public API. Our deployment on platforms without DBus tend to be standalone applications anyway. Test Plan: Attached unit test Reviewers: broulik, dfaure Reviewed By: broulik, dfaure Subscribers: dfaure, broulik, zzag, kde-frameworks-devel Tags: #frameworks Differential Revision: https://phabricator.kde.org/D13034
Diffstat (limited to 'src/core/kconfigwatcher.cpp')
-rw-r--r--src/core/kconfigwatcher.cpp107
1 files changed, 107 insertions, 0 deletions
diff --git a/src/core/kconfigwatcher.cpp b/src/core/kconfigwatcher.cpp
new file mode 100644
index 00000000..96120c6a
--- /dev/null
+++ b/src/core/kconfigwatcher.cpp
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2018 David Edmundson <davidedmundson@kde.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "kconfigwatcher.h"
+
+#include "config-kconfig.h"
+
+#if KCONFIG_USE_DBUS
+#include <QDBusConnection>
+#include <QDBusMessage>
+#include <QDBusMetaType>
+#endif
+
+#include <QDebug>
+#include <QThreadStorage>
+#include <QHash>
+
+class KConfigWatcherPrivate {
+public:
+ KSharedConfig::Ptr m_config;
+};
+
+KConfigWatcher::Ptr KConfigWatcher::create(const KSharedConfig::Ptr &config)
+{
+ static QThreadStorage<QHash<KSharedConfig*, QWeakPointer<KConfigWatcher>>> watcherList;
+
+ auto c = config.data();
+ KConfigWatcher::Ptr watcher;
+
+ if (!watcherList.localData().contains(c)) {
+ watcher = KConfigWatcher::Ptr(new KConfigWatcher(config));
+
+ watcherList.localData().insert(c, watcher.toWeakRef());
+
+ QObject::connect(watcher.data(), &QObject::destroyed, [c]() {
+ watcherList.localData().remove(c);
+ });
+ }
+ return watcherList.localData().value(c).toStrongRef();
+}
+
+KConfigWatcher::KConfigWatcher(const KSharedConfig::Ptr &config):
+ QObject (nullptr),
+ d(new KConfigWatcherPrivate)
+{
+ Q_ASSERT(config);
+#if KCONFIG_USE_DBUS
+
+ qDBusRegisterMetaType<QByteArrayList>();
+ qDBusRegisterMetaType<QHash<QString, QByteArrayList>>();
+
+ d->m_config = config;
+
+ QStringList watchedPaths;
+ watchedPaths <<QStringLiteral("/") + d->m_config->name();
+ for (const QString file: d->m_config->additionalConfigSources()) {
+ watchedPaths << QStringLiteral("/") + file;
+ }
+ if (d->m_config->openFlags() & KConfig::IncludeGlobals) {
+ watchedPaths << QStringLiteral("/kdeglobals");
+ }
+
+ for(const QString &path: qAsConst(watchedPaths)) {
+ QDBusConnection::sessionBus().connect(QString(),
+ path,
+ QStringLiteral("org.kde.kconfig.notify"),
+ QStringLiteral("ConfigChanged"),
+ this,
+ SLOT(onConfigChangeNotification(QHash<QString, QByteArrayList>)));
+ }
+#else
+ qWarning() << "Use of KConfigWatcher without DBus support. You will not receive updates"
+#endif
+}
+
+void KConfigWatcher::onConfigChangeNotification(const QHash<QString, QByteArrayList> &changes)
+{
+ //should we ever need it we can determine the file changed with QDbusContext::message().path(), but it doesn't seem too useful
+
+ d->m_config->reparseConfiguration();
+
+ for(auto it = changes.constBegin(); it != changes.constEnd(); it++) {
+ KConfigGroup group = d->m_config->group(QString());//top level group
+ const auto parts = it.key().split(QLatin1Char('\x1d')); //magic char, see KConfig
+ for(const QString &groupName: parts) {
+ group = group.group(groupName);
+ }
+ emit configChanged(group, it.value());
+ }
+}
+