summaryrefslogtreecommitdiffstats
path: root/examples/sensors/sensorsshowcase
diff options
context:
space:
mode:
Diffstat (limited to 'examples/sensors/sensorsshowcase')
-rw-r--r--examples/sensors/sensorsshowcase/Accelerometer.qml70
-rw-r--r--examples/sensors/sensorsshowcase/CMakeLists.txt72
-rw-r--r--examples/sensors/sensorsshowcase/Compass.qml61
-rw-r--r--examples/sensors/sensorsshowcase/Gyroscope.qml128
-rw-r--r--examples/sensors/sensorsshowcase/Info.plist32
-rw-r--r--examples/sensors/sensorsshowcase/Magnetometer.qml68
-rw-r--r--examples/sensors/sensorsshowcase/Main.qml116
-rw-r--r--examples/sensors/sensorsshowcase/ProgressXYZBar.qml45
-rw-r--r--examples/sensors/sensorsshowcase/Proximity.qml55
-rw-r--r--examples/sensors/sensorsshowcase/android/AndroidManifest.xml57
-rw-r--r--examples/sensors/sensorsshowcase/android/res/drawable-hdpi/icon.pngbin0 -> 1352 bytes
-rw-r--r--examples/sensors/sensorsshowcase/android/res/drawable-ldpi/icon.pngbin0 -> 578 bytes
-rw-r--r--examples/sensors/sensorsshowcase/android/res/drawable-mdpi/icon.pngbin0 -> 962 bytes
-rw-r--r--examples/sensors/sensorsshowcase/android/res/drawable-xhdpi/icon.pngbin0 -> 1944 bytes
-rw-r--r--examples/sensors/sensorsshowcase/android/res/drawable-xxhdpi/icon.pngbin0 -> 3030 bytes
-rw-r--r--examples/sensors/sensorsshowcase/android/res/drawable-xxxhdpi/icon.pngbin0 -> 4290 bytes
-rw-r--r--examples/sensors/sensorsshowcase/doc/images/sensorsshowcase-gyroscope.webpbin0 -> 11922 bytes
-rw-r--r--examples/sensors/sensorsshowcase/doc/images/sensorsshowcase-mainview.webpbin0 -> 16784 bytes
-rw-r--r--examples/sensors/sensorsshowcase/doc/src/sensorsshowcase.qdoc78
-rw-r--r--examples/sensors/sensorsshowcase/images/compass.svg222
-rw-r--r--examples/sensors/sensorsshowcase/images/magnet.svg98
-rw-r--r--examples/sensors/sensorsshowcase/images/qt_logo.pngbin0 -> 14809 bytes
-rw-r--r--examples/sensors/sensorsshowcase/main.cpp18
-rw-r--r--examples/sensors/sensorsshowcase/qmldir9
-rw-r--r--examples/sensors/sensorsshowcase/qtquickcontrols2.conf6
-rw-r--r--examples/sensors/sensorsshowcase/sensorsshowcase.pro46
-rw-r--r--examples/sensors/sensorsshowcase/sensorsupport.h41
27 files changed, 1222 insertions, 0 deletions
diff --git a/examples/sensors/sensorsshowcase/Accelerometer.qml b/examples/sensors/sensorsshowcase/Accelerometer.qml
new file mode 100644
index 00000000..a22e1404
--- /dev/null
+++ b/examples/sensors/sensorsshowcase/Accelerometer.qml
@@ -0,0 +1,70 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+pragma ComponentBehavior: Bound
+import QtQuick
+import QtQuick.Layouts
+import QtSensors
+
+Item {
+ id: root
+
+ required property int fontSize
+ required property int imageSize
+
+ //! [0]
+ Accelerometer {
+ id: accelerometer
+
+ property real x: 0
+ property real y: 0
+ property real z: 0
+
+ active: true
+ dataRate: 25
+
+ onReadingChanged: {
+ x = (reading as AccelerometerReading).x
+ y = (reading as AccelerometerReading).y
+ z = (reading as AccelerometerReading).z
+ imageTranslation.x = -x * 10
+ imageTranslation.y = y * 10
+ }
+ }
+ //! [0]
+ ColumnLayout {
+ id: layout
+
+ anchors.fill: parent
+ spacing: 10
+
+ Image {
+ id: image
+
+ Layout.alignment: Qt.AlignCenter
+ Layout.preferredHeight: root.imageSize
+ Layout.preferredWidth: root.imageSize
+ fillMode: Image.PreserveAspectFit
+ source: "images/qt_logo.png"
+
+ transform: [
+ Translate {
+ id: imageTranslation
+
+ x: 0
+ y: 0
+ }
+ ]
+ }
+
+ ProgressXYZBar {
+ Layout.fillWidth: true
+ fontSize: root.fontSize
+ xText: "X: " + accelerometer.x.toFixed(2)
+ xValue: 0.5 + (accelerometer.x / 100)
+ yText: "Y: " + accelerometer.y.toFixed(2)
+ yValue: 0.5 + (accelerometer.y / 100)
+ zText: "Z: " + accelerometer.z.toFixed(2)
+ zValue: 0.5 + (accelerometer.z / 100)
+ }
+ }
+}
diff --git a/examples/sensors/sensorsshowcase/CMakeLists.txt b/examples/sensors/sensorsshowcase/CMakeLists.txt
new file mode 100644
index 00000000..b949213a
--- /dev/null
+++ b/examples/sensors/sensorsshowcase/CMakeLists.txt
@@ -0,0 +1,72 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+cmake_minimum_required(VERSION 3.16)
+project(sensorsshowcase LANGUAGES CXX)
+
+if(NOT DEFINED INSTALL_EXAMPLESDIR)
+ set(INSTALL_EXAMPLESDIR "examples")
+endif()
+
+set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/sensors/sensorsshowcase")
+find_package(Qt6 REQUIRED COMPONENTS Core Gui Quick Svg Sensors)
+qt_standard_project_setup(REQUIRES 6.5)
+
+qt_add_executable(sensorsshowcase
+ main.cpp
+)
+
+set_target_properties(sensorsshowcase PROPERTIES
+ WIN32_EXECUTABLE TRUE
+ MACOSX_BUNDLE TRUE
+)
+
+if(ANDROID)
+ set_property(TARGET sensorsshowcase PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR
+ ${CMAKE_CURRENT_SOURCE_DIR}/android)
+endif()
+
+if(APPLE AND IOS)
+ set_property(TARGET sensorsshowcase PROPERTY
+ MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/Info.plist"
+ )
+else()
+ # default search path for the config file is "qrc:/"
+ qt_add_resources(sensorsshowcase "resources"
+ FILES qtquickcontrols2.conf)
+endif()
+
+qt_add_qml_module(sensorsshowcase
+ URI SensorShowcaseModule
+ VERSION 1.0
+ QML_FILES
+ "Main.qml"
+ "Accelerometer.qml"
+ "Compass.qml"
+ "Gyroscope.qml"
+ "Magnetometer.qml"
+ "Proximity.qml"
+ "ProgressXYZBar.qml"
+ RESOURCES
+ "images/compass.svg"
+ "images/magnet.svg"
+ "images/qt_logo.png"
+ SOURCES
+ sensorsupport.h
+)
+
+target_link_libraries(sensorsshowcase
+ PRIVATE
+ Qt::Core
+ Qt::Gui
+ Qt::Quick
+ Qt::Svg
+ Qt::Sensors
+)
+
+
+install(TARGETS sensorsshowcase
+ RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
+ BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
+ LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
+)
diff --git a/examples/sensors/sensorsshowcase/Compass.qml b/examples/sensors/sensorsshowcase/Compass.qml
new file mode 100644
index 00000000..b4bc5ff1
--- /dev/null
+++ b/examples/sensors/sensorsshowcase/Compass.qml
@@ -0,0 +1,61 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+pragma ComponentBehavior: Bound
+import QtQuick
+import QtQuick.Layouts
+import QtSensors
+
+Item {
+ id: root
+
+ required property int fontSize
+ required property int imageSize
+ property alias isActive: compass.active
+
+ property real azimuth: 30
+
+ Compass {
+ id: compass
+ active: true
+ dataRate: 7
+ onReadingChanged: root.azimuth = -(reading as CompassReading).azimuth
+ }
+
+ ColumnLayout {
+ id: layout
+
+ anchors.fill: parent
+ spacing: 10
+
+ Image {
+ id: arrow
+
+ Layout.alignment: Qt.AlignHCenter
+ Layout.preferredWidth: root.imageSize * 1.25
+ Layout.fillHeight: true
+
+ source: "images/compass.svg"
+ fillMode: Image.PreserveAspectFit
+ rotation: root.azimuth
+ }
+
+ Rectangle {
+ id: separator
+
+ Layout.topMargin: 10
+ Layout.preferredWidth: parent.width * 0.75
+ Layout.preferredHeight: 1
+ Layout.alignment: Qt.AlignHCenter
+ color: "black"
+ }
+
+ Text {
+ id: info
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ Layout.topMargin: 10
+ text: "Azimuth: " + root.azimuth.toFixed(2) + "°"
+ font.pixelSize: root.fontSize
+ }
+ }
+}
diff --git a/examples/sensors/sensorsshowcase/Gyroscope.qml b/examples/sensors/sensorsshowcase/Gyroscope.qml
new file mode 100644
index 00000000..9f0ffd2f
--- /dev/null
+++ b/examples/sensors/sensorsshowcase/Gyroscope.qml
@@ -0,0 +1,128 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+pragma ComponentBehavior: Bound
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Layouts
+import QtSensors
+
+Item {
+ id: root
+
+ required property int fontSize
+ required property int imageSize
+
+ function resetRotations() : void
+ {
+ imageXRotation.angle = 0
+ imageYRotation.angle = 0
+ imageZRotation.angle = 0
+ }
+
+ //! [0]
+ Gyroscope {
+ id: gyroscope
+
+ property var lastTimeStamp: 0
+ property real x: 0
+ property real y: 0
+ property real z: 0
+
+ active: true
+ dataRate: 25
+
+ onReadingChanged: {
+ x = (reading as GyroscopeReading).x
+ y = (reading as GyroscopeReading).y
+ z = (reading as GyroscopeReading).z
+ let firstCall = false
+ if (lastTimeStamp == 0) {
+ firstCall = true
+ }
+ let timeSinceLast = reading.timestamp - lastTimeStamp
+ lastTimeStamp = reading.timestamp
+
+ //Skipping the initial time jump from 0
+ if (firstCall === true)
+ return
+ let normalizedX = x * (timeSinceLast / 1000000)
+ imageXRotation.angle += normalizedX
+ let normalizedY = y * (timeSinceLast / 1000000)
+ imageYRotation.angle -= normalizedY
+ let normalizedZ = z * (timeSinceLast / 1000000)
+ imageZRotation.angle += normalizedZ
+ }
+ }
+ //! [0]
+ ColumnLayout {
+ id: layout
+
+ anchors.fill: parent
+ spacing: 10
+
+ Image {
+ id: image
+
+ Layout.alignment: Qt.AlignHCenter
+ Layout.fillHeight: true
+ Layout.preferredWidth: root.imageSize
+ fillMode: Image.PreserveAspectFit
+ source: "images/qt_logo.png"
+
+ transform: [
+ Rotation {
+ id: imageXRotation
+
+ angle: 0
+ axis.x: 1
+ axis.y: 0
+ axis.z: 0
+ origin.x: layout.width / 2
+ origin.y: layout.height / 3
+ },
+ Rotation {
+ id: imageYRotation
+
+ angle: 0
+ axis.x: 0
+ axis.y: 1
+ axis.z: 0
+ origin.x: layout.width / 2
+ origin.y: layout.height / 3
+ },
+ Rotation {
+ id: imageZRotation
+
+ angle: 0
+ axis.x: 0
+ axis.y: 0
+ axis.z: 1
+ origin.x: layout.width / 2
+ origin.y: layout.height / 3
+ }
+ ]
+ }
+
+ ProgressXYZBar {
+ Layout.fillWidth: true
+ Layout.topMargin: 20
+ fontSize: root.fontSize
+ xText: "X: " + gyroscope.x.toFixed(2)
+ xValue: 0.5 + (gyroscope.x / 1000)
+ yText: "Y: " + gyroscope.y.toFixed(2)
+ yValue: 0.5 + (gyroscope.y / 1000)
+ zText: "Z: " + gyroscope.z.toFixed(2)
+ zValue: 0.5 + (gyroscope.z / 1000)
+ }
+
+ Button {
+ Layout.alignment: Qt.AlignHCenter
+ Layout.topMargin: 20
+ Layout.bottomMargin: 10
+ Layout.preferredWidth: parent.width / 2
+ Layout.preferredHeight: 60
+ onClicked: root.resetRotations()
+ text: "Reset rotation"
+ }
+ }
+}
diff --git a/examples/sensors/sensorsshowcase/Info.plist b/examples/sensors/sensorsshowcase/Info.plist
new file mode 100644
index 00000000..61d01e5a
--- /dev/null
+++ b/examples/sensors/sensorsshowcase/Info.plist
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDisplayName</key>
+ <string>sensorsshowcase</string>
+ <key>CFBundleExecutable</key>
+ <string>sensorsshowcase</string>
+ <key>CFBundleGetInfoString</key>
+ <string>Created by Qt/QMake</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.qt.sensorsshowcase</string>
+ <key>CFBundleName</key>
+ <string>sensorsshowcase</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1.0</string>
+ <key>LSRequiresIPhoneOS</key>
+ <true/>
+ <key>UILaunchStoryboardName</key>
+ <string>LaunchScreen</string>
+ <key>UISupportedInterfaceOrientations</key>
+ <array>
+ <string>UIInterfaceOrientationPortrait</string>
+ </array>
+</dict>
+</plist>
diff --git a/examples/sensors/sensorsshowcase/Magnetometer.qml b/examples/sensors/sensorsshowcase/Magnetometer.qml
new file mode 100644
index 00000000..551f8627
--- /dev/null
+++ b/examples/sensors/sensorsshowcase/Magnetometer.qml
@@ -0,0 +1,68 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+pragma ComponentBehavior: Bound
+import QtQuick
+import QtQuick.Layouts
+import QtSensors
+
+Item {
+ id: root
+
+ required property int fontSize
+ required property int imageSize
+
+ property real magnetRotation: 40
+ property real magnetometerX: 0
+ property real magnetometerY: 0
+ property real magnetometerZ: 0
+ property int barScaleFactor: 10000
+
+ //! [0]
+ Magnetometer {
+ id: magnetometer
+ active: true
+ dataRate: 25
+ onReadingChanged: {
+ root.magnetometerX = (reading as MagnetometerReading).x
+ root.magnetometerY = (reading as MagnetometerReading).y
+ root.magnetometerZ = (reading as MagnetometerReading).z
+ root.magnetRotation =
+ ((Math.atan2(root.magnetometerX, root.magnetometerY) / Math.PI) * 180)
+ }
+ }
+ //! [0]
+
+ ColumnLayout {
+ id: layout
+
+ anchors.fill: parent
+ spacing: 10
+
+ Image {
+ id: image
+
+ Layout.alignment: Qt.AlignHCenter
+ Layout.bottomMargin: 20
+ Layout.preferredWidth: root.imageSize * 0.9
+ Layout.preferredHeight: root.imageSize * 0.9
+
+ source: "images/magnet.svg"
+ fillMode: Image.PreserveAspectFit
+ rotation: root.magnetRotation
+ }
+
+ ProgressXYZBar {
+ Layout.fillWidth: true
+ fontSize: root.fontSize
+
+ xText: "X: " + root.magnetometerX.toFixed(9)
+ xValue: 0.5 + (root.magnetometerX * root.barScaleFactor)
+
+ yText: "Y: " + root.magnetometerY.toFixed(9)
+ yValue: 0.5 + (root.magnetometerY * root.barScaleFactor)
+
+ zText: "Z: " + root.magnetometerZ.toFixed(9)
+ zValue: 0.5 + (root.magnetometerZ * root.barScaleFactor)
+ }
+ }
+}
diff --git a/examples/sensors/sensorsshowcase/Main.qml b/examples/sensors/sensorsshowcase/Main.qml
new file mode 100644
index 00000000..4587ba21
--- /dev/null
+++ b/examples/sensors/sensorsshowcase/Main.qml
@@ -0,0 +1,116 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+pragma ComponentBehavior: Bound
+
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Layouts
+
+ApplicationWindow {
+ id: root
+
+ readonly property int defaultFontSize: 22
+ readonly property int imageSize: width / 2
+
+ width: 420
+ height: 760
+ visible: true
+ title: "Sensors Showcase"
+
+ header : ToolBar {
+ RowLayout {
+ anchors.fill: parent
+ anchors.leftMargin: 10
+ anchors.rightMargin: 10
+ ToolButton {
+ id: back
+ text: qsTr("Back")
+ font.pixelSize: root.defaultFontSize - 4
+ visible: stack.depth > 1
+ onClicked: {
+ stack.pop();
+ heading.text = root.title;
+ }
+ Layout.alignment: Qt.AlignLeft
+ }
+ Label {
+ id: heading
+ text: root.title
+ font.pixelSize: root.defaultFontSize
+ font.weight: Font.Medium
+ verticalAlignment: Qt.AlignVCenter
+ Layout.alignment: Qt.AlignCenter
+ Layout.preferredHeight: 55
+ }
+ Item {
+ visible: back.visible
+ Layout.preferredWidth: back.width
+ }
+ }
+ }
+
+ StackView {
+ id: stack
+
+ // Pushes the object and forwards the properties
+ function pusher(object : string) : void {
+ // Trim the suffix and set it as new heading
+ heading.text = object.split(".")[0]
+ return stack.push(object, {
+ fontSize: root.defaultFontSize,
+ imageSize: root.imageSize
+ })
+ }
+
+ anchors.fill: parent
+ anchors.margins: width / 12
+
+ initialItem: Item {
+ ColumnLayout {
+ id: initialItem
+
+ anchors.fill: parent
+ anchors.topMargin: 20
+ anchors.bottomMargin: 20
+ spacing: 5
+
+ component CustomButton: Button {
+ highlighted: true
+ font.pixelSize: root.defaultFontSize
+ font.letterSpacing: 1.5
+
+ Layout.alignment: Qt.AlignCenter
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+ }
+
+ CustomButton {
+ text: "Accelerometer"
+ onClicked: stack.pusher("Accelerometer.qml")
+ enabled: SensorSupport.hasAccelerometer()
+ }
+ CustomButton {
+ text: "Proximity"
+ onClicked: stack.pusher("Proximity.qml")
+ enabled: SensorSupport.hasProximity()
+ }
+ CustomButton {
+ text: "Compass"
+ onClicked: stack.pusher("Compass.qml")
+ enabled: SensorSupport.hasCompass()
+ }
+ CustomButton {
+ text: "Magnetometer"
+ onClicked: stack.pusher("Magnetometer.qml")
+ enabled: SensorSupport.hasMagnetometer()
+ }
+ CustomButton {
+ text: "Gyroscope"
+ onClicked: stack.pusher("Gyroscope.qml")
+ enabled: SensorSupport.hasGyroscope()
+ }
+ }
+ }
+ }
+
+}
diff --git a/examples/sensors/sensorsshowcase/ProgressXYZBar.qml b/examples/sensors/sensorsshowcase/ProgressXYZBar.qml
new file mode 100644
index 00000000..be7bf7ae
--- /dev/null
+++ b/examples/sensors/sensorsshowcase/ProgressXYZBar.qml
@@ -0,0 +1,45 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+pragma ComponentBehavior: Bound
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Layouts
+
+ColumnLayout {
+ id: root
+ spacing: 0
+
+ required property int fontSize
+ property alias xText: xBar.text
+ property alias xValue: xBar.value
+ property alias yText: yBar.text
+ property alias yValue: yBar.value
+ property alias zText: zBar.text
+ property alias zValue: zBar.value
+
+ component NamedProgressBar: ColumnLayout {
+ property alias text: axes.text
+ property alias value: bar.value
+ Text {
+ id: axes
+ font.pixelSize: root.fontSize
+ Layout.fillWidth: true
+ }
+ ProgressBar {
+ id: bar
+ Layout.fillWidth: true
+ }
+ }
+
+ NamedProgressBar {
+ id: xBar
+ }
+
+ NamedProgressBar {
+ id: yBar
+ }
+
+ NamedProgressBar {
+ id: zBar
+ }
+}
diff --git a/examples/sensors/sensorsshowcase/Proximity.qml b/examples/sensors/sensorsshowcase/Proximity.qml
new file mode 100644
index 00000000..41121983
--- /dev/null
+++ b/examples/sensors/sensorsshowcase/Proximity.qml
@@ -0,0 +1,55 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+pragma ComponentBehavior: Bound
+import QtQuick
+import QtQuick.Layouts
+import QtSensors
+
+Item {
+ id: root
+
+ required property int imageSize
+ required property int fontSize
+
+ property bool near: false
+
+ ProximitySensor {
+ id: proximity
+ onReadingChanged: root.near = (reading as ProximityReading).near
+ active: true
+ }
+
+ ColumnLayout {
+ id: layout
+
+ anchors.fill: parent
+ spacing: 10
+
+ Image {
+ id: image
+
+ Layout.alignment: Qt.AlignHCenter
+ Layout.preferredWidth: root.near ? root.imageSize : root.imageSize * 0.75
+ Layout.fillHeight: true
+
+ source: "images/qt_logo.png"
+ fillMode: Image.PreserveAspectFit
+ }
+
+ Rectangle {
+ id: separator
+ Layout.topMargin: 10
+ Layout.bottomMargin: 10
+ Layout.preferredWidth: parent.width * 0.75
+ Layout.preferredHeight: 1
+ Layout.alignment: Qt.AlignHCenter
+ color: "black"
+ }
+
+ Text {
+ Layout.fillHeight: true
+ font.pixelSize: root.fontSize
+ text: "Near: " + root.near
+ }
+ }
+}
diff --git a/examples/sensors/sensorsshowcase/android/AndroidManifest.xml b/examples/sensors/sensorsshowcase/android/AndroidManifest.xml
new file mode 100644
index 00000000..359c0114
--- /dev/null
+++ b/examples/sensors/sensorsshowcase/android/AndroidManifest.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="org.qtproject.example.sensorsshowcase"
+ android:installLocation="auto"
+ android:versionCode="1"
+ android:versionName="1.0">
+ <!-- The comment below will be replaced with dependencies permissions upon deployment.
+ Remove the comment if you do not require these default permissions. -->
+ <!-- %%INSERT_PERMISSIONS -->
+
+ <!-- The comment below will be replaced with dependencies permissions upon deployment.
+ Remove the comment if you do not require these default features. -->
+ <!-- %%INSERT_FEATURES -->
+ <supports-screens
+ android:anyDensity="true"
+ android:largeScreens="true"
+ android:normalScreens="true"
+ android:smallScreens="true" />
+ <application
+ android:name="org.qtproject.qt.android.bindings.QtApplication"
+ android:extractNativeLibs="true"
+ android:hardwareAccelerated="true"
+ android:label="-- %%INSERT_APP_NAME%% --"
+ android:requestLegacyExternalStorage="true"
+ android:allowNativeHeapPointerTagging="false"
+ android:allowBackup="true"
+ android:fullBackupOnly="false"
+ android:icon="@drawable/icon">
+ <activity
+ android:name="org.qtproject.qt.android.bindings.QtActivity"
+ android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation|mcc|mnc|density"
+ android:label="-- %%INSERT_APP_NAME%% --"
+ android:launchMode="singleTop"
+ android:screenOrientation="portrait"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+
+ <meta-data
+ android:name="android.app.lib_name"
+ android:value="-- %%INSERT_APP_LIB_NAME%% --" />
+
+ <meta-data android:name="android.app.arguments"
+ android:value="" />
+
+ <meta-data
+ android:name="android.app.extract_android_style"
+ android:value="minimal" />
+
+ <meta-data
+ android:name="android.app.background_running"
+ android:value="false" />
+ </activity>
+ </application>
+</manifest>
diff --git a/examples/sensors/sensorsshowcase/android/res/drawable-hdpi/icon.png b/examples/sensors/sensorsshowcase/android/res/drawable-hdpi/icon.png
new file mode 100644
index 00000000..5f61088b
--- /dev/null
+++ b/examples/sensors/sensorsshowcase/android/res/drawable-hdpi/icon.png
Binary files differ
diff --git a/examples/sensors/sensorsshowcase/android/res/drawable-ldpi/icon.png b/examples/sensors/sensorsshowcase/android/res/drawable-ldpi/icon.png
new file mode 100644
index 00000000..605497de
--- /dev/null
+++ b/examples/sensors/sensorsshowcase/android/res/drawable-ldpi/icon.png
Binary files differ
diff --git a/examples/sensors/sensorsshowcase/android/res/drawable-mdpi/icon.png b/examples/sensors/sensorsshowcase/android/res/drawable-mdpi/icon.png
new file mode 100644
index 00000000..3eb10832
--- /dev/null
+++ b/examples/sensors/sensorsshowcase/android/res/drawable-mdpi/icon.png
Binary files differ
diff --git a/examples/sensors/sensorsshowcase/android/res/drawable-xhdpi/icon.png b/examples/sensors/sensorsshowcase/android/res/drawable-xhdpi/icon.png
new file mode 100644
index 00000000..a9e39f88
--- /dev/null
+++ b/examples/sensors/sensorsshowcase/android/res/drawable-xhdpi/icon.png
Binary files differ
diff --git a/examples/sensors/sensorsshowcase/android/res/drawable-xxhdpi/icon.png b/examples/sensors/sensorsshowcase/android/res/drawable-xxhdpi/icon.png
new file mode 100644
index 00000000..b489d81e
--- /dev/null
+++ b/examples/sensors/sensorsshowcase/android/res/drawable-xxhdpi/icon.png
Binary files differ
diff --git a/examples/sensors/sensorsshowcase/android/res/drawable-xxxhdpi/icon.png b/examples/sensors/sensorsshowcase/android/res/drawable-xxxhdpi/icon.png
new file mode 100644
index 00000000..9443da63
--- /dev/null
+++ b/examples/sensors/sensorsshowcase/android/res/drawable-xxxhdpi/icon.png
Binary files differ
diff --git a/examples/sensors/sensorsshowcase/doc/images/sensorsshowcase-gyroscope.webp b/examples/sensors/sensorsshowcase/doc/images/sensorsshowcase-gyroscope.webp
new file mode 100644
index 00000000..0ff45403
--- /dev/null
+++ b/examples/sensors/sensorsshowcase/doc/images/sensorsshowcase-gyroscope.webp
Binary files differ
diff --git a/examples/sensors/sensorsshowcase/doc/images/sensorsshowcase-mainview.webp b/examples/sensors/sensorsshowcase/doc/images/sensorsshowcase-mainview.webp
new file mode 100644
index 00000000..b045b7ba
--- /dev/null
+++ b/examples/sensors/sensorsshowcase/doc/images/sensorsshowcase-mainview.webp
Binary files differ
diff --git a/examples/sensors/sensorsshowcase/doc/src/sensorsshowcase.qdoc b/examples/sensors/sensorsshowcase/doc/src/sensorsshowcase.qdoc
new file mode 100644
index 00000000..d3d31c34
--- /dev/null
+++ b/examples/sensors/sensorsshowcase/doc/src/sensorsshowcase.qdoc
@@ -0,0 +1,78 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+ \example sensorsshowcase
+ \title Sensors Showcase
+ \brief The Sensors Showcase example demonstrates sensor usage with visual examples.
+ \meta tag {sensors,quick,mobile}
+ \ingroup qtsensors-examples
+ \examplecategory {Mobile}
+
+ \image sensorsshowcase-mainview.webp
+
+ \section1 Overview
+
+ On startup, the application shows a menu with buttons for the subviews for each sensor.
+ The sensor views instantiate the given sensor, display the sensor's values as numbers,
+ and also visualize them with a simple graphical representation.
+
+ \section1 Main Menu
+
+ The main view shows the title with the name of the application and a button
+ for each subview laid out evenly by a \c ColumnLayout. A \c StackView
+ manages the navigation between the subviews and the main menu. The
+ application checks the availability of the sensors during startup and
+ disables the buttons for the sensors that are not available.
+
+ \note To simplify the example, the sensor availability is checked only once
+ during the startup.
+
+ \section1 Accelerometer View
+
+ The accelerometer view shows the current device acceleration values and moves around
+ an image with an amount that is opposite of the device acceleration giving the image
+ an inertia effect that is proportional with the movement of the device.
+
+ Moving around the image happens in the accelerometer \c onReadingChanged method.
+
+ \snippet sensorsshowcase/Accelerometer.qml 0
+
+ Whenever there is a new accelerometer value the image translation coordinates are
+ updated accordingly.
+
+ \section1 Proximity View
+
+ The proximity view shows an image that is enlarged whenever the proximity sensor of
+ the device is covered.
+
+ \section1 Compass View
+
+ The compass view shows a compass image that is rotated according to the Compass sensor
+ reading value making the compass turn towards north.
+
+ \section1 Magnetometer View
+
+ The magnetometer view displays a magnet image that is rotated around an amount that is
+ decided by the rotation angle of the vector given by the x and y magnetometer values.
+ This results in general in the same rotation as the compass gives, demonstrating one use
+ case of how the magnetometer readings can be used. Since the magnetometer provides
+ readings along all three axes, there is more freedom with how these readings can be used.
+
+ \snippet sensorsshowcase/Magnetometer.qml 0
+
+ \section1 Gyroscope View
+
+ \image sensorsshowcase-gyroscope.webp
+
+ The gyroscope view also shows an image that is rotated around three axes with an amount
+ that is calculated from the gyroscope readings. Since the gyroscope provides relative
+ rotational change around the three spatial axes and the time between reading updates
+ can vary, the time of the readings are stored and the rotational change is normalized
+ based on the time passed between reading updates.
+
+ \snippet sensorsshowcase/Gyroscope.qml 0
+
+ By pressing the reset button the image rotation is reset to 0.
+*/
+
diff --git a/examples/sensors/sensorsshowcase/images/compass.svg b/examples/sensors/sensorsshowcase/images/compass.svg
new file mode 100644
index 00000000..009e6ffd
--- /dev/null
+++ b/examples/sensors/sensorsshowcase/images/compass.svg
@@ -0,0 +1,222 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ width="123.29776mm"
+ height="123.29776mm"
+ viewBox="0 0 123.29776 123.29776"
+ version="1.1"
+ id="svg5"
+ inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20)"
+ sodipodi:docname="compass.svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <sodipodi:namedview
+ id="namedview7"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ inkscape:pagecheckerboard="0"
+ inkscape:document-units="mm"
+ showgrid="false"
+ showborder="true"
+ inkscape:zoom="1.5554293"
+ inkscape:cx="118.61677"
+ inkscape:cy="123.76005"
+ inkscape:window-width="2560"
+ inkscape:window-height="1377"
+ inkscape:window-x="1912"
+ inkscape:window-y="72"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="layer1"
+ lock-margins="true"
+ fit-margin-top="15"
+ fit-margin-left="15"
+ fit-margin-right="15"
+ fit-margin-bottom="15" />
+ <defs
+ id="defs2" />
+ <g
+ inkscape:groupmode="layer"
+ id="layer2"
+ inkscape:label="Layer 2"
+ style="display:inline"
+ transform="translate(7.215891,-13.196477)">
+ <path
+ sodipodi:type="star"
+ style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.88976;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path2691"
+ inkscape:flatsided="false"
+ sodipodi:sides="4"
+ sodipodi:cx="131.1535"
+ sodipodi:cy="547.11584"
+ sodipodi:r1="75.011292"
+ sodipodi:r2="15.353019"
+ sodipodi:arg1="0.77933767"
+ sodipodi:arg2="1.5647358"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="m 184.51497,599.83441 -53.26842,-37.36583 -52.811613,38.00874 37.365833,-53.26843 -38.008738,-52.81161 53.268428,37.36583 52.81161,-38.00874 -37.36583,53.26843 z"
+ transform="matrix(0.45357635,0,0,0.48302392,-5.0551384,-189.42468)" />
+ <circle
+ style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path25062"
+ cx="54.432987"
+ cy="74.84536"
+ r="30" />
+ <circle
+ style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.579683;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="circle25206"
+ cx="54.432987"
+ cy="74.84536"
+ r="34.780952" />
+ </g>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ style="display:inline"
+ transform="translate(7.215891,-13.196477)">
+ <path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:1.88976;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path846"
+ inkscape:flatsided="false"
+ sodipodi:sides="4"
+ sodipodi:cx="205.73099"
+ sodipodi:cy="282.8801"
+ sodipodi:r1="176.15717"
+ sodipodi:r2="35.231434"
+ sodipodi:arg1="1.5707963"
+ sodipodi:arg2="2.3561945"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 205.73099,459.03726 180.8186,307.79248 29.573822,282.8801 180.8186,257.96771 l 24.91238,-151.24478 24.91239,151.24478 151.24478,24.91238 -151.24478,24.91239 z"
+ transform="scale(0.26458333)" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 54.432988,28.237108 2e-6,93.216502"
+ id="path991" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 7.8247403,74.845359 93.2164997,-3e-6"
+ id="path993" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 47.841587,68.253956 C 61.024391,81.436759 61.024391,81.436759 61.024391,81.436759"
+ id="path995" />
+ <path
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 61.024391,68.253956 47.841587,81.436759"
+ id="path997" />
+ <path
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.607473;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 193.43534,269.62014 c -6.2322,-6.23407 -11.33698,-11.55089 -11.34397,-11.81517 -0.007,-0.26428 5.0921,-31.50414 11.33128,-69.4219 l 11.34397,-68.9414 0.0816,40.4123 c 0.0449,22.22675 0.0449,58.56721 0,80.75656 l -0.0816,40.34427 z"
+ id="path1073"
+ transform="scale(0.26458333)" />
+ <path
+ style="fill:#aa0000;stroke:#000000;stroke-width:0.607473;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 206.57191,200.26456 c 0.0205,-44.46429 0.0937,-80.62717 0.16276,-80.36197 0.27012,1.03808 22.62323,137.13728 22.62323,137.74386 0,0.42036 -3.98335,4.62794 -11.41164,12.05401 l -11.41164,11.40825 z"
+ id="path1186"
+ transform="scale(0.26458333)" />
+ <path
+ style="fill:#0000ff;stroke:#000000;stroke-width:0.607473;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 206.57191,365.49565 -0.0373,-80.84415 11.41164,11.40825 c 7.42829,7.42607 11.41164,11.63365 11.41164,12.05401 0,0.60657 -22.35311,136.70578 -22.62323,137.74386 -0.069,0.2652 -0.14225,-35.89769 -0.16276,-80.36197 z"
+ id="path1336"
+ transform="scale(0.26458333)" />
+ <path
+ style="fill:#0000aa;fill-opacity:1;stroke:#000000;stroke-width:0.607473;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 193.41121,377.30741 C 187.17832,339.428 182.08439,308.218 182.09137,307.95187 c 0.007,-0.26613 5.14794,-5.61759 11.42434,-11.89212 l 11.41164,-11.40825 v 80.76379 c 0,44.42008 -0.0413,80.76378 -0.0918,80.76378 -0.0505,0 -5.19144,-30.99224 -11.42433,-68.87166 z"
+ id="path1412"
+ transform="scale(0.26458333)" />
+ <path
+ style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.607473;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 41.628379,282.04372 c 0.2652,-0.0654 31.724078,-5.25942 69.908621,-11.5423 l 69.42643,-11.4234 11.57959,11.57959 11.57958,11.57958 -81.4882,-0.0373 c -44.818513,-0.0205 -81.271221,-0.0908 -81.006021,-0.15619 z"
+ id="path2360"
+ transform="scale(0.26458333)" />
+ <path
+ style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.607473;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 111.38404,295.24525 c -37.746813,-6.24278 -68.992206,-11.41247 -69.434206,-11.48821 -0.442001,-0.0757 35.865552,-0.15937 80.683446,-0.18586 l 81.48708,-0.0482 -11.56902,11.57237 c -6.36296,6.3648 -11.78675,11.55617 -12.05287,11.53638 -0.26612,-0.0198 -31.36762,-5.14373 -69.11443,-11.38651 z"
+ id="path2436"
+ transform="scale(0.26458333)" />
+ <path
+ style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.607473;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 218.92415,270.65241 11.58478,-11.58478 69.42124,11.42566 c 38.18168,6.28411 69.63822,11.48048 69.90342,11.54749 0.2652,0.067 -36.18751,0.13862 -81.00602,0.15913 l -81.4882,0.0373 z"
+ id="path2475"
+ transform="scale(0.26458333)" />
+ <path
+ style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.607473;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 218.91063,295.09538 -11.56902,-11.57237 81.48708,0.0373 c 44.81789,0.0205 81.2701,0.0921 81.0049,0.15913 -0.42568,0.10756 -139.03687,22.94832 -139.26393,22.94832 -0.0495,0 -5.29607,-5.20757 -11.65903,-11.57237 z"
+ id="path2514"
+ transform="scale(0.26458333)" />
+ <path
+ style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.21495;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 51.111292,281.19388 c 0.5304,-0.13818 29.895283,-5.01467 65.255298,-10.83664 l 64.29093,-10.5854 10.92713,10.91122 10.92713,10.91123 -76.18242,-0.0746 c -41.900341,-0.041 -75.748469,-0.18764 -75.218068,-0.32583 z"
+ id="path2999"
+ transform="scale(0.26458333)" />
+ <path
+ style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.21495;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 219.88208,295.10818 -10.92236,-10.94226 76.17766,0.0508 c 41.89771,0.0279 75.88835,0.15784 75.53475,0.28872 -0.3536,0.13088 -28.99521,4.88871 -63.64802,10.57296 -34.65281,5.68424 -63.72839,10.47833 -64.61239,10.65353 -1.3859,0.27467 -3.11163,-1.18855 -12.52964,-10.62371 z"
+ id="path3075"
+ transform="scale(0.26458333)" />
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-weight:normal;font-size:10.5833px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
+ x="48.989689"
+ y="16.670103"
+ id="text6475"><tspan
+ sodipodi:role="line"
+ id="tspan6473"
+ style="stroke-width:0.264583"
+ x="48.989689"
+ y="16.670103"></tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-weight:normal;font-size:10.5833px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
+ x="50.474586"
+ y="25.95421"
+ id="text29322"><tspan
+ sodipodi:role="line"
+ id="tspan29320"
+ style="stroke-width:0.264583"
+ x="50.474586"
+ y="25.95421">N</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-weight:normal;font-size:10.5833px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
+ x="51.019772"
+ y="131.41812"
+ id="text33982"><tspan
+ sodipodi:role="line"
+ id="tspan33980"
+ style="stroke-width:0.264583"
+ x="51.019772"
+ y="131.41812">S</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-weight:normal;font-size:10.5833px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
+ x="104.54184"
+ y="78.702988"
+ id="text37802"><tspan
+ sodipodi:role="line"
+ id="tspan37800"
+ style="stroke-width:0.264583"
+ x="104.54184"
+ y="78.702988">E</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-weight:normal;font-size:10.5833px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
+ x="-4.1540327"
+ y="78.702988"
+ id="text39852"><tspan
+ sodipodi:role="line"
+ id="tspan39850"
+ style="stroke-width:0.264583"
+ x="-4.1540327"
+ y="78.702988">W</tspan></text>
+ </g>
+</svg>
diff --git a/examples/sensors/sensorsshowcase/images/magnet.svg b/examples/sensors/sensorsshowcase/images/magnet.svg
new file mode 100644
index 00000000..21d9f46b
--- /dev/null
+++ b/examples/sensors/sensorsshowcase/images/magnet.svg
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ width="152.6804mm"
+ height="186.70102mm"
+ viewBox="0 0 152.6804 186.70102"
+ version="1.1"
+ id="svg22292"
+ sodipodi:docname="magnet.svg"
+ inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20)"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <sodipodi:namedview
+ id="namedview22294"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ inkscape:pagecheckerboard="0"
+ inkscape:document-units="mm"
+ showgrid="false"
+ inkscape:zoom="3.1108586"
+ inkscape:cx="384.62051"
+ inkscape:cy="214.24953"
+ inkscape:window-width="2560"
+ inkscape:window-height="1377"
+ inkscape:window-x="1912"
+ inkscape:window-y="72"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="layer1" />
+ <defs
+ id="defs22289" />
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(0.34020391,-51.711357)">
+ <path
+ style="fill:none;stroke:#0000ff;stroke-width:40;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path22661"
+ sodipodi:type="arc"
+ sodipodi:cx="76.206184"
+ sodipodi:cy="162.27835"
+ sodipodi:rx="56.134018"
+ sodipodi:ry="56.134018"
+ sodipodi:start="1.5707963"
+ sodipodi:end="3.1415927"
+ sodipodi:arc-type="arc"
+ d="M 76.206184,218.41237 A 56.134018,56.134018 0 0 1 36.513439,201.9711 56.134018,56.134018 0 0 1 20.072166,162.27835"
+ sodipodi:open="true" />
+ <rect
+ style="fill:#cccccc;fill-opacity:1;stroke:none;stroke-width:0.814709;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect22976"
+ width="39.829895"
+ height="50.35051"
+ x="0.17010537"
+ y="51.711357" />
+ <path
+ style="fill:#ff0000;stroke:#ff0000;stroke-width:40;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path23734"
+ sodipodi:type="arc"
+ sodipodi:cx="-76.206184"
+ sodipodi:cy="162.27835"
+ sodipodi:rx="56.134018"
+ sodipodi:ry="56.134018"
+ sodipodi:start="1.5707963"
+ sodipodi:end="3.1415927"
+ sodipodi:arc-type="arc"
+ d="M -76.206184,218.41237 A 56.134018,56.134018 0 0 1 -115.89893,201.9711 56.134018,56.134018 0 0 1 -132.3402,162.27835"
+ sodipodi:open="true"
+ transform="scale(-1,1)" />
+ <rect
+ style="fill:#cccccc;fill-opacity:1;stroke:none;stroke-width:0.816447;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect24456"
+ width="40"
+ height="50.35051"
+ x="112.26804"
+ y="51.711357" />
+ <rect
+ style="fill:#ff0000;fill-opacity:1;stroke:none;stroke-width:1.00283;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect24480"
+ width="40"
+ height="60.340206"
+ x="112.26804"
+ y="102.06187" />
+ <rect
+ style="fill:#0000ff;fill-opacity:1;stroke:none;stroke-width:1.00563;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect24580"
+ width="39.829895"
+ height="60.93557"
+ x="0.17010537"
+ y="102.06187" />
+ </g>
+</svg>
diff --git a/examples/sensors/sensorsshowcase/images/qt_logo.png b/examples/sensors/sensorsshowcase/images/qt_logo.png
new file mode 100644
index 00000000..3a75e10c
--- /dev/null
+++ b/examples/sensors/sensorsshowcase/images/qt_logo.png
Binary files differ
diff --git a/examples/sensors/sensorsshowcase/main.cpp b/examples/sensors/sensorsshowcase/main.cpp
new file mode 100644
index 00000000..4a7bd285
--- /dev/null
+++ b/examples/sensors/sensorsshowcase/main.cpp
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+#include <QGuiApplication>
+#include <QQmlApplicationEngine>
+
+int main(int argc, char *argv[])
+{
+ QGuiApplication app(argc,argv);
+ QGuiApplication::setOrganizationName("QtProject");
+ QGuiApplication::setApplicationName("Sensors Showcase");
+
+ QQmlApplicationEngine engine;
+ engine.loadFromModule("SensorShowcaseModule", "Main");
+ if (engine.rootObjects().isEmpty())
+ return -1;
+
+ return app.exec();
+}
diff --git a/examples/sensors/sensorsshowcase/qmldir b/examples/sensors/sensorsshowcase/qmldir
new file mode 100644
index 00000000..76e61cdf
--- /dev/null
+++ b/examples/sensors/sensorsshowcase/qmldir
@@ -0,0 +1,9 @@
+module SensorShowcaseModule
+prefer :/qt/qml/SensorShowcaseModule/
+Main 1.0 Main.qml
+Accelerometer 1.0 Accelerometer.qml
+Compass 1.0 Compass.qml
+Gyroscope 1.0 Gyroscope.qml
+Magnetometer 1.0 Magnetometer.qml
+Proximity 1.0 Proximity.qml
+ProgressXYZBar 1.0 ProgressXYZBar.qml
diff --git a/examples/sensors/sensorsshowcase/qtquickcontrols2.conf b/examples/sensors/sensorsshowcase/qtquickcontrols2.conf
new file mode 100644
index 00000000..76439328
--- /dev/null
+++ b/examples/sensors/sensorsshowcase/qtquickcontrols2.conf
@@ -0,0 +1,6 @@
+[Controls]
+Style=Material
+
+[Material]
+Background=#eafcf3
+Accent=#28c878
diff --git a/examples/sensors/sensorsshowcase/sensorsshowcase.pro b/examples/sensors/sensorsshowcase/sensorsshowcase.pro
new file mode 100644
index 00000000..cded9071
--- /dev/null
+++ b/examples/sensors/sensorsshowcase/sensorsshowcase.pro
@@ -0,0 +1,46 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+QT += quick sensors svg
+
+TARGET = sensorsshowcase
+TEMPLATE = app
+
+SOURCES = main.cpp
+
+qml_resources.files = \
+ qmldir \
+ Main.qml \
+ Accelerometer.qml \
+ Compass.qml \
+ Gyroscope.qml \
+ Magnetometer.qml \
+ Proximity.qml \
+ ProgressXYZBar.qml \
+ images/compass.svg \
+ images/magnet.svg \
+ images/qt_logo.png
+
+qml_resources.prefix = /qt/qml/SensorShowcaseModule
+
+data_resources.files = \
+ qtquickcontrols2.conf
+
+data_resources.prefix = /
+
+RESOURCES += \
+ qml_resources \
+ data_resources
+
+android {
+ OTHER_FILES = android/AndroidManifest.xml
+ ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android
+}
+
+ios {
+ QMAKE_INFO_PLIST = Info.plist
+ EXAMPLE_FILES += Info.plist
+}
+
+target.path = $$[QT_INSTALL_EXAMPLES]/sensors/sensorsshowcase
+INSTALLS += target
diff --git a/examples/sensors/sensorsshowcase/sensorsupport.h b/examples/sensors/sensorsshowcase/sensorsupport.h
new file mode 100644
index 00000000..915157f8
--- /dev/null
+++ b/examples/sensors/sensorsshowcase/sensorsupport.h
@@ -0,0 +1,41 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+#ifndef SENSORSUPPORT_H
+#define SENSORSUPPORT_H
+
+#include <QObject>
+#include <QtQmlIntegration>
+#include <QtSensors/QtSensors>
+
+class SensorSupport : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ QML_SINGLETON
+ QML_UNCREATABLE("SensorSupport is a utility class")
+public:
+ explicit SensorSupport(QObject *parent = nullptr) : QObject(parent) { }
+
+ Q_INVOKABLE static bool hasAccelerometer()
+ {
+ return !QSensor::sensorsForType(QAccelerometer::sensorType).empty();
+ }
+ Q_INVOKABLE static bool hasCompass()
+ {
+ return !QSensor::sensorsForType(QCompass::sensorType).empty();
+ }
+ Q_INVOKABLE static bool hasGyroscope()
+ {
+ return !QSensor::sensorsForType(QGyroscope::sensorType).empty();
+ }
+ Q_INVOKABLE static bool hasMagnetometer()
+ {
+ return !QSensor::sensorsForType(QMagnetometer::sensorType).empty();
+ }
+ Q_INVOKABLE static bool hasProximity()
+ {
+ return !QSensor::sensorsForType(QProximitySensor::sensorType).empty();
+ }
+};
+
+#endif // SENSORSUPPORT_H