summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvan Solovev <ivan.solovev@qt.io>2023-03-23 15:20:40 +0100
committerIvan Solovev <ivan.solovev@qt.io>2023-03-28 09:37:11 +0200
commitca681cd1b3a51d10106a1287a98c5590100feb6a (patch)
tree2bbba40b16f2b7862368f59544d2577eedf06cfe
parentb72c83bfecc5d259ef0fcf20cb05d2464a7fd0ab (diff)
downloadqtconnectivity-ca681cd1b3a51d10106a1287a98c5590100feb6a.tar.gz
LowEnergyScanner example: refactor QML code
Adapt the QML code to modern guidelines: * properly create a QML module in CMake and qmake * use versionless imports * convert the Device class to QML_SINGLETON instead of injecting it into the root context * use QQmlApplicationEngine::loadFromModule() to start the app The last change actually requires that we use Window instead of a Rectangle for the Main.qml page. This, in turn, breaks the pre-existing Loader logic, because every time we load the Main.qml page, a new window is created. Apart from that, we get unqualified access warnings from qmllint, because loader is accessed from every QML element, while it is only defined in the Main.qml. To fix that, we introduce a new page for device scan, and convert Main.qml to use StackLayout instead of a Loader to avoid unqualified access warnings. While on it, also fix other qmllint warnings and re-format the QML files. Task-number: QTBUG-111972 Pick-to: 6.5 6.5.0 Change-Id: Ia83cda08bf9547f5c2e335cb090c15d776f1b6ad Reviewed-by: Juha Vuolle <juha.vuolle@qt.io>
-rw-r--r--examples/bluetooth/lowenergyscanner/CMakeLists.txt48
-rw-r--r--examples/bluetooth/lowenergyscanner/Characteristics.qml (renamed from examples/bluetooth/lowenergyscanner/assets/Characteristics.qml)49
-rw-r--r--examples/bluetooth/lowenergyscanner/Devices.qml (renamed from examples/bluetooth/lowenergyscanner/assets/main.qml)69
-rw-r--r--examples/bluetooth/lowenergyscanner/Dialog.qml (renamed from examples/bluetooth/lowenergyscanner/assets/Dialog.qml)22
-rw-r--r--examples/bluetooth/lowenergyscanner/Header.qml (renamed from examples/bluetooth/lowenergyscanner/assets/Header.qml)5
-rw-r--r--examples/bluetooth/lowenergyscanner/Label.qml (renamed from examples/bluetooth/lowenergyscanner/assets/Label.qml)2
-rw-r--r--examples/bluetooth/lowenergyscanner/Main.qml31
-rw-r--r--examples/bluetooth/lowenergyscanner/Menu.qml (renamed from examples/bluetooth/lowenergyscanner/assets/Menu.qml)11
-rw-r--r--examples/bluetooth/lowenergyscanner/Services.qml (renamed from examples/bluetooth/lowenergyscanner/assets/Services.qml)56
-rw-r--r--examples/bluetooth/lowenergyscanner/characteristicinfo.h4
-rw-r--r--examples/bluetooth/lowenergyscanner/device.h9
-rw-r--r--examples/bluetooth/lowenergyscanner/deviceinfo.h5
-rw-r--r--examples/bluetooth/lowenergyscanner/lowenergyscanner.pro35
-rw-r--r--examples/bluetooth/lowenergyscanner/main.cpp15
-rw-r--r--examples/bluetooth/lowenergyscanner/qmldir11
-rw-r--r--examples/bluetooth/lowenergyscanner/resources.qrc12
-rw-r--r--examples/bluetooth/lowenergyscanner/serviceinfo.h5
17 files changed, 233 insertions, 156 deletions
diff --git a/examples/bluetooth/lowenergyscanner/CMakeLists.txt b/examples/bluetooth/lowenergyscanner/CMakeLists.txt
index 534c8f15..6f5f5692 100644
--- a/examples/bluetooth/lowenergyscanner/CMakeLists.txt
+++ b/examples/bluetooth/lowenergyscanner/CMakeLists.txt
@@ -4,8 +4,6 @@
cmake_minimum_required(VERSION 3.16)
project(lowenergyscanner LANGUAGES CXX)
-set(CMAKE_AUTOMOC ON)
-
if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
@@ -14,12 +12,10 @@ set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/bluetooth/lowenergyscanner")
find_package(Qt6 REQUIRED COMPONENTS Bluetooth Core Gui Quick)
+qt_standard_project_setup(REQUIRES 6.5)
+
qt_add_executable(lowenergyscanner
- characteristicinfo.cpp characteristicinfo.h
- device.cpp device.h
- deviceinfo.cpp deviceinfo.h
main.cpp
- serviceinfo.cpp serviceinfo.h
)
set_target_properties(lowenergyscanner PROPERTIES
@@ -27,10 +23,6 @@ set_target_properties(lowenergyscanner PROPERTIES
MACOSX_BUNDLE TRUE
)
-target_include_directories(lowenergyscanner PUBLIC
- .
-)
-
target_link_libraries(lowenergyscanner PUBLIC
Qt::Bluetooth
Qt::Core
@@ -52,23 +44,25 @@ if (APPLE)
endif()
endif()
-# Resources:
-set(resources_resource_files
- "assets/Characteristics.qml"
- "assets/Dialog.qml"
- "assets/Header.qml"
- "assets/Label.qml"
- "assets/Menu.qml"
- "assets/Services.qml"
- "assets/busy_dark.png"
- "assets/main.qml"
-)
-
-qt6_add_resources(lowenergyscanner "resources"
- PREFIX
- "/"
- FILES
- ${resources_resource_files}
+qt_add_qml_module(lowenergyscanner
+ URI Scanner
+ VERSION 1.0
+ SOURCES
+ characteristicinfo.cpp characteristicinfo.h
+ device.cpp device.h
+ deviceinfo.cpp deviceinfo.h
+ serviceinfo.cpp serviceinfo.h
+ QML_FILES
+ Characteristics.qml
+ Devices.qml
+ Dialog.qml
+ Header.qml
+ Label.qml
+ Main.qml
+ Menu.qml
+ Services.qml
+ RESOURCES
+ assets/busy_dark.png
)
install(TARGETS lowenergyscanner
diff --git a/examples/bluetooth/lowenergyscanner/assets/Characteristics.qml b/examples/bluetooth/lowenergyscanner/Characteristics.qml
index 39721401..5d140bd1 100644
--- a/examples/bluetooth/lowenergyscanner/assets/Characteristics.qml
+++ b/examples/bluetooth/lowenergyscanner/Characteristics.qml
@@ -1,10 +1,16 @@
// Copyright (C) 2013 BlackBerry Limited. All rights reserved.
-// Copyright (C) 2017 The Qt Company Ltd.
+// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-import QtQuick 2.0
+pragma ComponentBehavior: Bound
+import QtQuick
Rectangle {
+ id: characteristicsPage
+
+ signal showServices
+ signal showDevices
+
width: 300
height: 600
@@ -18,11 +24,11 @@ Rectangle {
id: info
anchors.centerIn: parent
visible: true
- dialogText: "Scanning for characteristics...";
+ dialogText: "Scanning for characteristics..."
}
Connections {
- target: device
+ target: Device
function onCharacteristicsUpdated() {
menu.menuText = "Back"
if (characteristicview.count === 0) {
@@ -35,7 +41,7 @@ Rectangle {
}
function onDisconnected() {
- pageLoader.source = "main.qml"
+ characteristicsPage.showDevices()
}
}
@@ -46,11 +52,12 @@ Rectangle {
anchors.top: header.bottom
anchors.bottom: menu.top
- model: device.characteristicList
+ model: Device.characteristicList
delegate: Rectangle {
- id: characteristicbox
- height:300
+ required property var modelData
+ id: box
+ height: 300
width: characteristicview.width
color: "lightsteelblue"
border.width: 2
@@ -59,23 +66,23 @@ Rectangle {
Label {
id: characteristicName
- textContent: modelData.characteristicName
+ textContent: box.modelData.characteristicName
anchors.top: parent.top
anchors.topMargin: 5
}
Label {
id: characteristicUuid
- font.pointSize: characteristicName.font.pointSize*0.7
- textContent: modelData.characteristicUuid
+ font.pointSize: characteristicName.font.pointSize * 0.7
+ textContent: box.modelData.characteristicUuid
anchors.top: characteristicName.bottom
anchors.topMargin: 5
}
Label {
id: characteristicValue
- font.pointSize: characteristicName.font.pointSize*0.7
- textContent: ("Value: " + modelData.characteristicValue)
+ font.pointSize: characteristicName.font.pointSize * 0.7
+ textContent: ("Value: " + box.modelData.characteristicValue)
anchors.bottom: characteristicHandle.top
horizontalAlignment: Text.AlignHCenter
anchors.topMargin: 5
@@ -83,16 +90,16 @@ Rectangle {
Label {
id: characteristicHandle
- font.pointSize: characteristicName.font.pointSize*0.7
- textContent: ("Handlers: " + modelData.characteristicHandle)
+ font.pointSize: characteristicName.font.pointSize * 0.7
+ textContent: ("Handlers: " + box.modelData.characteristicHandle)
anchors.bottom: characteristicPermission.top
anchors.topMargin: 5
}
Label {
id: characteristicPermission
- font.pointSize: characteristicName.font.pointSize*0.7
- textContent: modelData.characteristicPermission
+ font.pointSize: characteristicName.font.pointSize * 0.7
+ textContent: box.modelData.characteristicPermission
anchors.bottom: parent.bottom
anchors.topMargin: 5
anchors.bottomMargin: 5
@@ -104,11 +111,11 @@ Rectangle {
id: menu
anchors.bottom: parent.bottom
menuWidth: parent.width
- menuText: device.update
- menuHeight: (parent.height/6)
+ menuText: Device.update
+ menuHeight: (parent.height / 6)
onButtonClick: {
- pageLoader.source = "Services.qml"
- device.update = "Back"
+ characteristicsPage.showServices()
+ Device.update = "Back"
}
}
}
diff --git a/examples/bluetooth/lowenergyscanner/assets/main.qml b/examples/bluetooth/lowenergyscanner/Devices.qml
index 2dc92a63..594e6b7d 100644
--- a/examples/bluetooth/lowenergyscanner/assets/main.qml
+++ b/examples/bluetooth/lowenergyscanner/Devices.qml
@@ -1,17 +1,22 @@
// Copyright (C) 2013 BlackBerry Limited. All rights reserved.
-// Copyright (C) 2017 The Qt Company Ltd.
+// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+pragma ComponentBehavior: Bound
import QtQuick
Rectangle {
- id: back
+ id: devicesPage
+
+ property bool deviceState: Device.state
+ signal showServices
+
width: 300
height: 600
- property bool deviceState: device.state
+
onDeviceStateChanged: {
- if (!device.state)
- info.visible = false;
+ if (!Device.state)
+ info.visible = false
}
Header {
@@ -33,11 +38,12 @@ Rectangle {
anchors.top: header.bottom
anchors.bottom: connectToggle.top
- model: device.devicesList
+ model: Device.devicesList
delegate: Rectangle {
+ required property var modelData
id: box
- height:100
+ height: 100
width: theListView.width
color: "lightsteelblue"
border.width: 2
@@ -45,29 +51,29 @@ Rectangle {
radius: 5
Component.onCompleted: {
- info.visible = false;
- header.headerText = "Select a device";
+ info.visible = false
+ header.headerText = "Select a device"
}
MouseArea {
anchors.fill: parent
onClicked: {
- device.scanServices(modelData.deviceAddress);
- pageLoader.source = "Services.qml"
+ Device.scanServices(box.modelData.deviceAddress)
+ showServices()
}
}
Label {
id: deviceName
- textContent: modelData.deviceName
+ textContent: box.modelData.deviceName
anchors.top: parent.top
anchors.topMargin: 5
}
Label {
id: deviceAddress
- textContent: modelData.deviceAddress
- font.pointSize: deviceName.font.pointSize*0.7
+ textContent: box.modelData.deviceAddress
+ font.pointSize: deviceName.font.pointSize * 0.7
anchors.bottom: box.bottom
anchors.bottomMargin: 5
}
@@ -79,37 +85,30 @@ Rectangle {
menuWidth: parent.width
anchors.bottom: menu.top
- menuText: { if (device.devicesList.length)
- visible = true
- else
- visible = false
- if (device.useRandomAddress)
- "Address type: Random"
- else
- "Address type: Public"
+ menuText: {
+ visible = Device.devicesList.length > 0
+ if (Device.useRandomAddress)
+ return "Address type: Random"
+ else
+ return "Address type: Public"
}
- onButtonClick: device.useRandomAddress = !device.useRandomAddress;
+ onButtonClick: Device.useRandomAddress = !Device.useRandomAddress
}
Menu {
id: menu
anchors.bottom: parent.bottom
menuWidth: parent.width
- menuHeight: (parent.height/6)
- menuText: device.update
+ menuHeight: (parent.height / 6)
+ menuText: Device.update
onButtonClick: {
- device.startDeviceDiscovery();
- // if startDeviceDiscovery() failed device.state is not set
- if (device.state) {
- info.dialogText = "Searching...";
- info.visible = true;
+ Device.startDeviceDiscovery()
+ // if startDeviceDiscovery() failed Device.state is not set
+ if (Device.state) {
+ info.dialogText = "Searching..."
+ info.visible = true
}
}
}
-
- Loader {
- id: pageLoader
- anchors.fill: parent
- }
}
diff --git a/examples/bluetooth/lowenergyscanner/assets/Dialog.qml b/examples/bluetooth/lowenergyscanner/Dialog.qml
index 5c3e23a7..75e82642 100644
--- a/examples/bluetooth/lowenergyscanner/assets/Dialog.qml
+++ b/examples/bluetooth/lowenergyscanner/Dialog.qml
@@ -1,10 +1,11 @@
// Copyright (C) 2013 BlackBerry Limited. All rights reserved.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-import QtQuick 2.0
+import QtQuick
Rectangle {
- width: parent.width/3*2
+ id: dialog
+ width: parent.width / 3 * 2
height: dialogTextId.height + background.height + 20
z: 50
property string dialogText: ""
@@ -18,11 +19,11 @@ Rectangle {
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
anchors.horizontalCenter: parent.horizontalCenter
- anchors.top: parent.top;
+ anchors.top: parent.top
anchors.topMargin: 10
elide: Text.ElideMiddle
- text: dialogText
+ text: dialog.dialogText
color: "#363636"
wrapMode: Text.Wrap
}
@@ -30,13 +31,18 @@ Rectangle {
Image {
id: background
- width:20
- height:20
+ width: 20
+ height: 20
anchors.top: dialogTextId.bottom
anchors.horizontalCenter: dialogTextId.horizontalCenter
visible: parent.busyImage
- source: "busy_dark.png"
+ source: "assets/busy_dark.png"
fillMode: Image.PreserveAspectFit
- NumberAnimation on rotation { duration: 3000; from:0; to: 360; loops: Animation.Infinite}
+ NumberAnimation on rotation {
+ duration: 3000
+ from: 0
+ to: 360
+ loops: Animation.Infinite
+ }
}
}
diff --git a/examples/bluetooth/lowenergyscanner/assets/Header.qml b/examples/bluetooth/lowenergyscanner/Header.qml
index 51649be0..c95385dd 100644
--- a/examples/bluetooth/lowenergyscanner/assets/Header.qml
+++ b/examples/bluetooth/lowenergyscanner/Header.qml
@@ -1,9 +1,10 @@
// Copyright (C) 2013 BlackBerry Limited. All rights reserved.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-import QtQuick 2.0
+import QtQuick
Rectangle {
+ id: header
width: parent.width
height: 70
border.width: 1
@@ -15,7 +16,7 @@ Rectangle {
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
anchors.fill: parent
- text: headerText
+ text: header.headerText
font.bold: true
font.pointSize: 20
elide: Text.ElideMiddle
diff --git a/examples/bluetooth/lowenergyscanner/assets/Label.qml b/examples/bluetooth/lowenergyscanner/Label.qml
index 664aa9f4..e3115674 100644
--- a/examples/bluetooth/lowenergyscanner/assets/Label.qml
+++ b/examples/bluetooth/lowenergyscanner/Label.qml
@@ -1,7 +1,7 @@
// Copyright (C) 2013 BlackBerry Limited. All rights reserved.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-import QtQuick 2.0
+import QtQuick
Text {
property string textContent: ""
diff --git a/examples/bluetooth/lowenergyscanner/Main.qml b/examples/bluetooth/lowenergyscanner/Main.qml
new file mode 100644
index 00000000..88600bac
--- /dev/null
+++ b/examples/bluetooth/lowenergyscanner/Main.qml
@@ -0,0 +1,31 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtQuick.Layouts
+
+Window {
+ id: main
+
+ width: 300
+ height: 600
+ visible: true
+
+ StackLayout {
+ id: pagesLayout
+ anchors.fill: parent
+ currentIndex: 0
+
+ Devices {
+ onShowServices: pagesLayout.currentIndex = 1
+ }
+ Services {
+ onShowDevices: pagesLayout.currentIndex = 0
+ onShowCharacteristics: pagesLayout.currentIndex = 2
+ }
+ Characteristics {
+ onShowDevices: pagesLayout.currentIndex = 0
+ onShowServices: pagesLayout.currentIndex = 1
+ }
+ }
+}
diff --git a/examples/bluetooth/lowenergyscanner/assets/Menu.qml b/examples/bluetooth/lowenergyscanner/Menu.qml
index 33511267..ef69c895 100644
--- a/examples/bluetooth/lowenergyscanner/assets/Menu.qml
+++ b/examples/bluetooth/lowenergyscanner/Menu.qml
@@ -1,15 +1,16 @@
// Copyright (C) 2013 BlackBerry Limited. All rights reserved.
-// Copyright (C) 2017 The Qt Company Ltd.
+// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-import QtQuick 2.0
+import QtQuick
Rectangle {
+ id: menu
property real menuWidth: 100
property real menuHeight: 50
property string menuText: "Search"
- signal buttonClick()
+ signal buttonClick
height: menuHeight
width: menuWidth
@@ -28,7 +29,7 @@ Rectangle {
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
anchors.fill: parent
- text: menuText
+ text: menu.menuText
elide: Text.ElideMiddle
color: "#E3E3E3"
wrapMode: Text.WordWrap
@@ -47,7 +48,7 @@ Rectangle {
}
onClicked: {
- buttonClick()
+ menu.buttonClick()
}
}
}
diff --git a/examples/bluetooth/lowenergyscanner/assets/Services.qml b/examples/bluetooth/lowenergyscanner/Services.qml
index c729674b..4d7fee32 100644
--- a/examples/bluetooth/lowenergyscanner/assets/Services.qml
+++ b/examples/bluetooth/lowenergyscanner/Services.qml
@@ -1,10 +1,16 @@
// Copyright (C) 2013 BlackBerry Limited. All rights reserved.
-// Copyright (C) 2017 The Qt Company Ltd.
+// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-import QtQuick 2.0
+pragma ComponentBehavior: Bound
+import QtQuick
Rectangle {
+ id: servicesPage
+
+ signal showCharacteristics
+ signal showDevices
+
width: 300
height: 600
@@ -12,9 +18,9 @@ Rectangle {
// Loading this page may take longer than QLEController
// stopping with an error, go back and readjust this view
// based on controller errors
- if (device.controllerError) {
- info.visible = false;
- menu.menuText = device.update
+ if (Device.controllerError) {
+ info.visible = false
+ menu.menuText = Device.update
}
}
@@ -28,20 +34,20 @@ Rectangle {
id: info
anchors.centerIn: parent
visible: true
- dialogText: "Scanning for services...";
+ dialogText: "Scanning for services..."
}
Connections {
- target: device
+ target: Device
function onServicesUpdated() {
if (servicesview.count === 0)
info.dialogText = "No services found"
else
- info.visible = false;
+ info.visible = false
}
function onDisconnected() {
- pageLoader.source = "main.qml"
+ servicesPage.showDevices()
}
}
@@ -50,38 +56,36 @@ Rectangle {
width: parent.width
anchors.top: header.bottom
anchors.bottom: menu.top
- model: device.servicesList
+ model: Device.servicesList
clip: true
delegate: Rectangle {
- id: servicebox
- height:100
+ required property var modelData
+ id: box
+ height: 100
color: "lightsteelblue"
border.width: 2
border.color: "black"
radius: 5
width: servicesview.width
- Component.onCompleted: {
- info.visible = false
- }
MouseArea {
anchors.fill: parent
onClicked: {
- pageLoader.source = "Characteristics.qml";
- device.connectToService(modelData.serviceUuid);
+ Device.connectToService(box.modelData.serviceUuid)
+ servicesPage.showCharacteristics()
}
}
Label {
id: serviceName
- textContent: modelData.serviceName
+ textContent: box.modelData.serviceName
anchors.top: parent.top
anchors.topMargin: 5
}
Label {
- textContent: modelData.serviceType
+ textContent: box.modelData.serviceType
font.pointSize: serviceName.font.pointSize * 0.5
anchors.top: serviceName.bottom
}
@@ -89,8 +93,8 @@ Rectangle {
Label {
id: serviceUuid
font.pointSize: serviceName.font.pointSize * 0.5
- textContent: modelData.serviceUuid
- anchors.bottom: servicebox.bottom
+ textContent: box.modelData.serviceUuid
+ anchors.bottom: box.bottom
anchors.bottomMargin: 5
}
}
@@ -100,12 +104,12 @@ Rectangle {
id: menu
anchors.bottom: parent.bottom
menuWidth: parent.width
- menuText: device.update
- menuHeight: (parent.height/6)
+ menuText: Device.update
+ menuHeight: (parent.height / 6)
onButtonClick: {
- device.disconnectFromDevice()
- pageLoader.source = "main.qml"
- device.update = "Search"
+ Device.disconnectFromDevice()
+ servicesPage.showDevices()
+ Device.update = "Search"
}
}
}
diff --git a/examples/bluetooth/lowenergyscanner/characteristicinfo.h b/examples/bluetooth/lowenergyscanner/characteristicinfo.h
index 7a258fa7..7e0adbf7 100644
--- a/examples/bluetooth/lowenergyscanner/characteristicinfo.h
+++ b/examples/bluetooth/lowenergyscanner/characteristicinfo.h
@@ -10,6 +10,8 @@
#include <QtCore/qobject.h>
#include <QtCore/qstring.h>
+#include <QtQmlIntegration/qqmlintegration.h>
+
class CharacteristicInfo: public QObject
{
Q_OBJECT
@@ -18,6 +20,8 @@ class CharacteristicInfo: public QObject
Q_PROPERTY(QString characteristicValue READ getValue NOTIFY characteristicChanged)
Q_PROPERTY(QString characteristicPermission READ getPermission NOTIFY characteristicChanged)
+ QML_ANONYMOUS
+
public:
CharacteristicInfo() = default;
CharacteristicInfo(const QLowEnergyCharacteristic &characteristic);
diff --git a/examples/bluetooth/lowenergyscanner/device.h b/examples/bluetooth/lowenergyscanner/device.h
index 6a1d2b9c..ea5d6ed6 100644
--- a/examples/bluetooth/lowenergyscanner/device.h
+++ b/examples/bluetooth/lowenergyscanner/device.h
@@ -16,6 +16,8 @@
#include <QtCore/qobject.h>
#include <QtCore/qvariant.h>
+#include <QtQmlIntegration/qqmlintegration.h>
+
QT_BEGIN_NAMESPACE
class QBluetoothDeviceInfo;
class QBluetoothUuid;
@@ -28,9 +30,14 @@ class Device: public QObject
Q_PROPERTY(QVariant servicesList READ getServices NOTIFY servicesUpdated)
Q_PROPERTY(QVariant characteristicList READ getCharacteristics NOTIFY characteristicsUpdated)
Q_PROPERTY(QString update READ getUpdate WRITE setUpdate NOTIFY updateChanged)
- Q_PROPERTY(bool useRandomAddress READ isRandomAddress WRITE setRandomAddress NOTIFY randomAddressChanged)
+ Q_PROPERTY(bool useRandomAddress READ isRandomAddress WRITE setRandomAddress
+ NOTIFY randomAddressChanged)
Q_PROPERTY(bool state READ state NOTIFY stateChanged)
Q_PROPERTY(bool controllerError READ hasControllerError)
+
+ QML_ELEMENT
+ QML_SINGLETON
+
public:
Device();
~Device();
diff --git a/examples/bluetooth/lowenergyscanner/deviceinfo.h b/examples/bluetooth/lowenergyscanner/deviceinfo.h
index 78854490..94b70465 100644
--- a/examples/bluetooth/lowenergyscanner/deviceinfo.h
+++ b/examples/bluetooth/lowenergyscanner/deviceinfo.h
@@ -10,11 +10,16 @@
#include <QtCore/qlist.h>
#include <QtCore/qobject.h>
+#include <QtQmlIntegration/qqmlintegration.h>
+
class DeviceInfo: public QObject
{
Q_OBJECT
Q_PROPERTY(QString deviceName READ getName NOTIFY deviceChanged)
Q_PROPERTY(QString deviceAddress READ getAddress NOTIFY deviceChanged)
+
+ QML_ANONYMOUS
+
public:
DeviceInfo() = default;
DeviceInfo(const QBluetoothDeviceInfo &d);
diff --git a/examples/bluetooth/lowenergyscanner/lowenergyscanner.pro b/examples/bluetooth/lowenergyscanner/lowenergyscanner.pro
index 31b243ac..54ba3dce 100644
--- a/examples/bluetooth/lowenergyscanner/lowenergyscanner.pro
+++ b/examples/bluetooth/lowenergyscanner/lowenergyscanner.pro
@@ -1,28 +1,45 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+TEMPLATE = app
TARGET = lowenergyscanner
-INCLUDEPATH += .
QT += quick bluetooth
-# Input
+CONFIG += qmltypes
+QML_IMPORT_NAME = Scanner
+QML_IMPORT_MAJOR_VERSION = 1
+
SOURCES += main.cpp \
device.cpp \
deviceinfo.cpp \
serviceinfo.cpp \
characteristicinfo.cpp
-ios: QMAKE_INFO_PLIST = Info.plist
-macos: QMAKE_INFO_PLIST = ../shared/Info.qmake.macos.plist
-
-OTHER_FILES += assets/*.qml
-
HEADERS += \
device.h \
deviceinfo.h \
serviceinfo.h \
characteristicinfo.h
-RESOURCES += \
- resources.qrc
+qml_resources.files = \
+ qmldir \
+ Characteristics.qml \
+ Devices.qml \
+ Dialog.qml \
+ Header.qml \
+ Label.qml \
+ Main.qml \
+ Menu.qml \
+ Services.qml \
+ assets/busy_dark.png
+
+qml_resources.prefix = /qt/qml/Scanner
+
+RESOURCES = qml_resources
+
+ios: QMAKE_INFO_PLIST = Info.plist
+macos: QMAKE_INFO_PLIST = ../shared/Info.qmake.macos.plist
target.path = $$[QT_INSTALL_EXAMPLES]/bluetooth/lowenergyscanner
INSTALLS += target
diff --git a/examples/bluetooth/lowenergyscanner/main.cpp b/examples/bluetooth/lowenergyscanner/main.cpp
index 7fbb8c99..411fac02 100644
--- a/examples/bluetooth/lowenergyscanner/main.cpp
+++ b/examples/bluetooth/lowenergyscanner/main.cpp
@@ -6,20 +6,17 @@
#include <QtCore/qloggingcategory.h>
#include <QtGui/qguiapplication.h>
-#include <QtQml/qqmlcontext.h>
-#include <QtQuick/qquickview.h>
+#include <QtQml/qqmlapplicationengine.h>
int main(int argc, char *argv[])
{
// QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true"));
QGuiApplication app(argc, argv);
- Device d;
- QQuickView view;
- view.rootContext()->setContextProperty("device", &d);
+ QQmlApplicationEngine engine;
+ QObject::connect(&engine, &QQmlApplicationEngine::objectCreationFailed, &app,
+ []() { QCoreApplication::exit(1); }, Qt::QueuedConnection);
+ engine.loadFromModule("Scanner", "Main");
- view.setSource(QUrl("qrc:/assets/main.qml"));
- view.setResizeMode(QQuickView::SizeRootObjectToView);
- view.show();
- return QGuiApplication::exec();
+ return app.exec();
}
diff --git a/examples/bluetooth/lowenergyscanner/qmldir b/examples/bluetooth/lowenergyscanner/qmldir
new file mode 100644
index 00000000..c2f4d141
--- /dev/null
+++ b/examples/bluetooth/lowenergyscanner/qmldir
@@ -0,0 +1,11 @@
+module Scanner
+prefer :/qt/qml/Scanner/
+Characteristics 1.0 Characteristics.qml
+Devices 1.0 Devices.qml
+Dialog 1.0 Dialog.qml
+Header 1.0 Header.qml
+Label 1.0 Label.qml
+Main 1.0 Main.qml
+Menu 1.0 Menu.qml
+Services 1.0 Services.qml
+
diff --git a/examples/bluetooth/lowenergyscanner/resources.qrc b/examples/bluetooth/lowenergyscanner/resources.qrc
deleted file mode 100644
index 4634cf6b..00000000
--- a/examples/bluetooth/lowenergyscanner/resources.qrc
+++ /dev/null
@@ -1,12 +0,0 @@
-<RCC>
- <qresource prefix="/">
- <file>assets/Characteristics.qml</file>
- <file>assets/main.qml</file>
- <file>assets/Menu.qml</file>
- <file>assets/Services.qml</file>
- <file>assets/Header.qml</file>
- <file>assets/Dialog.qml</file>
- <file>assets/Label.qml</file>
- <file>assets/busy_dark.png</file>
- </qresource>
-</RCC>
diff --git a/examples/bluetooth/lowenergyscanner/serviceinfo.h b/examples/bluetooth/lowenergyscanner/serviceinfo.h
index f89b37a0..dfd0b919 100644
--- a/examples/bluetooth/lowenergyscanner/serviceinfo.h
+++ b/examples/bluetooth/lowenergyscanner/serviceinfo.h
@@ -7,6 +7,8 @@
#include <QtCore/qobject.h>
+#include <QtQmlIntegration/qqmlintegration.h>
+
QT_BEGIN_NAMESPACE
class QLowEnergyService;
QT_END_NAMESPACE
@@ -17,6 +19,9 @@ class ServiceInfo: public QObject
Q_PROPERTY(QString serviceName READ getName NOTIFY serviceChanged)
Q_PROPERTY(QString serviceUuid READ getUuid NOTIFY serviceChanged)
Q_PROPERTY(QString serviceType READ getType NOTIFY serviceChanged)
+
+ QML_ANONYMOUS
+
public:
ServiceInfo() = default;
ServiceInfo(QLowEnergyService *service);