From 8579ec54838b7188ed016f7adb4a69bbf2e39712 Mon Sep 17 00:00:00 2001 From: David Edmundson Date: Wed, 10 Oct 2018 14:48:49 +0100 Subject: 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 --- src/core/kconfig.cpp | 55 +++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 50 insertions(+), 5 deletions(-) (limited to 'src/core/kconfig.cpp') diff --git a/src/core/kconfig.cpp b/src/core/kconfig.cpp index e4c9935b..df3ad471 100644 --- a/src/core/kconfig.cpp +++ b/src/core/kconfig.cpp @@ -23,6 +23,8 @@ #include "kconfig.h" #include "kconfig_p.h" +#include "config-kconfig.h" + #include #include @@ -54,6 +56,12 @@ static inline int pclose(FILE *stream) #include #include +#if KCONFIG_USE_DBUS +#include +#include +#include +#endif + bool KConfigPrivate::mappingsRegistered = false; Q_GLOBAL_STATIC(QStringList, s_globalFiles) // For caching purposes. @@ -424,6 +432,9 @@ bool KConfig::sync() return false; } + QHash notifyGroupsLocal; + QHash notifyGroupsGlobal; + if (d->bDirty && d->mBackend) { const QByteArray utf8Locale(locale().toUtf8()); @@ -439,16 +450,20 @@ bool KConfig::sync() // Rewrite global/local config only if there is a dirty entry in it. bool writeGlobals = false; bool writeLocals = false; - Q_FOREACH (const KEntry &e, d->entryMap) { + + for (auto it = d->entryMap.constBegin(); it != d->entryMap.constEnd(); ++it) { + auto e = it.value(); if (e.bDirty) { if (e.bGlobal) { writeGlobals = true; + if (e.bNotify) { + notifyGroupsGlobal[QString::fromUtf8(it.key().mGroup)] << it.key().mKey; + } } else { writeLocals = true; - } - - if (writeGlobals && writeLocals) { - break; + if (e.bNotify) { + notifyGroupsLocal[QString::fromUtf8(it.key().mGroup)] << it.key().mKey; + } } } } @@ -485,9 +500,35 @@ bool KConfig::sync() d->mBackend->unlock(); } } + + if (!notifyGroupsLocal.isEmpty()) { + d->notifyClients(notifyGroupsLocal, QStringLiteral("/") + name()); + } + if (!notifyGroupsGlobal.isEmpty()) { + d->notifyClients(notifyGroupsGlobal, QStringLiteral("/kdeglobals")); + } + return !d->bDirty; } +void KConfigPrivate::notifyClients(const QHash &changes, const QString &path) +{ +#if KCONFIG_USE_DBUS + qDBusRegisterMetaType(); + + qDBusRegisterMetaType>(); + + QDBusMessage message = QDBusMessage::createSignal(path, + QStringLiteral("org.kde.kconfig.notify"), + QStringLiteral("ConfigChanged")); + message.setArguments({QVariant::fromValue(changes)}); + QDBusConnection::sessionBus().send(message); +#else + Q_UNUSED(changes) + Q_UNUSED(path) +#endif +} + void KConfig::markAsClean() { Q_D(KConfig); @@ -497,6 +538,7 @@ void KConfig::markAsClean() const KEntryMapIterator theEnd = d->entryMap.end(); for (KEntryMapIterator it = d->entryMap.begin(); it != theEnd; ++it) { it->bDirty = false; + it->bNotify = false; } } @@ -874,6 +916,9 @@ KEntryMap::EntryOptions convertToOptions(KConfig::WriteConfigFlags flags) if (flags & KConfig::Localized) { options |= KEntryMap::EntryLocalized; } + if (flags & KConfig::Notify) { + options |= KEntryMap::EntryNotify; + } return options; } -- cgit v1.2.1