diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2019-12-02 15:00:16 +0100 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2019-12-03 10:39:32 +0100 |
commit | f6b550ea5eae80124576766fe1a9609ae5aba1e3 (patch) | |
tree | aa77775c9fd891cda2dda4ca26a87be20a4b6225 /src | |
parent | 7aef9656318bb5f827be997a526e9effcfb62502 (diff) | |
download | qtsensors-f6b550ea5eae80124576766fe1a9609ae5aba1e3.tar.gz |
Fix QML API for sensor ranges
Previously the QQmlListProperties were constructed on stack-allocated
lists, which immediately turned into dangling pointers on return. Also,
none of the sensor ranges was ever deleted.
Keep the sensor ranges in persistent lists in the private object, parent
them to the main QmlSensor object, and add some tests for them.
Fixes: QTBUG-79224
Change-Id: Ie61d0aaeaaaf998c1d1f46f60c81848ae48659d6
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Alex Blasche <alexander.blasche@qt.io>
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/imports/sensors/qmlsensor.cpp | 81 | ||||
-rw-r--r-- | src/imports/sensors/qmlsensor.h | 3 | ||||
-rw-r--r-- | src/imports/sensors/sensors.pro | 2 |
3 files changed, 60 insertions, 26 deletions
diff --git a/src/imports/sensors/qmlsensor.cpp b/src/imports/sensors/qmlsensor.cpp index 0389af4..752cdb1 100644 --- a/src/imports/sensors/qmlsensor.cpp +++ b/src/imports/sensors/qmlsensor.cpp @@ -40,9 +40,39 @@ #include "qmlsensor.h" #include <QtSensors/QSensor> #include <QDebug> +#include <QtCore/private/qobject_p.h> QT_BEGIN_NAMESPACE +class QmlSensorPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QmlSensor) +public: + + QList<QmlSensorRange *> availableRanges; + QList<QmlSensorOutputRange *> outputRanges; +}; + +template<typename Item> +int readonlyListCount(QQmlListProperty<Item> *p) +{ + return static_cast<const QList<Item *> *>(p->data)->count(); +} + +template<typename Item> +Item *readonlyListAt(QQmlListProperty<Item> *p, int idx) +{ + return static_cast<const QList<Item *> *>(p->data)->at(idx); +}; + +template<typename Item> +QQmlListProperty<Item> readonlyListProperty(const QObject *o, const QList<Item *> *list) +{ + // Unfortunately QQmlListProperty won't accept a const object, even on the readonly ctor. + return QQmlListProperty<Item>(const_cast<QObject *>(o), const_cast<QList<Item *> *>(list), + readonlyListCount<Item>, readonlyListAt<Item>); +} + /*! \qmltype Sensor \instantiates QmlSensor @@ -59,7 +89,7 @@ QT_BEGIN_NAMESPACE */ QmlSensor::QmlSensor(QObject *parent) - : QObject(parent) + : QObject(*(new QmlSensorPrivate), parent) , m_parsed(false) , m_active(false) , m_reading(0) @@ -193,19 +223,10 @@ void QmlSensor::setSkipDuplicates(bool skipDuplicates) Please see QSensor::availableDataRates for information about this property. */ - QQmlListProperty<QmlSensorRange> QmlSensor::availableDataRates() const { - QList<QmlSensorRange*> ret; - ret.reserve(sensor()->availableDataRates().size()); - foreach (const qrange &r, sensor()->availableDataRates()) { - QmlSensorRange *range = new QmlSensorRange; - //QQmlEngine::setObjectOwnership(range, QQmlEngine::JavaScriptOwnership); - range->setMinumum(r.first); - range->setMaximum(r.second); - ret << range; - } - return QQmlListProperty<QmlSensorRange>(const_cast<QmlSensor*>(this), ret); + Q_D(const QmlSensor); + return readonlyListProperty<QmlSensorRange>(this, &d->availableRanges); } /*! @@ -237,17 +258,8 @@ void QmlSensor::setDataRate(int rate) QQmlListProperty<QmlSensorOutputRange> QmlSensor::outputRanges() const { - QList<QmlSensorOutputRange*> ret; - ret.reserve(sensor()->outputRanges().size()); - foreach (const qoutputrange &r, sensor()->outputRanges()) { - QmlSensorOutputRange *range = new QmlSensorOutputRange; - //QQmlEngine::setObjectOwnership(range, QQmlEngine::JavaScriptOwnership); - range->setMinimum(r.minimum); - range->setMaximum(r.maximum); - range->setAccuracy(r.accuracy); - ret << range; - } - return QQmlListProperty<QmlSensorOutputRange>(const_cast<QmlSensor*>(this), ret); + Q_D(const QmlSensor); + return readonlyListProperty<QmlSensorOutputRange>(this, &d->outputRanges); } /*! @@ -468,12 +480,31 @@ void QmlSensor::componentComplete() 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 (sensor()->availableDataRates().count()) + if (available.count()) Q_EMIT availableDataRatesChanged(); - if (sensor()->outputRanges().count()) + if (output.count()) Q_EMIT outputRangesChanged(); _update(); diff --git a/src/imports/sensors/qmlsensor.h b/src/imports/sensors/qmlsensor.h index e46278b..3ac8269 100644 --- a/src/imports/sensors/qmlsensor.h +++ b/src/imports/sensors/qmlsensor.h @@ -40,6 +40,7 @@ #ifndef QMLSENSOR_H #define QMLSENSOR_H +#include <QObject> #include <QQmlParserStatus> #include <QQmlListProperty> #include "qmlsensorrange.h" @@ -51,9 +52,11 @@ class QSensorReading; class QmlSensorReading; +class QmlSensorPrivate; class QmlSensor : public QObject, public QQmlParserStatus { Q_OBJECT + Q_DECLARE_PRIVATE(QmlSensor) Q_ENUMS(AxesOrientationMode) Q_INTERFACES(QQmlParserStatus) Q_PROPERTY(QString identifier READ identifier WRITE setIdentifier NOTIFY identifierChanged) diff --git a/src/imports/sensors/sensors.pro b/src/imports/sensors/sensors.pro index d627916..7d15ec9 100644 --- a/src/imports/sensors/sensors.pro +++ b/src/imports/sensors/sensors.pro @@ -1,4 +1,4 @@ -QT += qml sensors sensors-private +QT += core-private qml sensors sensors-private HEADERS += \ qmlsensor.h \ |