summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvan Solovev <ivan.solovev@qt.io>2023-03-24 15:10:22 +0100
committerIvan Solovev <ivan.solovev@qt.io>2023-03-28 14:44:21 +0200
commit007bf2bcf10007b02dd5fe09c0fc4be24229af14 (patch)
tree628e057af54c8b07db611fec7ca696c6ba5389dc
parenta1f43b9dcd722527d52ceb0c7a138bd2994c1a7b (diff)
downloadqtconnectivity-007bf2bcf10007b02dd5fe09c0fc4be24229af14.tar.gz
HeartRate Game: QML revamp
This patch implements proper QML module registration for both CMake and qmake. It also tries to address all qmllint warnings, which results in a major refactoring, because the current approach with Loaders provides a lot of unqualified access warnings. The new approach uses StackLayout to switch between different pages. Task-number: QTBUG-111972 Pick-to: 6.5 6.5.0 Change-Id: Icc0122deebe63af16dd53c47690f2dc9fb88c919 Reviewed-by: Juha Vuolle <juha.vuolle@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
-rw-r--r--examples/bluetooth/heartrate-game/App.qml98
-rw-r--r--examples/bluetooth/heartrate-game/BluetoothAlarmDialog.qml (renamed from examples/bluetooth/heartrate-game/qml/BluetoothAlarmDialog.qml)0
-rw-r--r--examples/bluetooth/heartrate-game/BottomLine.qml (renamed from examples/bluetooth/heartrate-game/qml/BottomLine.qml)0
-rw-r--r--examples/bluetooth/heartrate-game/CMakeLists.txt74
-rw-r--r--examples/bluetooth/heartrate-game/Connect.qml (renamed from examples/bluetooth/heartrate-game/qml/Connect.qml)68
-rw-r--r--examples/bluetooth/heartrate-game/GameButton.qml (renamed from examples/bluetooth/heartrate-game/qml/GameButton.qml)12
-rw-r--r--examples/bluetooth/heartrate-game/GamePage.qml (renamed from examples/bluetooth/heartrate-game/qml/GamePage.qml)18
-rw-r--r--examples/bluetooth/heartrate-game/GameSettings.qml (renamed from examples/bluetooth/heartrate-game/qml/GameSettings.qml)11
-rw-r--r--examples/bluetooth/heartrate-game/Main.qml71
-rw-r--r--examples/bluetooth/heartrate-game/Measure.qml (renamed from examples/bluetooth/heartrate-game/qml/Measure.qml)93
-rw-r--r--examples/bluetooth/heartrate-game/SplashScreen.qml (renamed from examples/bluetooth/heartrate-game/qml/SplashScreen.qml)19
-rw-r--r--examples/bluetooth/heartrate-game/Stats.qml (renamed from examples/bluetooth/heartrate-game/qml/Stats.qml)17
-rw-r--r--examples/bluetooth/heartrate-game/StatsLabel.qml (renamed from examples/bluetooth/heartrate-game/qml/StatsLabel.qml)1
-rw-r--r--examples/bluetooth/heartrate-game/TitleBar.qml (renamed from examples/bluetooth/heartrate-game/qml/TitleBar.qml)32
-rw-r--r--examples/bluetooth/heartrate-game/devicehandler.h5
-rw-r--r--examples/bluetooth/heartrate-game/heartrate-game.pro32
-rw-r--r--examples/bluetooth/heartrate-game/images.qrc7
-rw-r--r--examples/bluetooth/heartrate-game/images/bt_off_to_on.png (renamed from examples/bluetooth/heartrate-game/qml/images/bt_off_to_on.png)bin6143 -> 6143 bytes
-rw-r--r--examples/bluetooth/heartrate-game/images/heart.png (renamed from examples/bluetooth/heartrate-game/qml/images/heart.png)bin2664 -> 2664 bytes
-rw-r--r--examples/bluetooth/heartrate-game/images/logo.png (renamed from examples/bluetooth/heartrate-game/qml/images/logo.png)bin31915 -> 31915 bytes
-rw-r--r--examples/bluetooth/heartrate-game/main.cpp6
-rw-r--r--examples/bluetooth/heartrate-game/qml.qrc18
-rw-r--r--examples/bluetooth/heartrate-game/qml/App.qml83
-rw-r--r--examples/bluetooth/heartrate-game/qml/main.qml63
-rw-r--r--examples/bluetooth/heartrate-game/qml/qmldir1
-rw-r--r--examples/bluetooth/heartrate-game/qmldir15
26 files changed, 383 insertions, 361 deletions
diff --git a/examples/bluetooth/heartrate-game/App.qml b/examples/bluetooth/heartrate-game/App.qml
new file mode 100644
index 00000000..98633c98
--- /dev/null
+++ b/examples/bluetooth/heartrate-game/App.qml
@@ -0,0 +1,98 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtQuick.Layouts
+import HeartRateGame
+
+Item {
+ id: app
+
+ required property ConnectionHandler connectionHandler
+ required property DeviceFinder deviceFinder
+ required property DeviceHandler deviceHandler
+
+ anchors.fill: parent
+ opacity: 0.0
+
+ Behavior on opacity {
+ NumberAnimation {
+ duration: 500
+ }
+ }
+
+ property int __currentIndex: 0
+
+ TitleBar {
+ id: titleBar
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ currentIndex: app.__currentIndex
+
+ onTitleClicked: (index) => {
+ if (index < app.__currentIndex)
+ app.__currentIndex = index
+ }
+ }
+
+ StackLayout {
+ id: pageStack
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.top: titleBar.bottom
+ anchors.bottom: parent.bottom
+ currentIndex: app.__currentIndex
+
+ Connect {
+ connectionHandler: app.connectionHandler
+ deviceFinder: app.deviceFinder
+ deviceHandler: app.deviceHandler
+
+ onShowMeasurePage: app.__currentIndex = 1
+ }
+ Measure {
+ id: measurePage
+ deviceHandler: app.deviceHandler
+
+ onShowStatsPage: app.__currentIndex = 2
+ }
+ Stats {
+ deviceHandler: app.deviceHandler
+ }
+
+ onCurrentIndexChanged: {
+ if (currentIndex === 0)
+ measurePage.close()
+ }
+ }
+
+ BluetoothAlarmDialog {
+ id: btAlarmDialog
+ anchors.fill: parent
+ visible: !app.connectionHandler.alive
+ }
+
+ Keys.onReleased: (event) => {
+ switch (event.key) {
+ case Qt.Key_Escape:
+ case Qt.Key_Back:
+ {
+ if (app.__currentIndex > 0) {
+ app.__currentIndex = app.__currentIndex - 1
+ event.accepted = true
+ } else {
+ Qt.quit()
+ }
+ break
+ }
+ default:
+ break
+ }
+ }
+
+ Component.onCompleted: {
+ forceActiveFocus()
+ app.opacity = 1.0
+ }
+}
diff --git a/examples/bluetooth/heartrate-game/qml/BluetoothAlarmDialog.qml b/examples/bluetooth/heartrate-game/BluetoothAlarmDialog.qml
index 93f4a3cd..93f4a3cd 100644
--- a/examples/bluetooth/heartrate-game/qml/BluetoothAlarmDialog.qml
+++ b/examples/bluetooth/heartrate-game/BluetoothAlarmDialog.qml
diff --git a/examples/bluetooth/heartrate-game/qml/BottomLine.qml b/examples/bluetooth/heartrate-game/BottomLine.qml
index caebc307..caebc307 100644
--- a/examples/bluetooth/heartrate-game/qml/BottomLine.qml
+++ b/examples/bluetooth/heartrate-game/BottomLine.qml
diff --git a/examples/bluetooth/heartrate-game/CMakeLists.txt b/examples/bluetooth/heartrate-game/CMakeLists.txt
index 0d2a7c84..ac680cc2 100644
--- a/examples/bluetooth/heartrate-game/CMakeLists.txt
+++ b/examples/bluetooth/heartrate-game/CMakeLists.txt
@@ -15,11 +15,6 @@ find_package(Qt6 REQUIRED COMPONENTS Bluetooth Core Gui Qml Quick)
qt_standard_project_setup(REQUIRES 6.5)
qt_add_executable(heartrate-game
- bluetoothbaseclass.cpp bluetoothbaseclass.h
- connectionhandler.cpp connectionhandler.h
- devicefinder.cpp devicefinder.h
- devicehandler.cpp devicehandler.h
- deviceinfo.cpp deviceinfo.h
heartrate-global.h
main.cpp
)
@@ -37,10 +32,37 @@ target_link_libraries(heartrate-game PRIVATE
Qt::Quick
)
+set_source_files_properties(GameSettings.qml PROPERTIES
+ QT_QML_SINGLETON_TYPE TRUE
+)
+
qt_add_qml_module(heartrate-game
- URI Shared
+ URI HeartRateGame
VERSION 1.0
- NO_RESOURCE_TARGET_PATH
+ SOURCES
+ bluetoothbaseclass.cpp bluetoothbaseclass.h
+ connectionhandler.cpp connectionhandler.h
+ devicefinder.cpp devicefinder.h
+ devicehandler.cpp devicehandler.h
+ deviceinfo.cpp deviceinfo.h
+ QML_FILES
+ App.qml
+ BluetoothAlarmDialog.qml
+ BottomLine.qml
+ Connect.qml
+ GameButton.qml
+ GamePage.qml
+ GameSettings.qml
+ Measure.qml
+ SplashScreen.qml
+ Stats.qml
+ StatsLabel.qml
+ TitleBar.qml
+ Main.qml
+ RESOURCES
+ images/bt_off_to_on.png
+ images/heart.png
+ images/logo.png
)
if (APPLE)
@@ -57,44 +79,6 @@ if (APPLE)
endif()
endif()
-# Resources:
-set(qml_resource_files
- "qml/App.qml"
- "qml/BluetoothAlarmDialog.qml"
- "qml/BottomLine.qml"
- "qml/Connect.qml"
- "qml/GameButton.qml"
- "qml/GamePage.qml"
- "qml/GameSettings.qml"
- "qml/Measure.qml"
- "qml/SplashScreen.qml"
- "qml/Stats.qml"
- "qml/StatsLabel.qml"
- "qml/TitleBar.qml"
- "qml/main.qml"
- "qml/qmldir"
-)
-
-qt6_add_resources(heartrate-game "qml"
- PREFIX
- "/"
- FILES
- ${qml_resource_files}
-)
-
-set(images_resource_files
- "qml/images/bt_off_to_on.png"
- "qml/images/heart.png"
- "qml/images/logo.png"
-)
-
-qt6_add_resources(heartrate-game "images"
- PREFIX
- "/"
- FILES
- ${images_resource_files}
-)
-
install(TARGETS heartrate-game
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
diff --git a/examples/bluetooth/heartrate-game/qml/Connect.qml b/examples/bluetooth/heartrate-game/Connect.qml
index 40f25310..8582411d 100644
--- a/examples/bluetooth/heartrate-game/qml/Connect.qml
+++ b/examples/bluetooth/heartrate-game/Connect.qml
@@ -1,10 +1,18 @@
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+pragma ComponentBehavior: Bound
import QtQuick
-import Shared
+import HeartRateGame
GamePage {
+ id: connectPage
+
+ required property ConnectionHandler connectionHandler
+ required property DeviceFinder deviceFinder
+ required property DeviceHandler deviceHandler
+
+ signal showMeasurePage
errorMessage: deviceFinder.error
infoMessage: deviceFinder.info
@@ -12,17 +20,16 @@ GamePage {
Rectangle {
id: viewContainer
anchors.top: parent.top
- anchors.bottom:
- // only BlueZ platform has address type selection
- connectionHandler.requiresAddressType ? addressTypeButton.top : searchButton.top
- anchors.topMargin: GameSettings.fieldMargin + messageHeight
+ // only BlueZ platform has address type selection
+ anchors.bottom: connectPage.connectionHandler.requiresAddressType ? addressTypeButton.top
+ : searchButton.top
+ anchors.topMargin: GameSettings.fieldMargin + connectPage.messageHeight
anchors.bottomMargin: GameSettings.fieldMargin
anchors.horizontalCenter: parent.horizontalCenter
- width: parent.width - GameSettings.fieldMargin*2
+ width: parent.width - GameSettings.fieldMargin * 2
color: GameSettings.viewColor
radius: GameSettings.buttonRadius
-
Text {
id: title
width: parent.width
@@ -34,40 +41,43 @@ GamePage {
text: qsTr("FOUND DEVICES")
BottomLine {
- height: 1;
+ height: 1
width: parent.width
color: "#898989"
}
}
-
ListView {
id: devices
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.top: title.bottom
- model: deviceFinder.devices
+ model: connectPage.deviceFinder.devices
clip: true
delegate: Rectangle {
id: box
- height:GameSettings.fieldHeight * 1.2
+
+ required property int index
+ required property var modelData
+
+ height: GameSettings.fieldHeight * 1.2
width: devices.width
color: index % 2 === 0 ? GameSettings.delegate1Color : GameSettings.delegate2Color
MouseArea {
- anchors.fill: parent
+ anchors.fill: parent
onClicked: {
- deviceFinder.connectToService(modelData.deviceAddress);
- app.showPage("Measure.qml")
+ connectPage.deviceFinder.connectToService(box.modelData.deviceAddress)
+ connectPage.showMeasurePage()
}
}
Text {
id: device
font.pixelSize: GameSettings.smallFontSize
- text: modelData.deviceName
+ text: box.modelData.deviceName
anchors.top: parent.top
anchors.topMargin: parent.height * 0.1
anchors.leftMargin: parent.height * 0.1
@@ -78,7 +88,7 @@ GamePage {
Text {
id: deviceAddress
font.pixelSize: GameSettings.smallFontSize
- text: modelData.deviceAddress
+ text: box.modelData.deviceAddress
anchors.bottom: parent.bottom
anchors.bottomMargin: parent.height * 0.1
anchors.rightMargin: parent.height * 0.1
@@ -93,23 +103,31 @@ GamePage {
id: addressTypeButton
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: searchButton.top
- anchors.bottomMargin: GameSettings.fieldMargin*0.5
+ anchors.bottomMargin: GameSettings.fieldMargin * 0.5
width: viewContainer.width
height: GameSettings.fieldHeight
- visible: connectionHandler.requiresAddressType // only required on BlueZ
+ visible: connectPage.connectionHandler.requiresAddressType // only required on BlueZ
state: "public"
- onClicked: state == "public" ? state = "random" : state = "public"
+ onClicked: state === "public" ? state = "random" : state = "public"
states: [
State {
name: "public"
- PropertyChanges { target: addressTypeText; text: qsTr("Public Address") }
- PropertyChanges { target: deviceHandler; addressType: AddressType.PublicAddress }
+ PropertyChanges {
+ addressTypeText.text: qsTr("Public Address")
+ }
+ PropertyChanges {
+ connectPage.deviceHandler.addressType: DeviceHandler.PublicAddress
+ }
},
State {
name: "random"
- PropertyChanges { target: addressTypeText; text: qsTr("Random Address") }
- PropertyChanges { target: deviceHandler; addressType: AddressType.RandomAddress }
+ PropertyChanges {
+ addressTypeText.text: qsTr("Random Address")
+ }
+ PropertyChanges {
+ connectPage.deviceHandler.addressType: DeviceHandler.RandomAddress
+ }
}
]
@@ -128,8 +146,8 @@ GamePage {
anchors.bottomMargin: GameSettings.fieldMargin
width: viewContainer.width
height: GameSettings.fieldHeight
- enabled: !deviceFinder.scanning
- onClicked: deviceFinder.startSearch()
+ enabled: !connectPage.deviceFinder.scanning
+ onClicked: connectPage.deviceFinder.startSearch()
Text {
anchors.centerIn: parent
diff --git a/examples/bluetooth/heartrate-game/qml/GameButton.qml b/examples/bluetooth/heartrate-game/GameButton.qml
index 3ce9d66f..8e876010 100644
--- a/examples/bluetooth/heartrate-game/qml/GameButton.qml
+++ b/examples/bluetooth/heartrate-game/GameButton.qml
@@ -2,7 +2,6 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
import QtQuick
-import "."
Rectangle {
id: button
@@ -14,10 +13,9 @@ Rectangle {
property color pressedColor: GameSettings.buttonPressedColor
property color disabledColor: GameSettings.disabledButtonColor
- signal clicked()
+ signal clicked
- function checkColor()
- {
+ function checkColor() {
if (!button.enabled) {
button.color = disabledColor
} else {
@@ -31,10 +29,10 @@ Rectangle {
MouseArea {
id: mouseArea
anchors.fill: parent
- onPressed: checkColor()
- onReleased: checkColor()
+ onPressed: button.checkColor()
+ onReleased: button.checkColor()
onClicked: {
- checkColor()
+ button.checkColor()
button.clicked()
}
}
diff --git a/examples/bluetooth/heartrate-game/qml/GamePage.qml b/examples/bluetooth/heartrate-game/GamePage.qml
index 25a5bb3d..249f9418 100644
--- a/examples/bluetooth/heartrate-game/qml/GamePage.qml
+++ b/examples/bluetooth/heartrate-game/GamePage.qml
@@ -2,10 +2,9 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
import QtQuick
-import "."
Item {
- anchors.fill: parent
+ id: page
property string errorMessage: ""
property string infoMessage: ""
@@ -13,23 +12,14 @@ Item {
property bool hasError: errorMessage != ""
property bool hasInfo: infoMessage != ""
- function init()
- {
- }
-
- function close()
- {
- app.prevPage()
- }
-
Rectangle {
id: msg
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
height: GameSettings.fieldHeight
- color: hasError ? GameSettings.errorColor : GameSettings.infoColor
- visible: hasError || hasInfo
+ color: page.hasError ? GameSettings.errorColor : GameSettings.infoColor
+ visible: page.hasError || page.hasInfo
Text {
id: error
@@ -40,7 +30,7 @@ Item {
font.pixelSize: GameSettings.smallFontSize
fontSizeMode: Text.Fit
color: GameSettings.textColor
- text: hasError ? errorMessage : infoMessage
+ text: page.hasError ? page.errorMessage : page.infoMessage
}
}
}
diff --git a/examples/bluetooth/heartrate-game/qml/GameSettings.qml b/examples/bluetooth/heartrate-game/GameSettings.qml
index f265b73c..0fe85460 100644
--- a/examples/bluetooth/heartrate-game/qml/GameSettings.qml
+++ b/examples/bluetooth/heartrate-game/GameSettings.qml
@@ -41,14 +41,11 @@ Item {
property real buttonRadius: buttonHeight * 0.1
// Some help functions
- function widthForHeight(h, ss)
- {
- return h/ss.height * ss.width;
+ function widthForHeight(h, ss) {
+ return h / ss.height * ss.width
}
- function heightForWidth(w, ss)
- {
- return w/ss.width * ss.height;
+ function heightForWidth(w, ss) {
+ return w / ss.width * ss.height
}
-
}
diff --git a/examples/bluetooth/heartrate-game/Main.qml b/examples/bluetooth/heartrate-game/Main.qml
new file mode 100644
index 00000000..e26f9b00
--- /dev/null
+++ b/examples/bluetooth/heartrate-game/Main.qml
@@ -0,0 +1,71 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+pragma ComponentBehavior: Bound
+import QtQuick
+import QtQuick.Window
+import HeartRateGame
+
+Window {
+ id: wroot
+ visible: true
+ width: 720 * .7
+ height: 1240 * .7
+ title: qsTr("HeartRateGame")
+ color: GameSettings.backgroundColor
+
+ required property ConnectionHandler connectionHandler
+ required property DeviceFinder deviceFinder
+ required property DeviceHandler deviceHandler
+
+ Component.onCompleted: {
+ GameSettings.wWidth = Qt.binding(function () {
+ return width
+ })
+ GameSettings.wHeight = Qt.binding(function () {
+ return height
+ })
+ }
+
+ Loader {
+ id: splashLoader
+ anchors.fill: parent
+ asynchronous: false
+ visible: true
+
+ sourceComponent: SplashScreen {
+ appIsReady: appLoader.status === Loader.Ready
+ onReadyChanged: {
+ if (ready) {
+ appLoader.visible = true
+ splashLoader.visible = false
+ splashLoader.active = false
+ }
+ }
+ }
+
+ onStatusChanged: {
+ if (status === Loader.Ready)
+ appLoader.active = true
+ }
+ }
+
+ Loader {
+ id: appLoader
+ anchors.fill: parent
+ active: false
+ asynchronous: true
+ visible: false
+
+ sourceComponent: App {
+ connectionHandler: wroot.connectionHandler
+ deviceFinder: wroot.deviceFinder
+ deviceHandler: wroot.deviceHandler
+ }
+
+ onStatusChanged: {
+ if (status === Loader.Error)
+ Qt.quit()
+ }
+ }
+}
diff --git a/examples/bluetooth/heartrate-game/qml/Measure.qml b/examples/bluetooth/heartrate-game/Measure.qml
index c434d511..48e84e76 100644
--- a/examples/bluetooth/heartrate-game/qml/Measure.qml
+++ b/examples/bluetooth/heartrate-game/Measure.qml
@@ -2,49 +2,49 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
import QtQuick
+import HeartRateGame
GamePage {
id: measurePage
+ required property DeviceHandler deviceHandler
+
errorMessage: deviceHandler.error
infoMessage: deviceHandler.info
- property real __timeCounter: 0;
+ property real __timeCounter: 0
property real __maxTimeCount: 60
property string relaxText: qsTr("Relax!\nWhen you are ready, press Start. You have %1s time to increase heartrate so much as possible.\nGood luck!").arg(__maxTimeCount)
- function close()
- {
- deviceHandler.stopMeasurement();
- deviceHandler.disconnectService();
- app.prevPage();
+ signal showStatsPage
+
+ function close() {
+ deviceHandler.stopMeasurement()
+ deviceHandler.disconnectService()
}
- function start()
- {
+ function start() {
if (!deviceHandler.measuring) {
- __timeCounter = 0;
+ __timeCounter = 0
deviceHandler.startMeasurement()
}
}
- function stop()
- {
- if (deviceHandler.measuring) {
+ function stop() {
+ if (deviceHandler.measuring)
deviceHandler.stopMeasurement()
- }
- app.showPage("Stats.qml")
+ measurePage.showStatsPage()
}
Timer {
id: measureTimer
interval: 1000
- running: deviceHandler.measuring
+ running: measurePage.deviceHandler.measuring
repeat: true
onTriggered: {
- __timeCounter++;
- if (__timeCounter >= __maxTimeCount)
+ measurePage.__timeCounter++
+ if (measurePage.__timeCounter >= measurePage.__maxTimeCount)
measurePage.stop()
}
}
@@ -56,22 +56,23 @@ GamePage {
Rectangle {
id: circle
anchors.horizontalCenter: parent.horizontalCenter
- width: Math.min(measurePage.width, measurePage.height-GameSettings.fieldHeight*4) - 2*GameSettings.fieldMargin
+ width: Math.min(measurePage.width, measurePage.height - GameSettings.fieldHeight * 4)
+ - 2 * GameSettings.fieldMargin
height: width
- radius: width*0.5
+ radius: width * 0.5
color: GameSettings.viewColor
Text {
id: hintText
anchors.centerIn: parent
- anchors.verticalCenterOffset: -parent.height*0.1
+ anchors.verticalCenterOffset: -parent.height * 0.1
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
width: parent.width * 0.8
height: parent.height * 0.6
wrapMode: Text.WordWrap
text: measurePage.relaxText
- visible: !deviceHandler.measuring
+ visible: !measurePage.deviceHandler.measuring
color: GameSettings.textColor
fontSizeMode: Text.Fit
minimumPixelSize: 10
@@ -81,33 +82,33 @@ GamePage {
Text {
id: text
anchors.centerIn: parent
- anchors.verticalCenterOffset: -parent.height*0.15
+ anchors.verticalCenterOffset: -parent.height * 0.15
font.pixelSize: parent.width * 0.45
- text: deviceHandler.hr
- visible: deviceHandler.measuring
+ text: measurePage.deviceHandler.hr
+ visible: measurePage.deviceHandler.measuring
color: GameSettings.textColor
}
Item {
id: minMaxContainer
anchors.horizontalCenter: parent.horizontalCenter
- width: parent.width*0.7
+ width: parent.width * 0.7
height: parent.height * 0.15
anchors.bottom: parent.bottom
- anchors.bottomMargin: parent.height*0.16
- visible: deviceHandler.measuring
+ anchors.bottomMargin: parent.height * 0.16
+ visible: measurePage.deviceHandler.measuring
Text {
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
- text: deviceHandler.minHR
+ text: measurePage.deviceHandler.minHR
color: GameSettings.textColor
font.pixelSize: GameSettings.hugeFontSize
Text {
anchors.left: parent.left
anchors.bottom: parent.top
- font.pixelSize: parent.font.pixelSize*0.8
+ font.pixelSize: parent.font.pixelSize * 0.8
color: parent.color
text: "MIN"
}
@@ -116,14 +117,14 @@ GamePage {
Text {
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
- text: deviceHandler.maxHR
+ text: measurePage.deviceHandler.maxHR
color: GameSettings.textColor
font.pixelSize: GameSettings.hugeFontSize
Text {
anchors.right: parent.right
anchors.bottom: parent.top
- font.pixelSize: parent.font.pixelSize*0.8
+ font.pixelSize: parent.font.pixelSize * 0.8
color: parent.color
text: "MAX"
}
@@ -140,13 +141,25 @@ GamePage {
smooth: true
antialiasing: true
- SequentialAnimation{
+ SequentialAnimation {
id: heartAnim
- running: deviceHandler.alive
+ running: measurePage.deviceHandler.alive
loops: Animation.Infinite
alwaysRunToEnd: true
- PropertyAnimation { target: heart; property: "scale"; to: 1.2; duration: 500; easing.type: Easing.InQuad }
- PropertyAnimation { target: heart; property: "scale"; to: 1.0; duration: 500; easing.type: Easing.OutQuad }
+ PropertyAnimation {
+ target: heart
+ property: "scale"
+ to: 1.2
+ duration: 500
+ easing.type: Easing.InQuad
+ }
+ PropertyAnimation {
+ target: heart
+ property: "scale"
+ to: 1.0
+ duration: 500
+ easing.type: Easing.OutQuad
+ }
}
}
}
@@ -163,13 +176,15 @@ GamePage {
height: parent.height
radius: parent.radius
color: GameSettings.sliderColor
- width: Math.min(1.0,__timeCounter / __maxTimeCount) * parent.width
+ width: Math.min(
+ 1.0,
+ measurePage.__timeCounter / measurePage.__maxTimeCount) * parent.width
}
Text {
anchors.centerIn: parent
color: "gray"
- text: (__maxTimeCount - __timeCounter).toFixed(0) + " s"
+ text: (measurePage.__maxTimeCount - measurePage.__timeCounter).toFixed(0) + " s"
font.pixelSize: GameSettings.bigFontSize
}
}
@@ -182,10 +197,10 @@ GamePage {
anchors.bottomMargin: GameSettings.fieldMargin
width: circle.width
height: GameSettings.fieldHeight
- enabled: !deviceHandler.measuring
+ enabled: !measurePage.deviceHandler.measuring
radius: GameSettings.buttonRadius
- onClicked: start()
+ onClicked: measurePage.start()
Text {
anchors.centerIn: parent
diff --git a/examples/bluetooth/heartrate-game/qml/SplashScreen.qml b/examples/bluetooth/heartrate-game/SplashScreen.qml
index 23f71f08..2f9ac1b3 100644
--- a/examples/bluetooth/heartrate-game/qml/SplashScreen.qml
+++ b/examples/bluetooth/heartrate-game/SplashScreen.qml
@@ -2,33 +2,20 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
import QtQuick
-import "."
+import HeartRateGame
Item {
id: root
- anchors.fill: parent
property bool appIsReady: false
property bool splashIsReady: false
-
property bool ready: appIsReady && splashIsReady
- onReadyChanged: if (ready) readyToGo();
- signal readyToGo()
-
- function appReady()
- {
- appIsReady = true
- }
-
- function errorInLoadingApp()
- {
- Qt.quit()
- }
+ anchors.fill: parent
Image {
anchors.centerIn: parent
- width: Math.min(parent.height, parent.width)*0.6
+ width: Math.min(parent.height, parent.width) * 0.6
height: GameSettings.heightForWidth(width, sourceSize)
source: "images/logo.png"
}
diff --git a/examples/bluetooth/heartrate-game/qml/Stats.qml b/examples/bluetooth/heartrate-game/Stats.qml
index b818e85e..22cdd536 100644
--- a/examples/bluetooth/heartrate-game/qml/Stats.qml
+++ b/examples/bluetooth/heartrate-game/Stats.qml
@@ -2,8 +2,12 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
import QtQuick
+import HeartRateGame
GamePage {
+ id: statsPage
+
+ required property DeviceHandler deviceHandler
Column {
anchors.centerIn: parent
@@ -18,9 +22,9 @@ GamePage {
Text {
anchors.horizontalCenter: parent.horizontalCenter
- font.pixelSize: GameSettings.giganticFontSize*3
+ font.pixelSize: GameSettings.giganticFontSize * 3
color: GameSettings.textColor
- text: (deviceHandler.maxHR - deviceHandler.minHR).toFixed(0)
+ text: (statsPage.deviceHandler.maxHR - statsPage.deviceHandler.minHR).toFixed(0)
}
Item {
@@ -30,23 +34,22 @@ GamePage {
StatsLabel {
title: qsTr("MIN")
- value: deviceHandler.minHR.toFixed(0)
+ value: statsPage.deviceHandler.minHR.toFixed(0)
}
StatsLabel {
title: qsTr("MAX")
- value: deviceHandler.maxHR.toFixed(0)
+ value: statsPage.deviceHandler.maxHR.toFixed(0)
}
StatsLabel {
title: qsTr("AVG")
- value: deviceHandler.average.toFixed(1)
+ value: statsPage.deviceHandler.average.toFixed(1)
}
-
StatsLabel {
title: qsTr("CALORIES")
- value: deviceHandler.calories.toFixed(3)
+ value: statsPage.deviceHandler.calories.toFixed(3)
}
}
}
diff --git a/examples/bluetooth/heartrate-game/qml/StatsLabel.qml b/examples/bluetooth/heartrate-game/StatsLabel.qml
index cd5cda5b..0ea4249a 100644
--- a/examples/bluetooth/heartrate-game/qml/StatsLabel.qml
+++ b/examples/bluetooth/heartrate-game/StatsLabel.qml
@@ -2,7 +2,6 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
import QtQuick
-import "."
Item {
height: GameSettings.fieldHeight
diff --git a/examples/bluetooth/heartrate-game/qml/TitleBar.qml b/examples/bluetooth/heartrate-game/TitleBar.qml
index b7de77c4..016a4435 100644
--- a/examples/bluetooth/heartrate-game/qml/TitleBar.qml
+++ b/examples/bluetooth/heartrate-game/TitleBar.qml
@@ -1,50 +1,54 @@
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+pragma ComponentBehavior: Bound
import QtQuick
-Rectangle {
+Rectangle {
id: titleBar
- anchors.top: parent.top
- anchors.left: parent.left
- anchors.right: parent.right
- height: GameSettings.fieldHeight
- color: GameSettings.viewColor
property var __titles: ["CONNECT", "MEASURE", "STATS"]
property int currentIndex: 0
signal titleClicked(int index)
+ height: GameSettings.fieldHeight
+ color: GameSettings.viewColor
+
Repeater {
model: 3
Text {
+ id: caption
+ required property int index
width: titleBar.width / 3
height: titleBar.height
x: index * width
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
- text: __titles[index]
+ text: titleBar.__titles[index]
font.pixelSize: GameSettings.tinyFontSize
- color: titleBar.currentIndex === index ? GameSettings.textColor : GameSettings.disabledTextColor
+ color: titleBar.currentIndex === index ? GameSettings.textColor
+ : GameSettings.disabledTextColor
MouseArea {
anchors.fill: parent
- onClicked: titleClicked(index)
+ onClicked: titleBar.titleClicked(caption.index)
}
}
}
-
Item {
anchors.bottom: parent.bottom
width: parent.width / 3
height: parent.height
- x: currentIndex * width
+ x: titleBar.currentIndex * width
- BottomLine{}
+ BottomLine {}
- Behavior on x { NumberAnimation { duration: 200 } }
+ Behavior on x {
+ NumberAnimation {
+ duration: 200
+ }
+ }
}
-
}
diff --git a/examples/bluetooth/heartrate-game/devicehandler.h b/examples/bluetooth/heartrate-game/devicehandler.h
index fd670f43..eb155e5b 100644
--- a/examples/bluetooth/heartrate-game/devicehandler.h
+++ b/examples/bluetooth/heartrate-game/devicehandler.h
@@ -13,7 +13,7 @@
#include <QtCore/qlist.h>
#include <QtCore/qtimer.h>
-#include <QtQmlIntegration/qqmlintegration.h>
+#include <QtQml/qqmlregistration.h>
class DeviceInfo;
@@ -31,8 +31,7 @@ class DeviceHandler : public BluetoothBaseClass
Q_PROPERTY(float calories READ calories NOTIFY statsChanged)
Q_PROPERTY(AddressType addressType READ addressType WRITE setAddressType)
- QML_NAMED_ELEMENT(AddressType)
- QML_UNCREATABLE("Enum is not a type")
+ QML_ELEMENT
public:
enum class AddressType {
diff --git a/examples/bluetooth/heartrate-game/heartrate-game.pro b/examples/bluetooth/heartrate-game/heartrate-game.pro
index f55053b4..65be3382 100644
--- a/examples/bluetooth/heartrate-game/heartrate-game.pro
+++ b/examples/bluetooth/heartrate-game/heartrate-game.pro
@@ -2,10 +2,9 @@ TEMPLATE = app
TARGET = heartrate-game
QT += qml quick bluetooth
-CONFIG += c++11
CONFIG += qmltypes
-QML_IMPORT_NAME = Shared
+QML_IMPORT_NAME = HeartRateGame
QML_IMPORT_MAJOR_VERSION = 1
HEADERS += \
@@ -23,14 +22,31 @@ SOURCES += main.cpp \
devicehandler.cpp \
bluetoothbaseclass.cpp
+qml_resources.files = \
+ qmldir \
+ App.qml \
+ BluetoothAlarmDialog.qml \
+ BottomLine.qml \
+ Connect.qml \
+ GameButton.qml \
+ GamePage.qml \
+ GameSettings.qml \
+ Measure.qml \
+ SplashScreen.qml \
+ Stats.qml \
+ StatsLabel.qml \
+ TitleBar.qml \
+ Main.qml \
+ images/bt_off_to_on.png \
+ images/heart.png \
+ images/logo.png
+
+qml_resources.prefix = /qt/qml/HeartRateGame
+
+RESOURCES = qml_resources
+
ios: QMAKE_INFO_PLIST = Info.plist
macos: QMAKE_INFO_PLIST = ../shared/Info.qmake.macos.plist
-RESOURCES += qml.qrc \
- images.qrc
-
-# Additional import path used to resolve QML modules in Qt Creator's code model
-QML_IMPORT_PATH =
-
target.path = $$[QT_INSTALL_EXAMPLES]/bluetooth/heartrate-game
INSTALLS += target
diff --git a/examples/bluetooth/heartrate-game/images.qrc b/examples/bluetooth/heartrate-game/images.qrc
deleted file mode 100644
index 38058de0..00000000
--- a/examples/bluetooth/heartrate-game/images.qrc
+++ /dev/null
@@ -1,7 +0,0 @@
-<RCC>
- <qresource prefix="/">
- <file>qml/images/logo.png</file>
- <file>qml/images/bt_off_to_on.png</file>
- <file>qml/images/heart.png</file>
- </qresource>
-</RCC>
diff --git a/examples/bluetooth/heartrate-game/qml/images/bt_off_to_on.png b/examples/bluetooth/heartrate-game/images/bt_off_to_on.png
index 5ea1f3f0..5ea1f3f0 100644
--- a/examples/bluetooth/heartrate-game/qml/images/bt_off_to_on.png
+++ b/examples/bluetooth/heartrate-game/images/bt_off_to_on.png
Binary files differ
diff --git a/examples/bluetooth/heartrate-game/qml/images/heart.png b/examples/bluetooth/heartrate-game/images/heart.png
index f2b3c0a3..f2b3c0a3 100644
--- a/examples/bluetooth/heartrate-game/qml/images/heart.png
+++ b/examples/bluetooth/heartrate-game/images/heart.png
Binary files differ
diff --git a/examples/bluetooth/heartrate-game/qml/images/logo.png b/examples/bluetooth/heartrate-game/images/logo.png
index ea0af7e0..ea0af7e0 100644
--- a/examples/bluetooth/heartrate-game/qml/images/logo.png
+++ b/examples/bluetooth/heartrate-game/images/logo.png
Binary files differ
diff --git a/examples/bluetooth/heartrate-game/main.cpp b/examples/bluetooth/heartrate-game/main.cpp
index 11573512..50f891e1 100644
--- a/examples/bluetooth/heartrate-game/main.cpp
+++ b/examples/bluetooth/heartrate-game/main.cpp
@@ -48,9 +48,9 @@ int main(int argc, char *argv[])
{u"deviceHandler"_s, QVariant::fromValue(&deviceHandler)}
});
- engine.load(QUrl(u"qrc:/qml/main.qml"_s));
- if (engine.rootObjects().isEmpty())
- return -1;
+ QObject::connect(&engine, &QQmlApplicationEngine::objectCreationFailed, &app,
+ []() { QCoreApplication::exit(1); }, Qt::QueuedConnection);
+ engine.loadFromModule("HeartRateGame", "Main");
return app.exec();
}
diff --git a/examples/bluetooth/heartrate-game/qml.qrc b/examples/bluetooth/heartrate-game/qml.qrc
deleted file mode 100644
index bab96355..00000000
--- a/examples/bluetooth/heartrate-game/qml.qrc
+++ /dev/null
@@ -1,18 +0,0 @@
-<RCC>
- <qresource prefix="/">
- <file>qml/BluetoothAlarmDialog.qml</file>
- <file>qml/main.qml</file>
- <file>qml/SplashScreen.qml</file>
- <file>qml/GameSettings.qml</file>
- <file>qml/App.qml</file>
- <file>qml/TitleBar.qml</file>
- <file>qml/Connect.qml</file>
- <file>qml/Measure.qml</file>
- <file>qml/Stats.qml</file>
- <file>qml/GameButton.qml</file>
- <file>qml/GamePage.qml</file>
- <file>qml/BottomLine.qml</file>
- <file>qml/StatsLabel.qml</file>
- <file>qml/qmldir</file>
- </qresource>
-</RCC>
diff --git a/examples/bluetooth/heartrate-game/qml/App.qml b/examples/bluetooth/heartrate-game/qml/App.qml
deleted file mode 100644
index 1eb53202..00000000
--- a/examples/bluetooth/heartrate-game/qml/App.qml
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-
-import QtQuick
-
-Item {
- id: app
- anchors.fill: parent
- opacity: 0.0
-
- Behavior on opacity { NumberAnimation { duration: 500 } }
-
- property var lastPages: []
- property int __currentIndex: 0
-
- function init()
- {
- opacity = 1.0
- showPage("Connect.qml")
- }
-
- function prevPage()
- {
- lastPages.pop()
- pageLoader.setSource(lastPages[lastPages.length-1])
- __currentIndex = lastPages.length-1;
- }
-
- function showPage(name)
- {
- lastPages.push(name)
- pageLoader.setSource(name)
- __currentIndex = lastPages.length-1;
- }
-
- TitleBar {
- id: titleBar
- currentIndex: __currentIndex
-
- onTitleClicked: (index) => {
- if (index < __currentIndex)
- pageLoader.item.close()
- }
- }
-
- Loader {
- id: pageLoader
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.top: titleBar.bottom
- anchors.bottom: parent.bottom
-
- onStatusChanged: {
- if (status === Loader.Ready)
- {
- pageLoader.item.init();
- pageLoader.item.forceActiveFocus()
- }
- }
- }
-
- Keys.onReleased: (event) => {
- switch (event.key) {
- case Qt.Key_Escape:
- case Qt.Key_Back: {
- if (__currentIndex > 0) {
- pageLoader.item.close()
- event.accepted = true
- } else {
- Qt.quit()
- }
- break;
- }
- default: break;
- }
- }
-
- BluetoothAlarmDialog {
- id: btAlarmDialog
- anchors.fill: parent
- visible: !connectionHandler.alive
- }
-}
diff --git a/examples/bluetooth/heartrate-game/qml/main.qml b/examples/bluetooth/heartrate-game/qml/main.qml
deleted file mode 100644
index 44d824fa..00000000
--- a/examples/bluetooth/heartrate-game/qml/main.qml
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-
-import QtQuick
-import QtQuick.Window
-import "."
-import Shared
-
-Window {
- id: wroot
- visible: true
- width: 720 * .7
- height: 1240 * .7
- title: qsTr("HeartRateGame")
- color: GameSettings.backgroundColor
-
- required property ConnectionHandler connectionHandler
- required property DeviceFinder deviceFinder
- required property AddressType deviceHandler
-
- Component.onCompleted: {
- GameSettings.wWidth = Qt.binding(function() {return width})
- GameSettings.wHeight = Qt.binding(function() {return height})
- }
-
- Loader {
- id: splashLoader
- anchors.fill: parent
- source: "SplashScreen.qml"
- asynchronous: false
- visible: true
-
- onStatusChanged: {
- if (status === Loader.Ready) {
- appLoader.setSource("App.qml");
- }
- }
- }
-
- Connections {
- target: splashLoader.item
- function onReadyToGo() {
- appLoader.visible = true
- appLoader.item.init()
- splashLoader.visible = false
- splashLoader.setSource("")
- appLoader.item.forceActiveFocus();
- }
- }
-
- Loader {
- id: appLoader
- anchors.fill: parent
- visible: false
- asynchronous: true
- onStatusChanged: {
- if (status === Loader.Ready)
- splashLoader.item.appReady()
- if (status === Loader.Error)
- splashLoader.item.errorInLoadingApp();
- }
- }
-}
diff --git a/examples/bluetooth/heartrate-game/qml/qmldir b/examples/bluetooth/heartrate-game/qml/qmldir
deleted file mode 100644
index 5e0d2b54..00000000
--- a/examples/bluetooth/heartrate-game/qml/qmldir
+++ /dev/null
@@ -1 +0,0 @@
-singleton GameSettings 1.0 GameSettings.qml
diff --git a/examples/bluetooth/heartrate-game/qmldir b/examples/bluetooth/heartrate-game/qmldir
new file mode 100644
index 00000000..161e6bab
--- /dev/null
+++ b/examples/bluetooth/heartrate-game/qmldir
@@ -0,0 +1,15 @@
+module HeartRateGame
+prefer :/qt/qml/HeartRateGame/
+App 1.0 App.qml
+BluetoothAlarmDialog 1.0 BluetoothAlarmDialog.qml
+BottomLine 1.0 BottomLine.qml
+Connect 1.0 Connect.qml
+GameButton 1.0 GameButton.qml
+GamePage 1.0 GamePage.qml
+singleton GameSettings 1.0 GameSettings.qml
+Measure 1.0 Measure.qml
+SplashScreen 1.0 SplashScreen.qml
+Stats 1.0 Stats.qml
+StatsLabel 1.0 StatsLabel.qml
+TitleBar 1.0 TitleBar.qml
+Main 1.0 Main.qml