KConfig

kconfigwatcher.cpp
1 /*
2  SPDX-FileCopyrightText: 2018 David Edmundson <davidedmundson@kde.org>
3  SPDX-FileCopyrightText: 2023 Harald Sitter <sitter@kde.org>
4 
5  SPDX-License-Identifier: LGPL-2.0-or-later
6 */
7 
8 #include "kconfigwatcher.h"
9 
10 #include "config-kconfig.h"
11 #include "kconfig_core_log_settings.h"
12 
13 #if KCONFIG_USE_DBUS
14 #include <QDBusConnection>
15 #include <QDBusMessage>
16 #include <QDBusMetaType>
17 
18 #include "dbussanitizer_p.h"
19 #endif
20 
21 #include <QDebug>
22 #include <QHash>
23 #include <QThreadStorage>
24 
25 class KConfigWatcherPrivate
26 {
27 public:
28  KSharedConfig::Ptr m_config;
29 };
30 
32 {
34 
35  auto c = config.data();
36  KConfigWatcher::Ptr watcher;
37 
38  if (!watcherList.localData().contains(c)) {
40 
41  watcherList.localData().insert(c, watcher.toWeakRef());
42 
43  QObject::connect(watcher.data(), &QObject::destroyed, [c]() {
44  watcherList.localData().remove(c);
45  });
46  }
47  return watcherList.localData().value(c).toStrongRef();
48 }
49 
50 KConfigWatcher::KConfigWatcher(const KSharedConfig::Ptr &config)
51  : QObject(nullptr)
52  , d(new KConfigWatcherPrivate)
53 {
54  Q_ASSERT(config);
55  d->m_config = config;
56 
57 #if KCONFIG_USE_DBUS
58 
59  if (config->name().isEmpty()) {
60  return;
61  }
62 
63  // Watching absolute paths is not supported and also makes no sense.
64  const bool isAbsolutePath = config->name().at(0) == QLatin1Char('/');
65  if (isAbsolutePath) {
66  qCWarning(KCONFIG_CORE_LOG) << "Watching absolute paths is not supported" << config->name();
67  return;
68  }
69 
70  qDBusRegisterMetaType<QByteArrayList>();
71  qDBusRegisterMetaType<QHash<QString, QByteArrayList>>();
72 
73  QStringList watchedPaths = d->m_config->additionalConfigSources();
74  for (QString &file : watchedPaths) {
75  file.prepend(QLatin1Char('/'));
76  }
77  watchedPaths.prepend(kconfigDBusSanitizePath(QLatin1Char('/') + d->m_config->name()));
78 
79  if (d->m_config->openFlags() & KConfig::IncludeGlobals) {
80  watchedPaths << QStringLiteral("/kdeglobals");
81  }
82 
83  for (const QString &path : std::as_const(watchedPaths)) {
85  path,
86  QStringLiteral("org.kde.kconfig.notify"),
87  QStringLiteral("ConfigChanged"),
88  this,
89  // clang-format off
90  SLOT(onConfigChangeNotification(QHash<QString,QByteArrayList>))
91  // clang-format on
92  );
93  }
94 #else
95  qCWarning(KCONFIG_CORE_LOG) << "Use of KConfigWatcher without DBus support. You will not receive updates";
96 #endif
97 }
98 
99 KConfigWatcher::~KConfigWatcher() = default;
100 
102 {
103  return d->m_config;
104 }
105 
106 void KConfigWatcher::onConfigChangeNotification(const QHash<QString, QByteArrayList> &changes)
107 {
108  // should we ever need it we can determine the file changed with QDbusContext::message().path(), but it doesn't seem too useful
109 
110  d->m_config->reparseConfiguration();
111 
112  for (auto it = changes.constBegin(); it != changes.constEnd(); it++) {
113  KConfigGroup group = d->m_config->group(QString()); // top level group
114  const auto parts = it.key().split(QLatin1Char('\x1d')); // magic char, see KConfig
115  for (const QString &groupName : parts) {
116  group = group.group(groupName);
117  }
118  Q_EMIT configChanged(group, it.value());
119  }
120 }
121 
122 #include "moc_kconfigwatcher.cpp"
bool connect(const QString &service, const QString &path, const QString &interface, const QString &name, QObject *receiver, const char *slot)
T * data() const const
Q_EMITQ_EMIT
void configChanged(const KConfigGroup &group, const QByteArrayList &names)
Emitted when a config group has changed The config will be reloaded before this signal is emitted.
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
void destroyed(QObject *obj)
QDBusConnection sessionBus()
QHash::const_iterator constBegin() const const
QHash::const_iterator constEnd() const const
static Ptr create(const KSharedConfig::Ptr &config)
Instantiate a ConfigWatcher for a given config.
@ IncludeGlobals
Blend kdeglobals into the config object.
Definition: kconfig.h:82
KConfigGroup group(const QString &group)
Returns an object for the named subgroup.
Definition: kconfigbase.cpp:21
KSharedConfig::Ptr config() const
Returns the config being watched.
QWeakPointer< T > toWeakRef() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Thu Feb 15 2024 04:07:59 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.