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 | |
55 | QT_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 | */ |
65 | QSensorItem::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 | */ |
74 | QSensorItem::QSensorItem(QSensor* sensor, QObject* parent) |
75 | : QObject(parent) |
76 | , _qsensor(sensor) |
77 | { |
78 | } |
79 | |
80 | /* |
81 | Destructor of a QSensorItem |
82 | */ |
83 | QSensorItem::~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 | */ |
96 | bool QSensorItem::start() |
97 | { |
98 | return (_qsensor ? _qsensor->isActive() : false); |
99 | } |
100 | |
101 | void 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 | */ |
111 | QString 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 | */ |
119 | void 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 | */ |
132 | void 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 | */ |
187 | void 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 | */ |
196 | void 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 | */ |
215 | void 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 | */ |
228 | bool 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 | */ |
243 | bool 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 | */ |
269 | QString 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 | */ |
323 | QQmlListProperty<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 | |
331 | QT_END_NAMESPACE |
332 | |