1/****************************************************************************
2**
3** Copyright (C) 2017 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtSensors module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:BSD$
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 https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** BSD License Usage
18** Alternatively, you may use this file under the terms of the BSD license
19** as follows:
20**
21** "Redistribution and use in source and binary forms, with or without
22** modification, are permitted provided that the following conditions are
23** met:
24** * Redistributions of source code must retain the above copyright
25** notice, this list of conditions and the following disclaimer.
26** * Redistributions in binary form must reproduce the above copyright
27** notice, this list of conditions and the following disclaimer in
28** the documentation and/or other materials provided with the
29** distribution.
30** * Neither the name of The Qt Company Ltd nor the names of its
31** contributors may be used to endorse or promote products derived
32** from this software without specific prior written permission.
33**
34**
35** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
38** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
39** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
45** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
46**
47** $QT_END_LICENSE$
48**
49****************************************************************************/
50
51#include "sensoritem.h"
52#include <QtCore/QDebug>
53#include <QtSensors>
54
55QT_BEGIN_NAMESPACE
56
57/*
58 \class QSensorItem
59 \brief The QSensorItem type provides information about the metadata from a sensors installed on the system.
60*/
61
62/*
63 Construct a QSensorItem object with parent \a parent
64*/
65QSensorItem::QSensorItem(QObject* parent)
66 : QObject(parent)
67 , _qsensor(0)
68{
69}
70
71/*
72 Construct a QSensorItem object with QSensor \a sensor and parent \a parent
73*/
74QSensorItem::QSensorItem(QSensor* sensor, QObject* parent)
75 : QObject(parent)
76 , _qsensor(sensor)
77{
78}
79
80/*
81 Destructor of a QSensorItem
82*/
83QSensorItem::~QSensorItem()
84{
85}
86
87/*
88 \fn QSensorItem::startChanged()
89 Notifies the client if the sensors has changed its start active status
90*/
91
92/*
93 \property QSensorItem::start
94 This property starts or stops the sensor
95*/
96bool QSensorItem::start()
97{
98 return (_qsensor ? _qsensor->isActive() : false);
99}
100
101void QSensorItem::setStart(bool run)
102{
103 if (_qsensor)
104 _qsensor->setActive(run);
105}
106
107/*
108 \property QSensorItem::id
109 Returns the sensor id of the sensor item
110*/
111QString QSensorItem::id()
112{
113 return (_qsensor ? _qsensor->identifier() : "");
114}
115
116/*
117 Set the new value \a val to the QPropertyInfo object \a property
118*/
119void QSensorItem::changePropertyValue(QPropertyInfo* property, const QString& val)
120{
121 if (_qsensor && _sensorProperties.contains(t: property)){
122 if ( _qsensor->setProperty(name: property->name().toLatin1().constData(), value: QVariant(val)))
123 updateSensorPropertyValues();
124 else
125 qWarning() << "new property value couldn't be set";
126 }
127}
128
129/*
130 Reading the metadata and activates the sensor.
131*/
132void QSensorItem::select()
133{
134 if (_sensorProperties.isEmpty()) {
135 // Probe the reading using Qt's meta-object facilities
136 //Read properties from reader
137 QSensorReading *reading = _qsensor->reading();
138 const QMetaObject *mo = reading->metaObject();
139 int firstProperty = QSensorReading::staticMetaObject.propertyOffset();
140
141 for (int i = firstProperty; i < mo->propertyCount(); ++i) {
142 QString typeName = QLatin1String(mo->property(index: i).typeName());
143 int crap = typeName.lastIndexOf(s: "::");
144 if (crap != -1)
145 typeName = typeName.mid(position: crap + 2);
146
147 QPropertyInfo* pi = new QPropertyInfo(mo->property(index: i).name()
148 , i
149 , isWriteable(propertyname: mo->property(index: i).name())
150 , typeName
151 , "-"
152 , this);
153 _readerProperties.append(t: pi);
154 }
155
156 //Read properties from sensor
157 const QMetaObject *mo1 = _qsensor->metaObject();
158 firstProperty = QSensorReading::staticMetaObject.propertyOffset();
159
160 for (int i = firstProperty; i < mo1->propertyCount(); ++i) {
161 QString propertyname = mo1->property(index: i).name();
162 if (ignoreProperty(propertyname))
163 continue;
164
165 QString typeName = QLatin1String(mo1->property(index: i).typeName());
166 int crap = typeName.lastIndexOf(s: "::");
167 if (crap != -1)
168 typeName = typeName.mid(position: crap + 2);
169
170 QPropertyInfo* pi = new QPropertyInfo(propertyname
171 , i
172 , isWriteable(propertyname)
173 , typeName
174 , "-"
175 , this);
176 _sensorProperties.append(t: pi);
177 }
178 updateSensorPropertyValues();
179 connect(sender: _qsensor, SIGNAL(readingChanged()), receiver: this, SLOT(sensorReadingChanged()));
180 }
181 connect(asender: _qsensor, SIGNAL(activeChanged()), SIGNAL(startChanged()));
182}
183
184/*
185 Unselect the sensor by stopping the sensor.
186*/
187void QSensorItem::unSelect()
188{
189 _qsensor->stop();
190 disconnect(sender: _qsensor, SIGNAL(activeChanged()), receiver: this , SIGNAL(startChanged()));
191}
192
193/*
194 Updates the property values from QSensor
195*/
196void QSensorItem::updateSensorPropertyValues()
197{
198 if (_qsensor){
199 const QMetaObject *mo = _qsensor->metaObject();
200 for (int i = 0; i < _sensorProperties.count(); i++){
201 QVariant val = mo->property(index: _sensorProperties[i]->index()).read(obj: _qsensor);
202 _sensorProperties[i]->setValue(convertValue(type: _sensorProperties[i]->typeName(), val));
203 }
204 }
205}
206
207/*
208 \fn QSensorItem::propertiesChanged()
209 Notifies the client if the list of the properties was changed
210*/
211
212/*
213 Updates the property values from the QSensorReader
214*/
215void QSensorItem::sensorReadingChanged()
216{
217 QSensorReading *reading = _qsensor->reading();
218 const QMetaObject *mo = reading->metaObject();
219 for (int i = 0; i < _readerProperties.count(); i++){
220 QVariant val = mo->property(index: _readerProperties[i]->index()).read(obj: reading);
221 _readerProperties[i]->setValue(convertValue(type: _readerProperties[i]->typeName(), val));
222 }
223}
224
225/*
226 Returns true if the property with the name \a propertyname should be ignored
227*/
228bool QSensorItem::ignoreProperty(const QString& propertyname)
229{
230 if (propertyname == "reading" ||
231 propertyname == "active" ||
232 propertyname == "identifier" ||
233 propertyname == "connectedToBackend" ||
234 propertyname == "busy")
235 return true;
236
237 return false;
238}
239
240/*
241 Returns true if the property with the name \a propertyname is writeable
242*/
243bool QSensorItem::isWriteable(const QString& propertyname)
244{
245 if (_qsensor){
246 const QMetaObject *mo = _qsensor->metaObject();
247 int propertyindex = mo->indexOfProperty(name: propertyname.toLocal8Bit().constData());
248 if (propertyindex >= 0){
249 QMetaProperty prop = mo->property(index: propertyindex);
250 return prop.isWritable();
251 }
252 else {
253 QSensorReading *reading = _qsensor->reading();
254 const QMetaObject *moreader = reading->metaObject();
255 propertyindex = moreader->indexOfProperty(name: propertyname.toLocal8Bit().constData());
256 if (propertyindex >= 0){
257 QMetaProperty prop = mo->property(index: propertyindex);
258 return prop.isWritable();
259 }
260 }
261 }
262
263 return false;
264}
265
266/*
267 Convert the variant \a val dependent on the type \a type and returns the converted value as a QString
268*/
269QString QSensorItem::convertValue(const QString& type, const QVariant& val)
270{
271 if (type == "LightLevel"){
272 switch (val.toInt()) {
273 case 1: return "Dark";
274 case 2: return "Twilight";
275 case 3: return "Light";
276 case 4: return "Bright";
277 case 5: return "Sunny";
278 default: return "Undefined";
279 }
280 }
281 else if (type == "Orientation"){
282 switch (val.toInt()) {
283 case 1: return "TopUp";
284 case 2: return "TopDown";
285 case 3: return "LeftUp";
286 case 4: return "RightUp";
287 case 5: return "FaceUp";
288 case 6: return "FaceDown";
289 default: return "Undefined";
290 }
291 }
292 else if (type == "qrangelist"){
293 qrangelist rangelist = val.value<qrangelist>();
294 QStringList ranges;
295 foreach (const qrange &r, rangelist) {
296 if (r.first == r.second)
297 ranges << QString("%1 Hz").arg(a: r.first);
298 else
299 ranges << QString("%1-%2 Hz").arg(a: r.first).arg(a: r.second);
300 }
301 if (ranges.count() > 0)
302 return ranges.join(sep: ", ");
303 return "-";
304 }
305 else if (type == "qoutputrangelist") {
306 qoutputrangelist rangelist = val.value<qoutputrangelist>();
307 QStringList ranges;
308 foreach (const qoutputrange &r, rangelist) {
309 ranges << QString("(%1, %2) += %3").arg(a: r.minimum).arg(a: r.maximum).arg(a: r.accuracy);
310 }
311 if (ranges.count() > 0)
312 return ranges.join(sep: ", ");
313 return "-";
314 }
315
316 return val.toString();
317}
318
319/*
320 \property QSensorItem::properties
321 Returns a list of all properties from the sensor
322*/
323QQmlListProperty<QPropertyInfo> QSensorItem::properties()
324{
325 _properties.clear();
326 _properties.append(t: _sensorProperties);
327 _properties.append(t: _readerProperties);
328 return QQmlListProperty<QPropertyInfo> (this, &_properties);
329}
330
331QT_END_NAMESPACE
332

source code of qtsensors/examples/sensors/sensor_explorer/import/sensoritem.cpp