diff options
author | Juha Vuolle <juha.vuolle@qt.io> | 2023-02-17 13:40:13 +0200 |
---|---|---|
committer | Juha Vuolle <juha.vuolle@qt.io> | 2023-02-22 08:37:59 +0200 |
commit | f5426ddda0c8e022d55290de70f96cb4db1801bb (patch) | |
tree | ad5cf038654f1a69ad1e86aea12bc1513a699202 /examples | |
parent | 20373cfd4019c66884fb63a4316b1c60ede089ca (diff) | |
download | qtsensors-f5426ddda0c8e022d55290de70f96cb4db1801bb.tar.gz |
Move sensor_explorer QML example to manual tests
The example is useful as a sensor testing tool, but less necessary
as an example. The primary demonstrative element of the example was
how to iterate the available sensors, which is covered in a
documentation snippet (followup commit).
This commit also renames the pre-existing widget-based sensor_explorer
manual test to avoid name conflicts, as well as removes the qdoc and qmake
support from the now-a-manual-test application.
Task-number: QTBUG-110939
Pick-to: 6.5
Change-Id: I422f62f852d0a7e40a76f555ec8aa98404164f7a
Reviewed-by: Lorn Potter <lorn.potter@gmail.com>
Diffstat (limited to 'examples')
-rw-r--r-- | examples/sensors/CMakeLists.txt | 7 | ||||
-rw-r--r-- | examples/sensors/sensor_explorer/CMakeLists.txt | 44 | ||||
-rw-r--r-- | examples/sensors/sensor_explorer/doc/images/qtsensors-examples-sensor-explorer.png | bin | 47605 -> 0 bytes | |||
-rw-r--r-- | examples/sensors/sensor_explorer/doc/src/sensor_explorer.qdoc | 118 | ||||
-rw-r--r-- | examples/sensors/sensor_explorer/main.cpp | 20 | ||||
-rw-r--r-- | examples/sensors/sensor_explorer/qml.qrc | 5 | ||||
-rw-r--r-- | examples/sensors/sensor_explorer/sensor_explorer.pro | 22 | ||||
-rw-r--r-- | examples/sensors/sensor_explorer/sensor_explorer.qml | 127 | ||||
-rw-r--r-- | examples/sensors/sensor_explorer/sensormodels.cpp | 191 | ||||
-rw-r--r-- | examples/sensors/sensor_explorer/sensormodels.h | 63 | ||||
-rw-r--r-- | examples/sensors/sensors.pro | 4 |
11 files changed, 2 insertions, 599 deletions
diff --git a/examples/sensors/CMakeLists.txt b/examples/sensors/CMakeLists.txt index ef323ef..ecbd35f 100644 --- a/examples/sensors/CMakeLists.txt +++ b/examples/sensors/CMakeLists.txt @@ -1,9 +1,6 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -if(TARGET Qt::Quick) - qt_internal_add_example(sensor_explorer) - if(TARGET Qt::Svg) - qt_internal_add_example(sensorsshowcase) - endif() +if(TARGET Qt::Quick AND TARGET Qt::Svg) + qt_internal_add_example(sensorsshowcase) endif() diff --git a/examples/sensors/sensor_explorer/CMakeLists.txt b/examples/sensors/sensor_explorer/CMakeLists.txt deleted file mode 100644 index 33fc7ea..0000000 --- a/examples/sensors/sensor_explorer/CMakeLists.txt +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: BSD-3-Clause - -cmake_minimum_required(VERSION 3.16) -project(sensor_explorer LANGUAGES CXX) - -set(CMAKE_AUTOMOC ON) - -if(NOT DEFINED INSTALL_EXAMPLESDIR) - set(INSTALL_EXAMPLESDIR "examples") -endif() - -set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/sensors/sensor_explorer") - -find_package(Qt6 REQUIRED COMPONENTS Qml Quick Sensors) - -qt_add_executable(sensor_explorer - main.cpp - sensormodels.cpp sensormodels.h -) - -set_target_properties(sensor_explorer PROPERTIES - WIN32_EXECUTABLE TRUE - MACOSX_BUNDLE TRUE -) - -target_link_libraries(sensor_explorer PUBLIC - Qt::Qml - Qt::Quick - Qt::Sensors -) - -qt_add_qml_module(sensor_explorer - URI SensorModels - VERSION 1.0 - QML_FILES sensor_explorer.qml - NO_RESOURCE_TARGET_PATH -) - -install(TARGETS sensor_explorer - RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" - BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" - LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" -) diff --git a/examples/sensors/sensor_explorer/doc/images/qtsensors-examples-sensor-explorer.png b/examples/sensors/sensor_explorer/doc/images/qtsensors-examples-sensor-explorer.png Binary files differdeleted file mode 100644 index 830f959..0000000 --- a/examples/sensors/sensor_explorer/doc/images/qtsensors-examples-sensor-explorer.png +++ /dev/null diff --git a/examples/sensors/sensor_explorer/doc/src/sensor_explorer.qdoc b/examples/sensors/sensor_explorer/doc/src/sensor_explorer.qdoc deleted file mode 100644 index f4d7c6b..0000000 --- a/examples/sensors/sensor_explorer/doc/src/sensor_explorer.qdoc +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright (C) 2017 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only - -/*! - \example sensor_explorer - \title Qt Sensors - Explorer QML Example - \ingroup qtsensors-examples - \brief Demonstrates how to read the meta-data of available sensors. - - \image qtsensors-examples-sensor-explorer.png - - The example is implemented as a typical model-view application. The - models are written with C++ and exposed to QML, and the views are - implemented as QML types in the QML application. - - \section1 Exposing and Importing the Models - - The QML models written in C++ are exposed in the project build files - as a \c SensorModels QML module. - - \e CMake: - \code - qt_add_qml_module(sensor_explorer - URI SensorModels - VERSION 1.0 - ) - \endcode - - \e qmake: - \code - CONFIG += qmltypes - QML_IMPORT_NAME = SensorModels - QML_IMPORT_MAJOR_VERSION = 1 - \endcode - - The individual model elements are exposed as part of the model - code by using the \c QML_ELEMENT macro as illustrated here: - \snippet sensor_explorer/sensormodels.h 0 - - To access the models in the QML application, the module is imported - by the application QML: - \snippet sensor_explorer/sensor_explorer.qml 0 - - \section1 Populating the Model of Available Sensors - - The \c AvailableSensorsModel is a list model that provides information on - available sensors on the device. The model is populated once at the - element's construction time: - - \snippet sensor_explorer/sensormodels.cpp 0 - - The model's \c data() function returns a pointer to the requested sensor - object. - - \snippet sensor_explorer/sensormodels.cpp 1 - - Since the sensor (QSensor) is a QObject, the QML is then able to directly - access all metaproperties and -functions directly. - - \note It would be possible to refresh the sensor list later at will, but for - the simplicity of the example such functionality is not exposed to QML. - - \section1 Populating the Model of Sensor Properties - - The \c SensorPropertyModel is a table model that provides individual - sensor's property-value pairs as columns. The column \c 0 provides the - property's name and the column \c 1 provides the property's value. The - population of the properties is done by reading the metadata of the sensors. - The model reads both the sensor's metadata as well as the sensor's reading's - metadata. The code below illustrates the reading of the \c reading metadata: - - \snippet sensor_explorer/sensormodels.cpp 2 - - This metadata access allows providing the model data for all sensors - without prior compile-time understanding of their properties. - - Once the metadata is set, the code then subscribes to the - QSensor::readingChanged() signal to detect sensor reading changes. - Upon such changes (for example a rotation value changes), the model data - is updated accordingly. - - \section1 Viewing the Models - - The QML application is based on two views. The first view shows the available - sensors as a selectable list. The second view shows the selected sensor's - properties and their values. The delegates for viewing the individual items - are simplistic \e {rectangle and text} items. - - Binding the two views functionally together is done by binding the property - model's \c sensor property to the current selection of the available sensors - model: - - \snippet sensor_explorer/sensor_explorer.qml 1 - - When the selected sensor changes, the \c sensor of the property model changes - accordingly. - - The following snippet illustrates how the property view is implemented. For - more details about QML models and views, please see - \l{Models and Views in Qt Quick}. - - \snippet sensor_explorer/sensor_explorer.qml 3 - - For clarity it should be mentioned that the \c display attribute used by - the text element refers to the Qt::DisplayRole role of the model, which is - provided by default by Qt models. - - \section1 Activating the Sensors - - The example has a button for activating and deactivating the currently - selected sensor. The button is enabled only if a sensor is currently - selected, as illustrated below. - - \snippet sensor_explorer/sensor_explorer.qml 2 - - On clicking the button, the sensor's active property is toggled on/off. - -*/ diff --git a/examples/sensors/sensor_explorer/main.cpp b/examples/sensors/sensor_explorer/main.cpp deleted file mode 100644 index 4eeaa14..0000000 --- a/examples/sensors/sensor_explorer/main.cpp +++ /dev/null @@ -1,20 +0,0 @@ -// 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/examples/sensors/sensor_explorer/qml.qrc b/examples/sensors/sensor_explorer/qml.qrc deleted file mode 100644 index df6160a..0000000 --- a/examples/sensors/sensor_explorer/qml.qrc +++ /dev/null @@ -1,5 +0,0 @@ -<RCC> - <qresource prefix="/"> - <file>sensor_explorer.qml</file> - </qresource> -</RCC> diff --git a/examples/sensors/sensor_explorer/sensor_explorer.pro b/examples/sensors/sensor_explorer/sensor_explorer.pro deleted file mode 100644 index a27681e..0000000 --- a/examples/sensors/sensor_explorer/sensor_explorer.pro +++ /dev/null @@ -1,22 +0,0 @@ -TEMPLATE = app -TARGET = sensor_explorer -QT += qml quick sensors - -# Avoid going to release/debug subdirectory -win32: DESTDIR = ./ - -SOURCES = main.cpp sensormodels.cpp -HEADERS = sensormodels.h - -CONFIG += qmltypes -QML_IMPORT_NAME = SensorModels -QML_IMPORT_MAJOR_VERSION = 1 - -OTHER_FILES = \ - sensor_explorer.qml - -target.path = $$[QT_INSTALL_EXAMPLES]/sensors/sensor_explorer -INSTALLS += target - -RESOURCES += \ - qml.qrc diff --git a/examples/sensors/sensor_explorer/sensor_explorer.qml b/examples/sensors/sensor_explorer/sensor_explorer.qml deleted file mode 100644 index 9fe59ba..0000000 --- a/examples/sensors/sensor_explorer/sensor_explorer.qml +++ /dev/null @@ -1,127 +0,0 @@ -// 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 - -//! [0] -import SensorModels -//! [0] - -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 - } - } - } - } - - //! [1] - SensorPropertyModel { - id: propertyModel - sensor: availableSensorsModel.get(sensorsView.currentIndex) - } - //! [1] - - //! [2] - 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 - } - //! [2] - - 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 - - //! [3] - 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 - } - } - } - //! [3] - } - } -} diff --git a/examples/sensors/sensor_explorer/sensormodels.cpp b/examples/sensors/sensor_explorer/sensormodels.cpp deleted file mode 100644 index f9ed4d9..0000000 --- a/examples/sensors/sensor_explorer/sensormodels.cpp +++ /dev/null @@ -1,191 +0,0 @@ -// 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() -{ - //! [0] - 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(); - //! [0] -} - -int AvailableSensorsModel::rowCount(const QModelIndex&) const -{ - return m_availableSensors.size(); -} - -//! [1] -QVariant AvailableSensorsModel::data(const QModelIndex &index, int role) const -{ - if (role != Qt::DisplayRole) - return QVariant(); - return QVariant::fromValue<QSensor*>(m_availableSensors.at(index.row())); -} -//! [1] - -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 - //! [2] - 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] - - // 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/examples/sensors/sensor_explorer/sensormodels.h b/examples/sensors/sensor_explorer/sensormodels.h deleted file mode 100644 index 02de2a8..0000000 --- a/examples/sensors/sensor_explorer/sensormodels.h +++ /dev/null @@ -1,63 +0,0 @@ -// 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 - -//! [0] -class AvailableSensorsModel: public QAbstractListModel -{ - Q_OBJECT - QML_ELEMENT -//! [0] -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/examples/sensors/sensors.pro b/examples/sensors/sensors.pro index 984d761..566e172 100644 --- a/examples/sensors/sensors.pro +++ b/examples/sensors/sensors.pro @@ -1,6 +1,2 @@ TEMPLATE = subdirs -qtHaveModule(quick) { - SUBDIRS += \ - sensor_explorer -} |