summaryrefslogtreecommitdiffstats
path: root/tests/manual/sensor_explorer_qml/sensormodels.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/manual/sensor_explorer_qml/sensormodels.cpp')
-rw-r--r--tests/manual/sensor_explorer_qml/sensormodels.cpp185
1 files changed, 185 insertions, 0 deletions
diff --git a/tests/manual/sensor_explorer_qml/sensormodels.cpp b/tests/manual/sensor_explorer_qml/sensormodels.cpp
new file mode 100644
index 00000000..36de4412
--- /dev/null
+++ b/tests/manual/sensor_explorer_qml/sensormodels.cpp
@@ -0,0 +1,185 @@
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include "sensormodels.h"
+#include "qsensor.h"
+#include "qorientationsensor.h"
+#include <QtCore/QDebug>
+#include <qsensor.h>
+#include <QMetaObject>
+#include <QMetaProperty>
+
+QT_BEGIN_NAMESPACE
+
+QByteArray rangelistToByteArray(const qrangelist& list)
+{
+ QStringList ranges;
+ for (const qrange &r : list) {
+ if (r.first == r.second)
+ ranges << QString("%1 Hz").arg(r.first);
+ else
+ ranges << QString("%1-%2 Hz").arg(r.first).arg(r.second);
+ }
+ if (ranges.size() > 0)
+ return ranges.join(", ").toLatin1();
+ return "-";
+}
+
+QByteArray outputrangelistToByteArray(const qoutputrangelist& list)
+{
+ QStringList ranges;
+ for (const qoutputrange &r : list) {
+ ranges << QString("(%1, %2) += %3").arg(r.minimum).arg(r.maximum).arg(r.accuracy);
+ }
+ if (ranges.size() > 0)
+ return ranges.join(", ").toLatin1();
+ return "-";
+}
+
+AvailableSensorsModel::AvailableSensorsModel(QObject* parent) : QAbstractListModel(parent)
+{
+ // Some valuetypes do not convert nicely to presentable strings, add converters for them
+ QMetaType::registerConverter<qrangelist, QByteArray>(rangelistToByteArray);
+ QMetaType::registerConverter<qoutputrangelist, QByteArray>(outputrangelistToByteArray);
+
+ // Populate the available sensors list
+ loadSensors();
+}
+
+/*
+ Load all available sensors and store them in a list.
+*/
+void AvailableSensorsModel::loadSensors()
+{
+ beginResetModel();
+ m_availableSensors.clear();
+
+ for (const QByteArray &type : QSensor::sensorTypes()) {
+ for (const QByteArray &identifier : QSensor::sensorsForType(type)) {
+ QSensor* sensor = new QSensor(type, this);
+ sensor->setIdentifier(identifier);
+ // Don't put in sensors we can't connect to
+ if (!sensor->connectToBackend())
+ continue;
+ m_availableSensors.append(sensor);
+ }
+ }
+ endResetModel();
+}
+
+int AvailableSensorsModel::rowCount(const QModelIndex&) const
+{
+ return m_availableSensors.size();
+}
+
+QVariant AvailableSensorsModel::data(const QModelIndex &index, int role) const
+{
+ if (role != Qt::DisplayRole)
+ return QVariant();
+ return QVariant::fromValue<QSensor*>(m_availableSensors.at(index.row()));
+}
+
+QSensor* AvailableSensorsModel::get(int index) const
+{
+ if (index < 0 || index >= m_availableSensors.size())
+ return nullptr;
+ return m_availableSensors[index];
+}
+
+// -- SensorPropertyModel
+
+static QSet<QByteArray> ignoredProperties = {"reading", "identifier", "active",
+ "connectedToBackend", "busy"};
+
+SensorPropertyModel::SensorPropertyModel(QObject* parent) : QAbstractTableModel(parent)
+{
+}
+
+int SensorPropertyModel::rowCount(const QModelIndex&) const
+{
+ if (!m_sensor)
+ return 0;
+ return m_values.size();
+}
+
+int SensorPropertyModel::columnCount(const QModelIndex&) const
+{
+ return 2; // 2 = property name + value columns
+}
+
+QVariant SensorPropertyModel::data(const QModelIndex &index, int role) const
+{
+ if (role != Qt::DisplayRole)
+ return QVariant();
+ return (index.column() == 0) ? std::get<0>(m_values.at(index.row()))
+ : std::get<1>(m_values.at(index.row()));
+}
+
+void SensorPropertyModel::setSensor(QSensor *sensor)
+{
+ if (m_sensor == sensor)
+ return;
+ if (m_sensor)
+ m_sensor->disconnect(this);
+ m_sensor = sensor;
+
+ beginResetModel();
+ m_values.clear();
+ if (m_sensor) {
+ // Use metobject to read the available properties. This allows the model to support all
+ // available sensors without knowing their properties in advance / compile-time.
+
+ // 1. Read properties of the 'reading' object if available
+ int firstProperty = QSensorReading::staticMetaObject.propertyOffset();
+ QSensorReading *reading = m_sensor->reading();
+ if (reading) {
+ const QMetaObject *mo = reading->metaObject();
+ for (int i = firstProperty; i < mo->propertyCount(); ++i) {
+ QByteArray name = mo->property(i).name();
+ m_values.append(std::tuple<QByteArray, QByteArray>
+ (name, reading->property(name).toByteArray()));
+ }
+ }
+
+ // 2. Read properties of the 'sensor' object
+ const QMetaObject *mo1 = m_sensor->metaObject();
+ firstProperty = QSensorReading::staticMetaObject.propertyOffset();
+ for (int i = firstProperty; i < mo1->propertyCount(); ++i) {
+ QByteArray name = mo1->property(i).name();
+ if (ignoredProperties.contains(name))
+ continue;
+ m_values.append(std::tuple<QByteArray, QByteArray>
+ (name, m_sensor->property(name).toByteArray()));
+ }
+ QObject::connect(m_sensor, &QSensor::readingChanged,
+ this, &SensorPropertyModel::onReadingChanged);
+ }
+ endResetModel();
+ emit sensorChanged();
+}
+
+QSensor* SensorPropertyModel::sensor() const
+{
+ return m_sensor;
+}
+
+void SensorPropertyModel::onReadingChanged()
+{
+ QSensorReading *reading = m_sensor->reading();
+ const QMetaObject *mo = reading->metaObject();
+ int firstProperty = QSensorReading::staticMetaObject.propertyOffset();
+
+ int valueMapIndex = 0;
+ for (int i = firstProperty; i < mo->propertyCount(); ++i) {
+ QByteArray name = mo->property(i).name();
+ // Update the value and signal the change. Note: here we rely that the "reading"
+ // properties are first on the m_values, and in same order as after the initial
+ // population. This should be true as we access the static metabobject (dynamic
+ // property changes shouldn't impact)
+ m_values[valueMapIndex++] = std::tuple<QByteArray, QByteArray>
+ (name, reading->property(name).toByteArray());
+ }
+ emit dataChanged(createIndex(0,1), createIndex(valueMapIndex,1), {Qt::DisplayRole});
+}
+
+QT_END_NAMESPACE