/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtSensors module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qmlsensor_p.h" #include #include #include QT_BEGIN_NAMESPACE class QmlSensorPrivate : public QObjectPrivate { Q_DECLARE_PUBLIC(QmlSensor) public: QList availableRanges; QList outputRanges; }; template qsizetype readonlyListCount(QQmlListProperty *p) { return static_cast *>(p->data)->count(); } template Item *readonlyListAt(QQmlListProperty *p, qsizetype idx) { return static_cast *>(p->data)->at(idx); }; template QQmlListProperty readonlyListProperty(const QObject *o, const QList *list) { // Unfortunately QQmlListProperty won't accept a const object, even on the readonly ctor. return QQmlListProperty(const_cast(o), const_cast *>(list), readonlyListCount, readonlyListAt); } /*! \qmltype Sensor \instantiates QmlSensor \inqmlmodule QtSensors \since QtSensors 5.0 \brief The Sensor element serves as a base type for sensors. The Sensor element serves as a base type for sensors. This element wraps the QSensor class. Please see the documentation for QSensor for details. This element cannot be directly created. Please use one of the sub-classes instead. */ QmlSensor::QmlSensor(QObject *parent) : QObject(*(new QmlSensorPrivate), parent) { } QmlSensor::~QmlSensor() { } /*! \qmlproperty string Sensor::identifier This property holds the backend identifier for the sensor. Please see QSensor::identifier for information about this property. */ QByteArray QmlSensor::identifier() const { return sensor()->identifier(); } void QmlSensor::setIdentifier(const QByteArray &identifier) { sensor()->setIdentifier(identifier); } /*! \qmlproperty string Sensor::type This property holds the type of the sensor. */ QByteArray QmlSensor::type() const { return sensor()->type(); } /*! \qmlproperty bool Sensor::connectedToBackend This property holds a value indicating if the sensor has connected to a backend. Please see QSensor::connectedToBackend for information about this property. */ bool QmlSensor::isConnectedToBackend() const { return sensor()->isConnectedToBackend(); } /*! \qmlproperty bool Sensor::busy This property holds a value to indicate if the sensor is busy. Please see QSensor::busy for information about this property. */ bool QmlSensor::isBusy() const { return sensor()->isBusy(); } /*! \qmlproperty bool Sensor::active This property holds a value to indicate if the sensor is active. Please see QSensor::active for information about this property. */ void QmlSensor::setActive(bool active) { if (!m_componentComplete) { m_activateOnComplete = active; return; } if (active) sensor()->start(); else sensor()->stop(); } bool QmlSensor::isActive() const { return sensor()->isActive(); } /*! \qmlproperty bool Sensor::alwaysOn This property holds a value to indicate if the sensor should remain running when the screen is off. Please see QSensor::alwaysOn for information about this property. */ bool QmlSensor::isAlwaysOn() const { return sensor()->isAlwaysOn(); } void QmlSensor::setAlwaysOn(bool alwaysOn) { sensor()->setAlwaysOn(alwaysOn); } /*! \qmlproperty bool Sensor::skipDuplicates \since QtSensors 5.1 This property indicates whether duplicate reading values should be omitted. Please see QSensor::skipDuplicates for information about this property. */ bool QmlSensor::skipDuplicates() const { return sensor()->skipDuplicates(); } void QmlSensor::setSkipDuplicates(bool skipDuplicates) { sensor()->setSkipDuplicates(skipDuplicates); } /*! \qmlproperty list Sensor::availableDataRates This property holds the data rates that the sensor supports. Please see QSensor::availableDataRates for information about this property. */ QQmlListProperty QmlSensor::availableDataRates() const { Q_D(const QmlSensor); return readonlyListProperty(this, &d->availableRanges); } /*! \qmlproperty int Sensor::dataRate This property holds the data rate that the sensor should be run at. Please see QSensor::dataRate for information about this property. */ int QmlSensor::dataRate() const { return sensor()->dataRate(); } void QmlSensor::setDataRate(int rate) { if (rate != dataRate()) { sensor()->setDataRate(rate); Q_EMIT dataRateChanged(); } } /*! \qmlproperty list Sensor::outputRanges This property holds a list of output ranges the sensor supports. Please see QSensor::outputRanges for information about this property. */ QQmlListProperty QmlSensor::outputRanges() const { Q_D(const QmlSensor); return readonlyListProperty(this, &d->outputRanges); } /*! \qmlproperty int Sensor::outputRange This property holds the output range in use by the sensor. Please see QSensor::outputRange for information about this property. */ int QmlSensor::outputRange() const { return sensor()->outputRange(); } void QmlSensor::setOutputRange(int index) { int oldRange = outputRange(); if (oldRange == index) return; sensor()->setOutputRange(index); if (sensor()->outputRange() == index) Q_EMIT outputRangeChanged(); } /*! \qmlproperty string Sensor::description This property holds a descriptive string for the sensor. */ QString QmlSensor::description() const { return sensor()->description(); } /*! \qmlproperty int Sensor::error This property holds the last error code set on the sensor. */ int QmlSensor::error() const { return sensor()->error(); } /*! \qmlproperty SensorReading Sensor::reading This property holds the reading class. Please see QSensor::reading for information about this property. \sa {QML Reading types} */ QmlSensorReading *QmlSensor::reading() const { return m_reading; } QBindable QmlSensor::bindableReading() const { return &m_reading; } /*! \qmlproperty Sensor::AxesOrientationMode Sensor::axesOrientationMode \since QtSensors 5.1 This property holds the mode that affects how the screen orientation changes reading values. Please see QSensor::axesOrientationMode for information about this property. */ QmlSensor::AxesOrientationMode QmlSensor::axesOrientationMode() const { return static_cast(sensor()->axesOrientationMode()); } void QmlSensor::setAxesOrientationMode(QmlSensor::AxesOrientationMode axesOrientationMode) { sensor()->setAxesOrientationMode(static_cast(axesOrientationMode)); } /*! \qmlproperty int Sensor::currentOrientation \since QtSensors 5.1 This property holds the current orientation that is used for rotating the reading values. Please see QSensor::currentOrientation for information about this property. */ int QmlSensor::currentOrientation() const { return sensor()->currentOrientation(); } /*! \qmlproperty int Sensor::userOrientation \since QtSensors 5.1 This property holds the angle used for rotating the reading values in the UserOrientation mode. Please see QSensor::userOrientation for information about this property. */ int QmlSensor::userOrientation() const { return sensor()->userOrientation(); } void QmlSensor::setUserOrientation(int userOrientation) { sensor()->setUserOrientation(userOrientation); } /*! \qmlproperty int Sensor::maxBufferSize \since QtSensors 5.1 This property holds the maximum buffer size. Please see QSensor::maxBufferSize for information about this property. */ int QmlSensor::maxBufferSize() const { return sensor()->maxBufferSize(); } /*! \qmlproperty int Sensor::efficientBufferSize \since QtSensors 5.1 The property holds the most efficient buffer size. Please see QSensor::efficientBufferSize for information about this property. */ int QmlSensor::efficientBufferSize() const { return sensor()->efficientBufferSize(); } /*! \qmlproperty int Sensor::bufferSize \since QtSensors 5.1 This property holds the size of the buffer. Please see QSensor::bufferSize for information about this property. */ int QmlSensor::bufferSize() const { return sensor()->bufferSize(); } void QmlSensor::setBufferSize(int bufferSize) { sensor()->setBufferSize(bufferSize); } /*! \qmlmethod bool Sensor::start() Start retrieving values from the sensor. Returns true if the sensor was started, false otherwise. Please see QSensor::start() for information. */ bool QmlSensor::start() { return sensor()->start(); } /*! \qmlmethod bool Sensor::stop() Stop retrieving values from the sensor. Returns true if the sensor was stopped, false otherwise. Please see QSensor::stop() for information. */ void QmlSensor::stop() { setActive(false); } void QmlSensor::classBegin() { } void QmlSensor::componentComplete() { m_componentComplete = true; connect(sensor(), SIGNAL(sensorError(int)), this, SIGNAL(errorChanged())); connect(sensor(), SIGNAL(activeChanged()), this, SIGNAL(activeChanged())); connect(sensor(), SIGNAL(alwaysOnChanged()), this, SIGNAL(alwaysOnChanged())); connect(sensor(), SIGNAL(skipDuplicatesChanged(bool)), this, SIGNAL(skipDuplicatesChanged(bool))); connect(sensor(), SIGNAL(axesOrientationModeChanged(AxesOrientationMode)), this, SIGNAL(axesOrientationModeChanged(AxesOrientationMode))); connect(sensor(), SIGNAL(userOrientationChanged(int)), this, SIGNAL(userOrientationChanged(int))); connect(sensor(), SIGNAL(currentOrientationChanged(int)), this, SIGNAL(currentOrientationChanged(int))); connect(sensor(), SIGNAL(bufferSizeChanged(int)), this, SIGNAL(bufferSizeChanged(int))); connect(sensor(), SIGNAL(maxBufferSizeChanged(int)), this, SIGNAL(maxBufferSizeChanged(int))); connect(sensor(), SIGNAL(efficientBufferSizeChanged(int)), this, SIGNAL(efficientBufferSizeChanged(int))); connect(sensor(), &QSensor::busyChanged, this, &QmlSensor::busyChanged); connect(sensor(), &QSensor::identifierChanged, this, &QmlSensor::identifierChanged); // These can change! int oldDataRate = dataRate(); int oldOutputRange = outputRange(); if (sensor()->connectToBackend()) Q_EMIT connectedToBackendChanged(); m_reading.setValueBypassingBindings(createReading()); m_reading->setParent(this); if (oldDataRate != dataRate()) Q_EMIT dataRateChanged(); if (oldOutputRange != outputRange()) Q_EMIT outputRangeChanged(); Q_D(QmlSensor); const auto available = sensor()->availableDataRates(); d->availableRanges.reserve(available.size()); for (const qrange &r : available) { auto *range = new QmlSensorRange(this); range->setMinumum(r.first); range->setMaximum(r.second); d->availableRanges.append(range); } const auto output = sensor()->outputRanges(); d->outputRanges.reserve(output.size()); for (const qoutputrange &r : output) { auto *range = new QmlSensorOutputRange(this); range->setMinimum(r.minimum); range->setMaximum(r.maximum); range->setAccuracy(r.accuracy); d->outputRanges.append(range); } // meta-data should become non-empty if (!description().isEmpty()) Q_EMIT descriptionChanged(); if (available.count()) Q_EMIT availableDataRatesChanged(); if (output.count()) Q_EMIT outputRangesChanged(); connect(sensor(), SIGNAL(readingChanged()), this, SLOT(updateReading())); if (m_activateOnComplete) start(); } void QmlSensor::updateReading() { if (m_reading) { m_reading->update(); m_reading.notify(); Q_EMIT readingChanged(); } } /*! \qmltype SensorReading \instantiates QmlSensorReading \inqmlmodule QtSensors \since QtSensors 5.0 \brief The SensorReading element serves as a base type for sensor readings. The SensorReading element serves as a base type for sensor readings. This element wraps the QSensorReading class. Please see the documentation for QSensorReading for details. This element cannot be directly created. */ /*! \qmlproperty quint64 SensorReading::timestamp A timestamp for the reading. Please see QSensorReading::timestamp for information about this property. */ quint64 QmlSensorReading::timestamp() const { return m_timestamp; } QBindable QmlSensorReading::bindableTimestamp() const { return &m_timestamp; } void QmlSensorReading::update() { m_timestamp = reading()->timestamp(); readingUpdate(); } QT_END_NAMESPACE