state: Qt6::Sensors + libinput both built — 2 of 3 platform prerequisites resolved

Platform prerequisite status:
- Qt6::Sensors: BUILT (v6.11.0, 520KB pkgar, dummy backend)
- libinput: BUILT (v1.30.2, with libevdev v1.13.2 + linux-input-headers)
- QML/Quick JIT: still disabled on Redox (blocks real KWin binary,
  kirigami, plasma-framework)

KWin: now attempts real cmake build with Sensors + libinput deps
enabled. Falls back to redbear-compositor shim on cmake failure
(QML/Quick gate). Previously kwin was pure stub — now it's a
bounded build attempt with fallback.

Enabled in config (new this session):
- qt6-sensors, libevdev, libinput, kdecoration, kf6-kcmutils

Previously OOTB dependencies now resolved:
- libevdev → libinput → KWin real build path opened
- linux-input-headers → libevdev → libinput chain
- qt6-sensors → KWin Sensors dependency satisfied
This commit is contained in:
2026-04-30 08:47:15 +01:00
parent c54dff033d
commit 8fa62d20c9
457 changed files with 106858 additions and 382 deletions
@@ -0,0 +1,6 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
if(TARGET Qt::Quick AND TARGET Qt::Svg)
qt_internal_add_example(sensorsshowcase)
endif()
@@ -0,0 +1,5 @@
TEMPLATE = subdirs
qtHaveModule(quick): qtHaveModule(svg): {
SUBDIRS += sensorsshowcase
}
@@ -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)
}
}
}
@@ -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}"
)
@@ -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
}
}
}
@@ -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"
}
}
}
@@ -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>
@@ -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)
}
}
}
@@ -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()
}
}
}
}
}
@@ -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
}
}
@@ -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
}
}
}
@@ -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>
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 578 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 962 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

@@ -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.
*/
@@ -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>

After

Width:  |  Height:  |  Size: 11 KiB

@@ -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>

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

@@ -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();
}
@@ -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
@@ -0,0 +1,6 @@
[Controls]
Style=Material
[Material]
Background=#eafcf3
Accent=#28c878
@@ -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
@@ -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