summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/manual/CMakeLists.txt3
-rw-r--r--tests/manual/sensor_explorer_qml/CMakeLists.txt32
-rw-r--r--tests/manual/sensor_explorer_qml/main.cpp20
-rw-r--r--tests/manual/sensor_explorer_qml/qml.qrc5
-rw-r--r--tests/manual/sensor_explorer_qml/sensor_explorer.qml119
-rw-r--r--tests/manual/sensor_explorer_qml/sensormodels.cpp185
-rw-r--r--tests/manual/sensor_explorer_qml/sensormodels.h61
-rw-r--r--tests/manual/sensor_explorer_widgets/CMakeLists.txt (renamed from tests/manual/sensor_explorer/CMakeLists.txt)2
-rw-r--r--tests/manual/sensor_explorer_widgets/explorer.cpp (renamed from tests/manual/sensor_explorer/explorer.cpp)0
-rw-r--r--tests/manual/sensor_explorer_widgets/explorer.h (renamed from tests/manual/sensor_explorer/explorer.h)0
-rw-r--r--tests/manual/sensor_explorer_widgets/explorer.ui (renamed from tests/manual/sensor_explorer/explorer.ui)0
-rw-r--r--tests/manual/sensor_explorer_widgets/main.cpp (renamed from tests/manual/sensor_explorer/main.cpp)0
12 files changed, 425 insertions, 2 deletions
diff --git a/tests/manual/CMakeLists.txt b/tests/manual/CMakeLists.txt
index a23fbcd8..8686f854 100644
--- a/tests/manual/CMakeLists.txt
+++ b/tests/manual/CMakeLists.txt
@@ -2,8 +2,9 @@
# SPDX-License-Identifier: BSD-3-Clause
if(TARGET Qt::Widgets)
- add_subdirectory(sensor_explorer)
+ add_subdirectory(sensor_explorer_widgets)
endif()
if (TARGET Qt::Quick)
add_subdirectory(sensorclerk)
+ add_subdirectory(sensor_explorer_qml)
endif()
diff --git a/tests/manual/sensor_explorer_qml/CMakeLists.txt b/tests/manual/sensor_explorer_qml/CMakeLists.txt
new file mode 100644
index 00000000..e68fce62
--- /dev/null
+++ b/tests/manual/sensor_explorer_qml/CMakeLists.txt
@@ -0,0 +1,32 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+cmake_minimum_required(VERSION 3.16)
+project(tst_manual_sensor_explorer_qml LANGUAGES CXX)
+
+set(CMAKE_AUTOMOC ON)
+
+find_package(Qt6 REQUIRED COMPONENTS Qml Quick Sensors)
+
+qt_add_executable(tst_manual_sensor_explorer_qml
+ main.cpp
+ sensormodels.cpp sensormodels.h
+)
+
+set_target_properties(tst_manual_sensor_explorer_qml PROPERTIES
+ WIN32_EXECUTABLE TRUE
+ MACOSX_BUNDLE TRUE
+)
+
+target_link_libraries(tst_manual_sensor_explorer_qml PUBLIC
+ Qt::Qml
+ Qt::Quick
+ Qt::Sensors
+)
+
+qt_add_qml_module(tst_manual_sensor_explorer_qml
+ URI SensorModels
+ VERSION 1.0
+ QML_FILES sensor_explorer.qml
+ NO_RESOURCE_TARGET_PATH
+)
diff --git a/tests/manual/sensor_explorer_qml/main.cpp b/tests/manual/sensor_explorer_qml/main.cpp
new file mode 100644
index 00000000..4eeaa147
--- /dev/null
+++ b/tests/manual/sensor_explorer_qml/main.cpp
@@ -0,0 +1,20 @@
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#include <QtQml>
+#include <QtQuick/QQuickWindow>
+#include <QtGui/QGuiApplication>
+
+int main(int argc, char *argv[])
+{
+ QGuiApplication app(argc, argv);
+ QQmlApplicationEngine engine(QUrl("qrc:///sensor_explorer.qml"));
+ QObject *topLevel = engine.rootObjects().value(0);
+ QQuickWindow *window = qobject_cast<QQuickWindow *>(topLevel);
+ if (!window) {
+ qWarning("Error: Your root item has to be a Window.");
+ return -1;
+ }
+ window->show();
+ return app.exec();
+}
diff --git a/tests/manual/sensor_explorer_qml/qml.qrc b/tests/manual/sensor_explorer_qml/qml.qrc
new file mode 100644
index 00000000..df6160ae
--- /dev/null
+++ b/tests/manual/sensor_explorer_qml/qml.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/">
+ <file>sensor_explorer.qml</file>
+ </qresource>
+</RCC>
diff --git a/tests/manual/sensor_explorer_qml/sensor_explorer.qml b/tests/manual/sensor_explorer_qml/sensor_explorer.qml
new file mode 100644
index 00000000..f1c4d3cb
--- /dev/null
+++ b/tests/manual/sensor_explorer_qml/sensor_explorer.qml
@@ -0,0 +1,119 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtQuick.Window
+import QtQuick.Controls
+import QtQuick.Layouts
+
+import SensorModels
+
+Window {
+ id: window
+ width: 400
+ height: 600
+
+ AvailableSensorsModel {
+ id: availableSensorsModel
+ }
+
+ ColumnLayout {
+
+ GroupBox {
+ id: availableSensorsModelGroup
+ title: qsTr("Available Sensors")
+ Layout.preferredWidth: window.width - 4 // 4 = 2x2 margins
+ Layout.preferredHeight: window.height * 0.4
+ Layout.margins: 2
+
+ ListView {
+ id: sensorsView
+ anchors.fill: parent
+ currentIndex: -1 // no initial selection
+ spacing: 1
+ clip: true
+ model: availableSensorsModel
+ delegate: Item {
+ id: sensorRow
+ width: sensorsView.width
+ height: 30
+ property color rowColor: {
+ if (sensorsView.currentIndex == index)
+ return "lightsteelblue" // highlight
+ return (index % 2 == 0) ? "#CCCCCC" : "#AAAAAA"
+ }
+ RowLayout {
+ spacing: 1
+ anchors.fill: parent
+ Rectangle {
+ color: sensorRow.rowColor
+ Layout.preferredWidth: sensorRow.width * 0.8
+ Layout.preferredHeight: sensorRow.height
+ Text {
+ anchors.centerIn: parent
+ text: display.type + "::" + display.identifier
+ }
+ }
+ Rectangle {
+ color: sensorRow.rowColor
+ Layout.preferredWidth: sensorRow.width * 0.2
+ Layout.preferredHeight: sensorRow.height
+ Text {
+ anchors.centerIn: parent
+ text: display.active ? qsTr("Active") : qsTr("Inactive")
+ }
+ }
+ }
+ MouseArea {
+ anchors.fill: parent
+ onClicked: sensorsView.currentIndex = index
+ }
+ }
+ }
+ }
+
+ SensorPropertyModel {
+ id: propertyModel
+ sensor: availableSensorsModel.get(sensorsView.currentIndex)
+ }
+
+ Button {
+ id: activateButton
+ Layout.preferredHeight: 30
+ Layout.alignment: Qt.AlignCenter
+ enabled: propertyModel.sensor
+ text: !propertyModel.sensor ? qsTr("Select sensor")
+ : (propertyModel.sensor.active ? qsTr("Deactivate sensor")
+ : qsTr("Activate sensor"))
+ onClicked: propertyModel.sensor.active = !propertyModel.sensor.active
+ }
+
+ GroupBox {
+ title: qsTr("Selected sensor's properties")
+ Layout.preferredWidth: window.width - 4 // 4 = 2x2 margins
+ Layout.preferredHeight: window.height * 0.55 - activateButton.height
+ Layout.margins: 2
+ enabled: sensorsView.currentIndex != -1
+
+ TableView {
+ id: propertyView
+ anchors.fill: parent
+ model: propertyModel
+ columnSpacing: 1
+ rowSpacing: 1
+ boundsMovement: Flickable.StopAtBounds
+ clip: true
+
+ delegate: Rectangle {
+ implicitHeight: 30
+ implicitWidth: propertyView.width * 0.5
+ color: (model.row % 2 == 0) ? "#CCCCCC" : "#AAAAAA"
+ Text {
+ anchors.centerIn: parent
+ text: display
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/tests/manual/sensor_explorer_qml/sensormodels.cpp b/tests/manual/sensor_explorer_qml/sensormodels.cpp
new file mode 100644
index 00000000..ed365e51
--- /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 BSD-3-Clause
+
+#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
diff --git a/tests/manual/sensor_explorer_qml/sensormodels.h b/tests/manual/sensor_explorer_qml/sensormodels.h
new file mode 100644
index 00000000..80f4bcbb
--- /dev/null
+++ b/tests/manual/sensor_explorer_qml/sensormodels.h
@@ -0,0 +1,61 @@
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#ifndef QSEONSOREXPLORER_H
+#define QSEONSOREXPLORER_H
+
+#include <QtSensors/qsensor.h>
+
+#include <QtQml/qqml.h>
+#include <QtCore/QAbstractListModel>
+#include <QtCore/QAbstractTableModel>
+
+QT_BEGIN_NAMESPACE
+
+class AvailableSensorsModel: public QAbstractListModel
+{
+ Q_OBJECT
+ QML_ELEMENT
+public:
+ explicit AvailableSensorsModel(QObject* parent = nullptr);
+ int rowCount(const QModelIndex & = QModelIndex()) const override;
+ QVariant data(const QModelIndex &index, int role) const override;
+ Q_INVOKABLE QSensor* get(int index) const;
+
+private:
+ void loadSensors();
+ QList<QSensor*> m_availableSensors;
+};
+
+class SensorPropertyModel: public QAbstractTableModel
+{
+ Q_OBJECT
+ Q_PROPERTY(QSensor* sensor READ sensor WRITE setSensor NOTIFY sensorChanged)
+ QML_ELEMENT
+
+public:
+ explicit SensorPropertyModel(QObject* parent = nullptr);
+
+ int rowCount(const QModelIndex & = QModelIndex()) const override;
+ int columnCount(const QModelIndex & = QModelIndex()) const override;
+ QVariant data(const QModelIndex &index, int role) const override;
+
+ void setSensor(QSensor* sensor);
+ QSensor* sensor() const;
+
+signals:
+ void sensorChanged();
+
+private slots:
+ void onReadingChanged();
+
+private:
+ QSensor* m_sensor = nullptr;
+ // m_values is used to cache sensor property values to avoid
+ // full metaobject iteration on every sensor reading change
+ QList<std::tuple<QByteArray, QByteArray>> m_values;
+};
+
+QT_END_NAMESPACE
+
+#endif // QSEONSOREXPLORER_H
diff --git a/tests/manual/sensor_explorer/CMakeLists.txt b/tests/manual/sensor_explorer_widgets/CMakeLists.txt
index 2f32dc91..357eb02e 100644
--- a/tests/manual/sensor_explorer/CMakeLists.txt
+++ b/tests/manual/sensor_explorer_widgets/CMakeLists.txt
@@ -5,7 +5,7 @@
## sensor_explorer Binary:
#####################################################################
-qt_internal_add_manual_test(tst_manual_sensor_explorer
+qt_internal_add_manual_test(tst_manual_sensor_explorer_widgets
GUI
SOURCES
explorer.cpp explorer.h explorer.ui
diff --git a/tests/manual/sensor_explorer/explorer.cpp b/tests/manual/sensor_explorer_widgets/explorer.cpp
index e6353c01..e6353c01 100644
--- a/tests/manual/sensor_explorer/explorer.cpp
+++ b/tests/manual/sensor_explorer_widgets/explorer.cpp
diff --git a/tests/manual/sensor_explorer/explorer.h b/tests/manual/sensor_explorer_widgets/explorer.h
index 92aa6f47..92aa6f47 100644
--- a/tests/manual/sensor_explorer/explorer.h
+++ b/tests/manual/sensor_explorer_widgets/explorer.h
diff --git a/tests/manual/sensor_explorer/explorer.ui b/tests/manual/sensor_explorer_widgets/explorer.ui
index 166e9c36..166e9c36 100644
--- a/tests/manual/sensor_explorer/explorer.ui
+++ b/tests/manual/sensor_explorer_widgets/explorer.ui
diff --git a/tests/manual/sensor_explorer/main.cpp b/tests/manual/sensor_explorer_widgets/main.cpp
index 0e2ea93d..0e2ea93d 100644
--- a/tests/manual/sensor_explorer/main.cpp
+++ b/tests/manual/sensor_explorer_widgets/main.cpp