diff options
author | David Edmundson <kde@davidedmundson.co.uk> | 2018-10-10 14:48:49 +0100 |
---|---|---|
committer | David Edmundson <kde@davidedmundson.co.uk> | 2018-10-10 14:51:04 +0100 |
commit | 8579ec54838b7188ed016f7adb4a69bbf2e39712 (patch) | |
tree | b9614b014ba779dae40e96069fc2cadeeecea9de /src/core/kconfigwatcher.cpp | |
parent | 8e56083463374fa6525b5feff4373b5ab58914bb (diff) | |
download | kconfig-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.cpp | 107 |
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()); + } +} + |