1/****************************************************************************
2**
3** Copyright (C) 2015 The Qt Company Ltd and/or its subsidiary(-ies).
4** Contact: http://www.qt-project.org/legal
5**
6** This file is part of the QtSystems module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL21$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see http://www.qt.io/terms-conditions. For further
15** information use the contact form at http://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 2.1 or version 3 as published by the Free
20** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22** following information to ensure the GNU Lesser General Public License
23** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25**
26** As a special exception, The Qt Company gives you certain additional
27** rights. These rights are described in The Qt Company LGPL Exception
28** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29**
30** $QT_END_LICENSE$
31**
32****************************************************************************/
33
34#include <qvaluespacepublisher.h>
35
36#include "qvaluespace_p.h"
37#include "qvaluespacemanager_p.h"
38
39#include <QtCore/qmetaobject.h>
40
41QT_BEGIN_NAMESPACE
42
43/*!
44 \class QValueSpacePublisher
45 \brief The QValueSpacePublisher class allows applications to publish values in the Value Space.
46 \inmodule QtPublishSubscribe
47 \ingroup publishsubscribe
48
49 When multiple Value Space layers are available QValueSpacePublisher only publishes values to
50 the layer with the highest priority. The layers that QValueSpacePublisher can access can be
51 limited by specifying either a \l {QValueSpace::LayerOption}{filter} or a QUuid at construction
52 time.
53
54 The lifetime of values published in the Value Space is specified by the particular Value Space
55 layer that the value is published in. For details on the different behaviors see
56 QValueSpace::LayerOption.
57
58 Once a value is published all applications in the system will have read access to it via the
59 QValueSpaceSubscriber class.
60
61 Although, logically, the Value Space is a simple collection of
62 hierarchical paths, these paths can conceptually be visualized as a set of
63 objects with attributes. For example, rather than viewing the following list
64 as 12 distinct Value Space paths:
65
66 \code
67 /Device/Network/Interfaces/eth0/Name
68 /Device/Network/Interfaces/eth0/Type
69 /Device/Network/Interfaces/eth0/Status
70 /Device/Network/Interfaces/eth0/BytesSent
71 /Device/Network/Interfaces/eth0/BytesReceived
72 /Device/Network/Interfaces/eth0/Time
73 /Device/Network/Interfaces/ppp0/Name
74 /Device/Network/Interfaces/ppp0/Type
75 /Device/Network/Interfaces/ppp0/Status
76 /Device/Network/Interfaces/ppp0/BytesSent
77 /Device/Network/Interfaces/ppp0/BytesReceived
78 /Device/Network/Interfaces/ppp0/Time
79 \endcode
80
81 it can be thought of as describing two Value Space objects,
82 \c { { /Device/Network/Interfaces/eth0, /Device/Network/Interfaces/ppp0 } },
83 each with the six attributes \c { {Name, Type, Status, BytesSent,
84 BytesReceived, Time} }. The QValueSpacePublisher class encapsulates this
85 abstraction.
86
87 For performance reasons the setting of and removing of attributes is buffered
88 internally by the QValueSpacePublisher and applied as a batch sometime later.
89 Normally this occurs the next time the application enters the Qt event loop,
90 but this behavior should not be relied upon. If an application must
91 synchronize with others, the QValueSpacePublisher::sync() and QValueSpacePublisher::syncAll()
92 functions can be used to force the application of changes. This call is generally unnecessary,
93 and should be used sparingly to prevent unnecessary load on the system.
94
95 \sa QValueSpaceSubscriber
96*/
97
98/*!
99 \fn void QValueSpacePublisher::interestChanged(const QString &attribute, bool interested)
100
101 Signal that is emitted when interest in \a attribute changes. If \a interested is true at
102 least on QValueSpaceSubscriber is interested in the value of \a attribute.
103*/
104
105class QValueSpacePublisherPrivate
106{
107public:
108 QValueSpacePublisherPrivate(const QString &path, QValueSpace::LayerOptions filter = QValueSpace::UnspecifiedLayer);
109 QValueSpacePublisherPrivate(const QString &path, const QUuid &uuid);
110
111 QString path;
112 QAbstractValueSpaceLayer *layer;
113 QAbstractValueSpaceLayer::Handle handle;
114
115 bool hasSet;
116 bool hasWatch;
117};
118
119QValueSpacePublisherPrivate::QValueSpacePublisherPrivate(const QString &_path, QValueSpace::LayerOptions filter)
120 : layer(0)
121 , handle(QAbstractValueSpaceLayer::InvalidHandle)
122 , hasSet(false)
123 , hasWatch(false)
124{
125 path = qCanonicalPath(path: _path);
126
127 // check filter for mutually exclusive options
128 if ((filter & QValueSpace::PermanentLayer && filter & QValueSpace::TransientLayer)
129 || (filter & QValueSpace::WritableLayer && filter & QValueSpace::ReadOnlyLayer)) {
130 return;
131 }
132
133 QList<QAbstractValueSpaceLayer *> layers = QValueSpaceManager::instance()->getLayers();
134
135 for (int ii = 0; ii < layers.count(); ++ii) {
136 if ((layers.at(i: ii)->layerOptions() & filter) == filter) {
137 QAbstractValueSpaceLayer::Handle h =
138 layers.at(i: ii)->item(parent: QAbstractValueSpaceLayer::InvalidHandle, subPath: path);
139
140 if (h != QAbstractValueSpaceLayer::InvalidHandle) {
141 layer = layers.at(i: ii);
142 handle = h;
143 break;
144 }
145 }
146 }
147}
148
149QValueSpacePublisherPrivate::QValueSpacePublisherPrivate(const QString &_path, const QUuid &uuid)
150 : layer(0)
151 , handle(QAbstractValueSpaceLayer::InvalidHandle)
152 , hasSet(false)
153 , hasWatch(false)
154{
155 path = qCanonicalPath(path: _path);
156
157 QList<QAbstractValueSpaceLayer *> layers = QValueSpaceManager::instance()->getLayers();
158
159 for (int ii = 0; ii < layers.count(); ++ii) {
160 if (layers.at(i: ii)->id() == uuid) {
161 layer = layers.at(i: ii);
162 handle = layer->item(parent: QAbstractValueSpaceLayer::InvalidHandle, subPath: path);
163 break;
164 }
165 }
166}
167
168/*!
169 Constructs a QValueSpacePublisher with the specified \a parent that publishes values under
170 \a path.
171*/
172QValueSpacePublisher::QValueSpacePublisher(const QString &path, QObject *parent)
173 : QObject(parent)
174 , d_ptr(new QValueSpacePublisherPrivate(path))
175{
176}
177
178/*!
179 Constructs a QValueSpacePublisher with the specified \a parent that publishes values under
180 \a path. The \a filter parameter is used to limit which layer this QValueSpacePublisher will
181 access.
182
183 The constructed Value Space publisher will access the layer with the highest priority that matches
184 \a filter and for which \a path is a valid path.
185
186 If no suitable layer is found, the constructed QValueSpacePublisher will be unconnected.
187
188 \sa isConnected()
189*/
190QValueSpacePublisher::QValueSpacePublisher(QValueSpace::LayerOptions filter, const QString &path, QObject *parent)
191 : QObject(parent)
192 , d_ptr(new QValueSpacePublisherPrivate(path, filter))
193{
194}
195
196/*!
197 Constructs a QValueSpacePublisher with the specified \a parent that publishes values under
198 \a path. Only the layer identified by \a uuid will be accessed by this publisher.
199
200 Use of this constructor is not platform agnostic. If possible use one of the constructors that
201 take a QValueSpace::LayerOptions parameter instead.
202
203 If a layer with a matching \a uuid is not found, the constructed QValueSpacePublisher will be
204 unconnected.
205
206 \sa isConnected()
207*/
208QValueSpacePublisher::QValueSpacePublisher(const QUuid &uuid, const QString &path, QObject *parent)
209 : QObject(parent)
210 , d_ptr(new QValueSpacePublisherPrivate(path, uuid))
211{
212}
213
214/*!
215 Destroys the QValueSpacePublisher. This will remove all values published by this publisher in
216 \l {QValueSpace::TransientLayer}{non-permanent} layers.
217*/
218QValueSpacePublisher::~QValueSpacePublisher()
219{
220 if (!isConnected())
221 return;
222
223 if (d_ptr->hasSet && !(d_ptr->layer->layerOptions() & QValueSpace::PermanentLayer))
224 d_ptr->layer->removeSubTree(creator: this, handle: d_ptr->handle);
225
226 if (d_ptr->hasWatch)
227 d_ptr->layer->removeWatches(creator: this, parent: d_ptr->handle);
228
229 delete d_ptr;
230}
231
232/*!
233 Returns the path that this QValueSpacePublisher refers to.
234*/
235QString QValueSpacePublisher::path() const
236{
237 return d_ptr->path;
238}
239
240/*!
241 Returns true if this QValueSpacePublisher is connected to an available layer; otherwise returns
242 false.
243*/
244bool QValueSpacePublisher::isConnected() const
245{
246 return (d_ptr->layer && d_ptr->handle != QAbstractValueSpaceLayer::InvalidHandle);
247}
248
249/*!
250 Forcibly sync all Value Space publisher using the same layer as this publisher.
251
252 For performance reasons attribute changes are batched internally by QValueSpacePublisher
253 instances. In cases where the visibility of changes must be synchronized with other processes,
254 calling this function will flush these batches. By the time this function returns, all other
255 processes in the system will be able to see the attribute changes.
256
257 Generally, calling this function is unnecessary.
258*/
259void QValueSpacePublisher::sync()
260{
261 if (!isConnected()) {
262 qWarning(msg: "sync called on unconnected QValueSpacePublisher.");
263 return;
264 }
265
266 d_ptr->layer->sync();
267}
268
269/*!
270 Sets the value \a name on the publisher to \a data. If name is empty, this call will set the
271 value of this publisher's path.
272
273 For example:
274
275 \code
276 QValueSpacePublisher publisher("/Device");
277 publisher.setValue("State", "Starting");
278 publisher.sync();
279
280 // QValueSpaceSubscriber("/Device/State").value() == QVariant("Starting")
281 \endcode
282*/
283void QValueSpacePublisher::setValue(const QString &name, const QVariant &data)
284{
285 if (!isConnected()) {
286 qWarning(msg: "setValue called on unconnected QValueSpacePublisher.");
287 return;
288 }
289
290 d_ptr->hasSet = true;
291 d_ptr->layer->setValue(creator: this, handle: d_ptr->handle, subPath: qCanonicalPath(path: name), value: data);
292}
293
294/*!
295 Removes the value \a name and all sub-attributes from the system.
296
297 For example:
298 \code
299 QValueSpacePublisher publisher("/Device");
300 publisher.setValue("State", "Starting");
301 publisher.setValue("State/Memory", "1000");
302 publisher.sync();
303 // QValueSpaceSubscriber("/Device/State").value() == QVariant("Starting")
304 // QValueSpaceSubscriber("/Device/State/Memory").value() == QVariant("1000")
305
306 publisher.resetValue("State");
307 publisher.sync();
308 // QValueSpaceSubscriber("/Device/State").value() == QVariant();
309 // QValueSpaceSubscriber("/Device/State/Memory").value() == QVariant();
310 \endcode
311*/
312void QValueSpacePublisher::resetValue(const QString &name)
313{
314 if (!isConnected()) {
315 qWarning(msg: "resetValue called on unconnected QValueSpacePublisher.");
316 return;
317 }
318
319 d_ptr->layer->removeValue(creator: this, handle: d_ptr->handle, subPath: qCanonicalPath(path: name));
320}
321
322/*!
323 \reimp
324*/
325void QValueSpacePublisher::connectNotify(const QMetaMethod &signal)
326{
327 static const QMetaMethod interestChangedSignal = QMetaMethod::fromSignal(signal: &QValueSpacePublisher::interestChanged);
328 if (!d_ptr->hasWatch && isConnected() && signal == interestChangedSignal) {
329 d_ptr->layer->addWatch(creator: this, handle: d_ptr->handle);
330 d_ptr->hasWatch = true;
331 }
332}
333
334QT_END_NAMESPACE
335

source code of qtsystems/src/publishsubscribe/qvaluespacepublisher.cpp