1 | // Copyright (C) 2016 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #include "qmlsensor_p.h" |
5 | #include <QtSensors/QSensor> |
6 | #include <QDebug> |
7 | #include <QtCore/private/qobject_p.h> |
8 | |
9 | QT_BEGIN_NAMESPACE |
10 | |
11 | class QmlSensorPrivate : public QObjectPrivate |
12 | { |
13 | Q_DECLARE_PUBLIC(QmlSensor) |
14 | public: |
15 | |
16 | QList<QmlSensorRange *> availableRanges; |
17 | QList<QmlSensorOutputRange *> outputRanges; |
18 | }; |
19 | |
20 | template<typename Item> |
21 | qsizetype readonlyListCount(QQmlListProperty<Item> *p) |
22 | { |
23 | return static_cast<const QList<Item *> *>(p->data)->size(); |
24 | } |
25 | |
26 | template<typename Item> |
27 | Item *readonlyListAt(QQmlListProperty<Item> *p, qsizetype idx) |
28 | { |
29 | return static_cast<const QList<Item *> *>(p->data)->at(idx); |
30 | }; |
31 | |
32 | template<typename Item> |
33 | QQmlListProperty<Item> readonlyListProperty(const QObject *o, const QList<Item *> *list) |
34 | { |
35 | // Unfortunately QQmlListProperty won't accept a const object, even on the readonly ctor. |
36 | return QQmlListProperty<Item>(const_cast<QObject *>(o), const_cast<QList<Item *> *>(list), |
37 | readonlyListCount<Item>, readonlyListAt<Item>); |
38 | } |
39 | |
40 | /*! |
41 | \qmltype Sensor |
42 | //! \instantiates QmlSensor |
43 | \inqmlmodule QtSensors |
44 | \since QtSensors 5.0 |
45 | \brief The Sensor element serves as a base type for sensors. |
46 | |
47 | The Sensor element serves as a base type for sensors. |
48 | |
49 | This element wraps the QSensor class. Please see the documentation for |
50 | QSensor for details. |
51 | |
52 | This element cannot be directly created. Please use one of the sub-classes instead. |
53 | */ |
54 | |
55 | QmlSensor::QmlSensor(QObject *parent) |
56 | : QObject(*(new QmlSensorPrivate), parent) |
57 | { |
58 | } |
59 | |
60 | QmlSensor::~QmlSensor() |
61 | { |
62 | } |
63 | |
64 | /*! |
65 | \qmlproperty string Sensor::identifier |
66 | This property holds the backend identifier for the sensor. |
67 | |
68 | Please see QSensor::identifier for information about this property. |
69 | */ |
70 | |
71 | QByteArray QmlSensor::identifier() const |
72 | { |
73 | return sensor()->identifier(); |
74 | } |
75 | |
76 | void QmlSensor::setIdentifier(const QByteArray &identifier) |
77 | { |
78 | sensor()->setIdentifier(identifier); |
79 | } |
80 | |
81 | /*! |
82 | \qmlproperty string Sensor::type |
83 | This property holds the type of the sensor. |
84 | */ |
85 | |
86 | QByteArray QmlSensor::type() const |
87 | { |
88 | return sensor()->type(); |
89 | } |
90 | |
91 | /*! |
92 | \qmlproperty bool Sensor::connectedToBackend |
93 | This property holds a value indicating if the sensor has connected to a backend. |
94 | |
95 | Please see QSensor::connectedToBackend for information about this property. |
96 | */ |
97 | |
98 | bool QmlSensor::isConnectedToBackend() const |
99 | { |
100 | return sensor()->isConnectedToBackend(); |
101 | } |
102 | |
103 | /*! |
104 | \qmlproperty bool Sensor::busy |
105 | This property holds a value to indicate if the sensor is busy. |
106 | |
107 | Please see QSensor::busy for information about this property. |
108 | */ |
109 | |
110 | bool QmlSensor::isBusy() const |
111 | { |
112 | return sensor()->isBusy(); |
113 | } |
114 | |
115 | /*! |
116 | \qmlproperty bool Sensor::active |
117 | This property holds a value to indicate if the sensor is active. |
118 | |
119 | Please see QSensor::active for information about this property. |
120 | */ |
121 | |
122 | void QmlSensor::setActive(bool active) |
123 | { |
124 | if (!m_componentComplete) { |
125 | m_activateOnComplete = active; |
126 | return; |
127 | } |
128 | if (active) |
129 | sensor()->start(); |
130 | else |
131 | sensor()->stop(); |
132 | } |
133 | |
134 | bool QmlSensor::isActive() const |
135 | { |
136 | return sensor()->isActive(); |
137 | } |
138 | |
139 | /*! |
140 | \qmlproperty bool Sensor::alwaysOn |
141 | This property holds a value to indicate if the sensor should remain running when the screen is off. |
142 | |
143 | Please see QSensor::alwaysOn for information about this property. |
144 | */ |
145 | |
146 | bool QmlSensor::isAlwaysOn() const |
147 | { |
148 | return sensor()->isAlwaysOn(); |
149 | } |
150 | |
151 | void QmlSensor::setAlwaysOn(bool alwaysOn) |
152 | { |
153 | sensor()->setAlwaysOn(alwaysOn); |
154 | } |
155 | |
156 | /*! |
157 | \qmlproperty bool Sensor::skipDuplicates |
158 | \since QtSensors 5.1 |
159 | |
160 | This property indicates whether duplicate reading values should be omitted. |
161 | |
162 | Please see QSensor::skipDuplicates for information about this property. |
163 | */ |
164 | |
165 | bool QmlSensor::skipDuplicates() const |
166 | { |
167 | return sensor()->skipDuplicates(); |
168 | } |
169 | |
170 | void QmlSensor::setSkipDuplicates(bool skipDuplicates) |
171 | { |
172 | sensor()->setSkipDuplicates(skipDuplicates); |
173 | } |
174 | |
175 | /*! |
176 | \qmlproperty list<Range> Sensor::availableDataRates |
177 | This property holds the data rates that the sensor supports. |
178 | |
179 | Please see QSensor::availableDataRates for information about this property. |
180 | */ |
181 | QQmlListProperty<QmlSensorRange> QmlSensor::availableDataRates() const |
182 | { |
183 | Q_D(const QmlSensor); |
184 | return readonlyListProperty<QmlSensorRange>(o: this, list: &d->availableRanges); |
185 | } |
186 | |
187 | /*! |
188 | \qmlproperty int Sensor::dataRate |
189 | This property holds the data rate that the sensor should be run at. |
190 | |
191 | Please see QSensor::dataRate for information about this property. |
192 | */ |
193 | |
194 | int QmlSensor::dataRate() const |
195 | { |
196 | return sensor()->dataRate(); |
197 | } |
198 | |
199 | void QmlSensor::setDataRate(int rate) |
200 | { |
201 | if (rate != dataRate()) { |
202 | sensor()->setDataRate(rate); |
203 | Q_EMIT dataRateChanged(); |
204 | } |
205 | } |
206 | |
207 | /*! |
208 | \qmlproperty list<OutputRange> Sensor::outputRanges |
209 | This property holds a list of output ranges the sensor supports. |
210 | |
211 | Please see QSensor::outputRanges for information about this property. |
212 | */ |
213 | |
214 | QQmlListProperty<QmlSensorOutputRange> QmlSensor::outputRanges() const |
215 | { |
216 | Q_D(const QmlSensor); |
217 | return readonlyListProperty<QmlSensorOutputRange>(o: this, list: &d->outputRanges); |
218 | } |
219 | |
220 | /*! |
221 | \qmlproperty int Sensor::outputRange |
222 | This property holds the output range in use by the sensor. |
223 | |
224 | Please see QSensor::outputRange for information about this property. |
225 | */ |
226 | |
227 | int QmlSensor::outputRange() const |
228 | { |
229 | return sensor()->outputRange(); |
230 | } |
231 | |
232 | void QmlSensor::setOutputRange(int index) |
233 | { |
234 | int oldRange = outputRange(); |
235 | if (oldRange == index) return; |
236 | sensor()->setOutputRange(index); |
237 | if (sensor()->outputRange() == index) |
238 | Q_EMIT outputRangeChanged(); |
239 | } |
240 | |
241 | /*! |
242 | \qmlproperty string Sensor::description |
243 | This property holds a descriptive string for the sensor. |
244 | */ |
245 | |
246 | QString QmlSensor::description() const |
247 | { |
248 | return sensor()->description(); |
249 | } |
250 | |
251 | /*! |
252 | \qmlproperty int Sensor::error |
253 | This property holds the last error code set on the sensor. |
254 | */ |
255 | |
256 | int QmlSensor::error() const |
257 | { |
258 | return sensor()->error(); |
259 | } |
260 | |
261 | /*! |
262 | \qmlproperty SensorReading Sensor::reading |
263 | This property holds the reading class. |
264 | |
265 | Please see QSensor::reading for information about this property. |
266 | \sa {QML Reading types} |
267 | */ |
268 | |
269 | QmlSensorReading *QmlSensor::reading() const |
270 | { |
271 | return m_reading; |
272 | } |
273 | |
274 | QBindable<QmlSensorReading*> QmlSensor::bindableReading() const |
275 | { |
276 | return &m_reading; |
277 | } |
278 | |
279 | /*! |
280 | \qmlproperty Sensor::AxesOrientationMode Sensor::axesOrientationMode |
281 | \since QtSensors 5.1 |
282 | This property holds the mode that affects how the screen orientation changes reading values. |
283 | |
284 | Please see QSensor::axesOrientationMode for information about this property. |
285 | */ |
286 | |
287 | QmlSensor::AxesOrientationMode QmlSensor::axesOrientationMode() const |
288 | { |
289 | return static_cast<QmlSensor::AxesOrientationMode>(sensor()->axesOrientationMode()); |
290 | } |
291 | |
292 | void QmlSensor::setAxesOrientationMode(QmlSensor::AxesOrientationMode axesOrientationMode) |
293 | { |
294 | sensor()->setAxesOrientationMode(static_cast<QSensor::AxesOrientationMode>(axesOrientationMode)); |
295 | } |
296 | |
297 | /*! |
298 | \qmlproperty int Sensor::currentOrientation |
299 | \since QtSensors 5.1 |
300 | This property holds the current orientation that is used for rotating the reading values. |
301 | |
302 | Please see QSensor::currentOrientation for information about this property. |
303 | */ |
304 | |
305 | int QmlSensor::currentOrientation() const |
306 | { |
307 | return sensor()->currentOrientation(); |
308 | } |
309 | |
310 | /*! |
311 | \qmlproperty int Sensor::userOrientation |
312 | \since QtSensors 5.1 |
313 | This property holds the angle used for rotating the reading values in the UserOrientation mode. |
314 | |
315 | Please see QSensor::userOrientation for information about this property. |
316 | */ |
317 | |
318 | int QmlSensor::userOrientation() const |
319 | { |
320 | return sensor()->userOrientation(); |
321 | } |
322 | |
323 | void QmlSensor::setUserOrientation(int userOrientation) |
324 | { |
325 | sensor()->setUserOrientation(userOrientation); |
326 | } |
327 | |
328 | /*! |
329 | \qmlproperty int Sensor::maxBufferSize |
330 | \since QtSensors 5.1 |
331 | This property holds the maximum buffer size. |
332 | |
333 | Please see QSensor::maxBufferSize for information about this property. |
334 | */ |
335 | |
336 | int QmlSensor::maxBufferSize() const |
337 | { |
338 | return sensor()->maxBufferSize(); |
339 | } |
340 | |
341 | /*! |
342 | \qmlproperty int Sensor::efficientBufferSize |
343 | \since QtSensors 5.1 |
344 | The property holds the most efficient buffer size. |
345 | |
346 | Please see QSensor::efficientBufferSize for information about this property. |
347 | */ |
348 | |
349 | int QmlSensor::efficientBufferSize() const |
350 | { |
351 | return sensor()->efficientBufferSize(); |
352 | } |
353 | |
354 | /*! |
355 | \qmlproperty int Sensor::bufferSize |
356 | \since QtSensors 5.1 |
357 | This property holds the size of the buffer. |
358 | |
359 | Please see QSensor::bufferSize for information about this property. |
360 | */ |
361 | |
362 | int QmlSensor::bufferSize() const |
363 | { |
364 | return sensor()->bufferSize(); |
365 | } |
366 | |
367 | void QmlSensor::setBufferSize(int bufferSize) |
368 | { |
369 | sensor()->setBufferSize(bufferSize); |
370 | } |
371 | |
372 | /*! |
373 | \qmlmethod bool Sensor::start() |
374 | Start retrieving values from the sensor. Returns true if the sensor |
375 | was started, false otherwise. |
376 | |
377 | Please see QSensor::start() for information. |
378 | */ |
379 | |
380 | bool QmlSensor::start() |
381 | { |
382 | return sensor()->start(); |
383 | } |
384 | |
385 | /*! |
386 | \qmlmethod bool Sensor::stop() |
387 | Stop retrieving values from the sensor. |
388 | Returns true if the sensor was stopped, false otherwise. |
389 | |
390 | Please see QSensor::stop() for information. |
391 | */ |
392 | |
393 | void QmlSensor::stop() |
394 | { |
395 | setActive(false); |
396 | } |
397 | |
398 | void QmlSensor::classBegin() |
399 | { |
400 | } |
401 | |
402 | void QmlSensor::componentComplete() |
403 | { |
404 | m_componentComplete = true; |
405 | |
406 | connect(sender: sensor(), SIGNAL(sensorError(int)), receiver: this, SIGNAL(errorChanged())); |
407 | connect(sender: sensor(), SIGNAL(activeChanged()), receiver: this, SIGNAL(activeChanged())); |
408 | connect(sender: sensor(), SIGNAL(alwaysOnChanged()), receiver: this, SIGNAL(alwaysOnChanged())); |
409 | connect(sender: sensor(), SIGNAL(skipDuplicatesChanged(bool)), receiver: this, SIGNAL(skipDuplicatesChanged(bool))); |
410 | connect(sender: sensor(), SIGNAL(axesOrientationModeChanged(AxesOrientationMode)), |
411 | receiver: this, SIGNAL(axesOrientationModeChanged(AxesOrientationMode))); |
412 | connect(sender: sensor(), SIGNAL(userOrientationChanged(int)), receiver: this, SIGNAL(userOrientationChanged(int))); |
413 | connect(sender: sensor(), SIGNAL(currentOrientationChanged(int)), receiver: this, SIGNAL(currentOrientationChanged(int))); |
414 | connect(sender: sensor(), SIGNAL(bufferSizeChanged(int)), receiver: this, SIGNAL(bufferSizeChanged(int))); |
415 | connect(sender: sensor(), SIGNAL(maxBufferSizeChanged(int)), receiver: this, SIGNAL(maxBufferSizeChanged(int))); |
416 | connect(sender: sensor(), SIGNAL(efficientBufferSizeChanged(int)), receiver: this, SIGNAL(efficientBufferSizeChanged(int))); |
417 | connect(sender: sensor(), signal: &QSensor::busyChanged, context: this, slot: &QmlSensor::busyChanged); |
418 | connect(sender: sensor(), signal: &QSensor::identifierChanged, context: this, slot: &QmlSensor::identifierChanged); |
419 | |
420 | // These can change! |
421 | int oldDataRate = dataRate(); |
422 | int oldOutputRange = outputRange(); |
423 | |
424 | if (sensor()->connectToBackend()) |
425 | Q_EMIT connectedToBackendChanged(); |
426 | |
427 | m_reading.setValueBypassingBindings(createReading()); |
428 | m_reading->setParent(this); |
429 | if (oldDataRate != dataRate()) |
430 | Q_EMIT dataRateChanged(); |
431 | if (oldOutputRange != outputRange()) |
432 | Q_EMIT outputRangeChanged(); |
433 | |
434 | Q_D(QmlSensor); |
435 | const auto available = sensor()->availableDataRates(); |
436 | d->availableRanges.reserve(asize: available.size()); |
437 | for (const qrange &r : available) { |
438 | auto *range = new QmlSensorRange(this); |
439 | range->setMinumum(r.first); |
440 | range->setMaximum(r.second); |
441 | d->availableRanges.append(t: range); |
442 | } |
443 | const auto output = sensor()->outputRanges(); |
444 | d->outputRanges.reserve(asize: output.size()); |
445 | for (const qoutputrange &r : output) { |
446 | auto *range = new QmlSensorOutputRange(this); |
447 | range->setMinimum(r.minimum); |
448 | range->setMaximum(r.maximum); |
449 | range->setAccuracy(r.accuracy); |
450 | d->outputRanges.append(t: range); |
451 | } |
452 | |
453 | // meta-data should become non-empty |
454 | if (!description().isEmpty()) |
455 | Q_EMIT descriptionChanged(); |
456 | if (available.size()) |
457 | Q_EMIT availableDataRatesChanged(); |
458 | if (output.size()) |
459 | Q_EMIT outputRangesChanged(); |
460 | |
461 | connect(sender: sensor(), SIGNAL(readingChanged()), receiver: this, SLOT(updateReading())); |
462 | if (m_activateOnComplete) |
463 | start(); |
464 | } |
465 | |
466 | void QmlSensor::updateReading() |
467 | { |
468 | if (m_reading) { |
469 | m_reading->update(); |
470 | m_reading.notify(); |
471 | Q_EMIT readingChanged(); |
472 | } |
473 | } |
474 | |
475 | /*! |
476 | \qmltype SensorReading |
477 | //! \instantiates QmlSensorReading |
478 | \inqmlmodule QtSensors |
479 | \since QtSensors 5.0 |
480 | \brief The SensorReading element serves as a base type for sensor readings. |
481 | |
482 | The SensorReading element serves as a base type for sensor readings. |
483 | |
484 | This element wraps the QSensorReading class. Please see the documentation for |
485 | QSensorReading for details. |
486 | |
487 | This element cannot be directly created. |
488 | */ |
489 | |
490 | /*! |
491 | \qmlproperty quint64 SensorReading::timestamp |
492 | A timestamp for the reading. |
493 | |
494 | Please see QSensorReading::timestamp for information about this property. |
495 | */ |
496 | |
497 | quint64 QmlSensorReading::timestamp() const |
498 | { |
499 | return m_timestamp; |
500 | } |
501 | |
502 | QBindable<quint64> QmlSensorReading::bindableTimestamp() const |
503 | { |
504 | return &m_timestamp; |
505 | } |
506 | |
507 | |
508 | void QmlSensorReading::update() |
509 | { |
510 | m_timestamp = reading()->timestamp(); |
511 | readingUpdate(); |
512 | } |
513 | |
514 | QT_END_NAMESPACE |
515 | |