diff options
author | Ivan Solovev <ivan.solovev@qt.io> | 2023-03-17 13:53:40 +0100 |
---|---|---|
committer | Ivan Solovev <ivan.solovev@qt.io> | 2023-03-21 12:02:20 +0100 |
commit | 6168203d7c0e8e4df1908a62338b8abdd57855eb (patch) | |
tree | 056982aae0f5be2523e1e071457f62341f28a1a5 /tests | |
parent | 7d20a4fb6a520b13666c8808ae74fb9a43b6532c (diff) |
BtScanner example: move to manual tests
The example mostly shows the usage of
QBluetooth{Device,Service}DiscoveryAgent classes, which is also
illustrated by other examples. Move it, because it's not fully
functional on mobile platforms (because it's widget based).
Do not remove it completely, because it might still be useful
for doing Classic device scan.
Also implement some improvements while on it:
* fix CMakeLists.txt by using qt_standard_project_setup() and PRIVATE
linking
* fix memory leak in DeviceDiscoveryDialog
* rework the code to use Qt parent-child model instead of manually
deleting objects where possible
* fix includes
* fix forward declarations
Task-number: QTBUG-111972
Pick-to: 6.5 6.5.0
Change-Id: Ie4bc9e25ccdda6d5f5de2f57528df349c71cdc12
Reviewed-by: Juha Vuolle <juha.vuolle@qt.io>
Diffstat (limited to 'tests')
-rw-r--r-- | tests/manual/CMakeLists.txt | 1 | ||||
-rw-r--r-- | tests/manual/examples/btscanner/CMakeLists.txt | 52 | ||||
-rw-r--r-- | tests/manual/examples/btscanner/Info.plist | 41 | ||||
-rw-r--r-- | tests/manual/examples/btscanner/btscanner.pro | 24 | ||||
-rw-r--r-- | tests/manual/examples/btscanner/device.cpp | 182 | ||||
-rw-r--r-- | tests/manual/examples/btscanner/device.h | 49 | ||||
-rw-r--r-- | tests/manual/examples/btscanner/device.ui | 118 | ||||
-rw-r--r-- | tests/manual/examples/btscanner/main.cpp | 33 | ||||
-rw-r--r-- | tests/manual/examples/btscanner/service.cpp | 62 | ||||
-rw-r--r-- | tests/manual/examples/btscanner/service.h | 36 | ||||
-rw-r--r-- | tests/manual/examples/btscanner/service.ui | 71 |
11 files changed, 669 insertions, 0 deletions
diff --git a/tests/manual/CMakeLists.txt b/tests/manual/CMakeLists.txt index 2cce14f6..47fdbfb8 100644 --- a/tests/manual/CMakeLists.txt +++ b/tests/manual/CMakeLists.txt @@ -4,5 +4,6 @@ if(TARGET Qt::Bluetooth) add_subdirectory(qlowenergycontroller) add_subdirectory(qlowenergycontroller_peripheral) + add_subdirectory(examples/btscanner) endif() diff --git a/tests/manual/examples/btscanner/CMakeLists.txt b/tests/manual/examples/btscanner/CMakeLists.txt new file mode 100644 index 00000000..61d44dfc --- /dev/null +++ b/tests/manual/examples/btscanner/CMakeLists.txt @@ -0,0 +1,52 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +cmake_minimum_required(VERSION 3.16) +project(btscanner LANGUAGES CXX) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/bluetooth/btscanner") + +find_package(Qt6 REQUIRED COMPONENTS Bluetooth Core Widgets) + +qt_standard_project_setup() + +qt_add_executable(btscanner + device.cpp device.h device.ui + main.cpp + service.cpp service.h service.ui +) + +set_target_properties(btscanner PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) + +if (APPLE) + if (IOS) + set_target_properties(btscanner PROPERTIES + MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/Info.plist" + ) + else() + # Using absolute path for shared plist files is a Ninja bug workaround + get_filename_component(SHARED_PLIST_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../../examples/bluetooth/shared ABSOLUTE) + set_target_properties(btscanner PROPERTIES + MACOSX_BUNDLE_INFO_PLIST "${SHARED_PLIST_DIR}/Info.cmake.macos.plist" + ) + endif() +endif() + +target_link_libraries(btscanner PRIVATE + Qt::Bluetooth + Qt::Core + Qt::Widgets +) + +install(TARGETS btscanner + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/tests/manual/examples/btscanner/Info.plist b/tests/manual/examples/btscanner/Info.plist new file mode 100644 index 00000000..49fd2191 --- /dev/null +++ b/tests/manual/examples/btscanner/Info.plist @@ -0,0 +1,41 @@ +<?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>${PRODUCT_NAME}</string> + <key>CFBundleExecutable</key> + <string>${EXECUTABLE_NAME}</string> + <key>CFBundleIconFile</key> + <string>${ASSETCATALOG_COMPILER_APPICON_NAME}</string> + <key>CFBundleIdentifier</key> + <string>${PRODUCT_BUNDLE_IDENTIFIER}</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>${PRODUCT_NAME}</string> + <key>CFBundlePackageType</key> + <string>APPL</string> + <key>CFBundleShortVersionString</key> + <string>${QMAKE_SHORT_VERSION}</string> + <key>CFBundleSignature</key> + <string>${QMAKE_PKGINFO_TYPEINFO}</string> + <key>CFBundleVersion</key> + <string>${QMAKE_FULL_VERSION}</string> + <key>LSRequiresIPhoneOS</key> + <true/> + <key>MinimumOSVersion</key> + <string>${IPHONEOS_DEPLOYMENT_TARGET}</string> + <key>NSBluetoothAlwaysUsageDescription</key> + <string>Qt's BT scanner wants to access your Bluetooth adapter!</string> + <key>UILaunchStoryboardName</key> + <string>LaunchScreen</string> + <key>UISupportedInterfaceOrientations</key> + <array> + <string>UIInterfaceOrientationPortrait</string> + <string>UIInterfaceOrientationPortraitUpsideDown</string> + <string>UIInterfaceOrientationLandscapeLeft</string> + <string>UIInterfaceOrientationLandscapeRight</string> + </array> +</dict> +</plist> diff --git a/tests/manual/examples/btscanner/btscanner.pro b/tests/manual/examples/btscanner/btscanner.pro new file mode 100644 index 00000000..3ef49969 --- /dev/null +++ b/tests/manual/examples/btscanner/btscanner.pro @@ -0,0 +1,24 @@ +TARGET = btscanner + +QT = core bluetooth widgets +requires(qtConfig(listwidget)) +TEMPLATE = app + +SOURCES = \ + main.cpp \ + device.cpp \ + service.cpp + +ios: QMAKE_INFO_PLIST = Info.plist +macos: QMAKE_INFO_PLIST = ../../../../examples/bluetooth/shared/Info.qmake.macos.plist + +HEADERS = \ + device.h \ + service.h + +FORMS = \ + device.ui \ + service.ui + +target.path = $$[QT_INSTALL_EXAMPLES]/bluetooth/btscanner +INSTALLS += target diff --git a/tests/manual/examples/btscanner/device.cpp b/tests/manual/examples/btscanner/device.cpp new file mode 100644 index 00000000..6d1f775f --- /dev/null +++ b/tests/manual/examples/btscanner/device.cpp @@ -0,0 +1,182 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "device.h" +#include "service.h" +#include "ui_device.h" + +#include <QtBluetooth/qbluetoothaddress.h> +#include <QtBluetooth/qbluetoothdevicediscoveryagent.h> +#include <QtBluetooth/qbluetoothlocaldevice.h> + +#include <QtWidgets/qmenu.h> + +#if QT_CONFIG(permissions) +#include <QtCore/qpermissions.h> +#include <QtWidgets/qmessagebox.h> +#include <QtWidgets/qapplication.h> +#endif // QT_CONFIG(permissions) + +static QColor colorForPairing(QBluetoothLocalDevice::Pairing pairing) +{ + return pairing == QBluetoothLocalDevice::Paired + || pairing == QBluetoothLocalDevice::AuthorizedPaired + ? QColor(Qt::green) : QColor(Qt::red); +} + +DeviceDiscoveryDialog::DeviceDiscoveryDialog(QWidget *parent) : + QDialog(parent), + localDevice(new QBluetoothLocalDevice(this)), + ui(new Ui::DeviceDiscovery) +{ +#ifdef Q_OS_ANDROID + this->setWindowState(Qt::WindowMaximized); +#endif + ui->setupUi(this); + ui->stopScan->setVisible(false); + + // In case of multiple Bluetooth adapters it is possible to set the adapter + // to be used. Example code: + // + // QBluetoothAddress address("XX:XX:XX:XX:XX:XX"); + // discoveryAgent = new QBluetoothDeviceDiscoveryAgent(address, this); + + discoveryAgent = new QBluetoothDeviceDiscoveryAgent(this); + + connect(ui->scan, &QAbstractButton::clicked, this, &DeviceDiscoveryDialog::startScan); + connect(ui->stopScan, &QAbstractButton::clicked, this, &DeviceDiscoveryDialog::stopScan); + + connect(discoveryAgent, &QBluetoothDeviceDiscoveryAgent::deviceDiscovered, + this, &DeviceDiscoveryDialog::addDevice); + connect(discoveryAgent, &QBluetoothDeviceDiscoveryAgent::finished, + this, &DeviceDiscoveryDialog::scanFinished); + + connect(ui->list, &QListWidget::itemActivated, + this, &DeviceDiscoveryDialog::itemActivated); + + connect(localDevice, &QBluetoothLocalDevice::hostModeStateChanged, + this, &DeviceDiscoveryDialog::hostModeStateChanged); + + hostModeStateChanged(localDevice->hostMode()); + // add context menu for devices to be able to pair device + ui->list->setContextMenuPolicy(Qt::CustomContextMenu); + connect(ui->list, &QWidget::customContextMenuRequested, + this, &DeviceDiscoveryDialog::displayPairingMenu); + connect(localDevice, &QBluetoothLocalDevice::pairingFinished, + this, &DeviceDiscoveryDialog::pairingDone); +} + +DeviceDiscoveryDialog::~DeviceDiscoveryDialog() +{ + delete ui; +} + +void DeviceDiscoveryDialog::addDevice(const QBluetoothDeviceInfo &info) +{ + const QString label = info.address().toString() + u' ' + info.name(); + const auto items = ui->list->findItems(label, Qt::MatchExactly); + if (items.isEmpty()) { + QListWidgetItem *item = new QListWidgetItem(label); + QBluetoothLocalDevice::Pairing pairingStatus = localDevice->pairingStatus(info.address()); + item->setForeground(colorForPairing(pairingStatus)); + ui->list->addItem(item); + } +} + +void DeviceDiscoveryDialog::startScan() +{ +#if QT_CONFIG(permissions) + if (qApp->checkPermission(QBluetoothPermission{}) != Qt::PermissionStatus::Granted) { + QMessageBox::warning(this, tr("Missing permission"), + tr("Permission is needed to use Bluetooth. "\ + "Please grant the permission to this "\ + "application in the system settings.")); + return; + } +#endif // QT_CONFIG(permissions) + discoveryAgent->start(); + ui->scan->setVisible(false); + ui->stopScan->setVisible(true); +} + +void DeviceDiscoveryDialog::stopScan() +{ + discoveryAgent->stop(); + scanFinished(); +} + +void DeviceDiscoveryDialog::scanFinished() +{ + ui->scan->setVisible(true); + ui->stopScan->setVisible(false); +} + +void DeviceDiscoveryDialog::itemActivated(QListWidgetItem *item) +{ + const QString text = item->text(); + const auto index = text.indexOf(' '); + if (index == -1) + return; + + QBluetoothAddress address(text.left(index)); + QString name(text.mid(index + 1)); + + ServiceDiscoveryDialog d(name, address); + d.exec(); +} + +void DeviceDiscoveryDialog::on_discoverable_clicked(bool clicked) +{ + if (clicked) + localDevice->setHostMode(QBluetoothLocalDevice::HostDiscoverable); + else + localDevice->setHostMode(QBluetoothLocalDevice::HostConnectable); +} + +void DeviceDiscoveryDialog::on_power_clicked(bool clicked) +{ + if (clicked) + localDevice->powerOn(); + else + localDevice->setHostMode(QBluetoothLocalDevice::HostPoweredOff); +} + +void DeviceDiscoveryDialog::hostModeStateChanged(QBluetoothLocalDevice::HostMode mode) +{ + ui->power->setChecked(mode != QBluetoothLocalDevice::HostPoweredOff); + ui->discoverable->setChecked(mode == QBluetoothLocalDevice::HostDiscoverable); + + const bool on = mode != QBluetoothLocalDevice::HostPoweredOff; + ui->scan->setEnabled(on); + ui->discoverable->setEnabled(on); +} +void DeviceDiscoveryDialog::displayPairingMenu(const QPoint &pos) +{ + if (ui->list->count() == 0) + return; + QMenu menu(this); + QAction *pairAction = menu.addAction("Pair"); + QAction *removePairAction = menu.addAction("Remove Pairing"); + QAction *chosenAction = menu.exec(ui->list->viewport()->mapToGlobal(pos)); + QListWidgetItem *currentItem = ui->list->currentItem(); + + QString text = currentItem->text(); + const auto index = text.indexOf(' '); + if (index == -1) + return; + + QBluetoothAddress address (text.left(index)); + if (chosenAction == pairAction) { + localDevice->requestPairing(address, QBluetoothLocalDevice::Paired); + } else if (chosenAction == removePairAction) { + localDevice->requestPairing(address, QBluetoothLocalDevice::Unpaired); + } +} +void DeviceDiscoveryDialog::pairingDone(const QBluetoothAddress &address, + QBluetoothLocalDevice::Pairing pairing) +{ + const auto items = ui->list->findItems(address.toString(), Qt::MatchContains); + const QColor color = colorForPairing(pairing); + for (auto *item : items) + item->setForeground(color); +} diff --git a/tests/manual/examples/btscanner/device.h b/tests/manual/examples/btscanner/device.h new file mode 100644 index 00000000..389062bb --- /dev/null +++ b/tests/manual/examples/btscanner/device.h @@ -0,0 +1,49 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef DEVICE_H +#define DEVICE_H + +#include <QtBluetooth/qbluetoothlocaldevice.h> + +#include <QtWidgets/qdialog.h> + +QT_BEGIN_NAMESPACE +class QBluetoothAddress; +class QBluetoothDeviceDiscoveryAgent; +class QBluetoothDeviceInfo; +class QListWidgetItem; + +namespace Ui { + class DeviceDiscovery; +} +QT_END_NAMESPACE + +class DeviceDiscoveryDialog : public QDialog +{ + Q_OBJECT + +public: + DeviceDiscoveryDialog(QWidget *parent = nullptr); + ~DeviceDiscoveryDialog(); + +public slots: + void addDevice(const QBluetoothDeviceInfo &info); + void on_power_clicked(bool clicked); + void on_discoverable_clicked(bool clicked); + void displayPairingMenu(const QPoint &pos); + void pairingDone(const QBluetoothAddress &address, QBluetoothLocalDevice::Pairing pairing); +private slots: + void startScan(); + void stopScan(); + void scanFinished(); + void itemActivated(QListWidgetItem *item); + void hostModeStateChanged(QBluetoothLocalDevice::HostMode mode); + +private: + QBluetoothDeviceDiscoveryAgent *discoveryAgent; + QBluetoothLocalDevice *localDevice; + Ui::DeviceDiscovery *ui; +}; + +#endif diff --git a/tests/manual/examples/btscanner/device.ui b/tests/manual/examples/btscanner/device.ui new file mode 100644 index 00000000..fd86a358 --- /dev/null +++ b/tests/manual/examples/btscanner/device.ui @@ -0,0 +1,118 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>DeviceDiscovery</class> + <widget class="QDialog" name="DeviceDiscovery"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>400</width> + <height>411</height> + </rect> + </property> + <property name="windowTitle"> + <string>Bluetooth Scanner</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QListWidget" name="list"/> + </item> + <item> + <widget class="QGroupBox" name="groupBox"> + <property name="title"> + <string>Local Device</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <widget class="QCheckBox" name="power"> + <property name="text"> + <string>Bluetooth Powered On</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="discoverable"> + <property name="text"> + <string>Discoverable</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QPushButton" name="scan"> + <property name="text"> + <string>Scan</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="stopScan"> + <property name="text"> + <string>Stop scan</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="clear"> + <property name="text"> + <string>Clear</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="quit"> + <property name="text"> + <string>Quit</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>quit</sender> + <signal>clicked()</signal> + <receiver>DeviceDiscovery</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>323</x> + <y>275</y> + </hint> + <hint type="destinationlabel"> + <x>396</x> + <y>268</y> + </hint> + </hints> + </connection> + <connection> + <sender>clear</sender> + <signal>clicked()</signal> + <receiver>list</receiver> + <slot>clear()</slot> + <hints> + <hint type="sourcelabel"> + <x>188</x> + <y>276</y> + </hint> + <hint type="destinationlabel"> + <x>209</x> + <y>172</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/tests/manual/examples/btscanner/main.cpp b/tests/manual/examples/btscanner/main.cpp new file mode 100644 index 00000000..8ed2e652 --- /dev/null +++ b/tests/manual/examples/btscanner/main.cpp @@ -0,0 +1,33 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "device.h" + +#include <QtCore/qloggingcategory.h> +#include <QtWidgets/qapplication.h> + +#if QT_CONFIG(permissions) +#include <QtCore/qpermissions.h> +#endif + +int main(int argc, char *argv[]) +{ + // QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true")); + QApplication app(argc, argv); + DeviceDiscoveryDialog d; + + d.show(); + + // Check, and if needed, request a permission to use Bluetooth. +#if QT_CONFIG(permissions) + const auto permissionStatus = app.checkPermission(QBluetoothPermission{}); + if (permissionStatus == Qt::PermissionStatus::Undetermined) { + app.requestPermission(QBluetoothPermission{}, [](const QPermission &){ + }); + } + // Else means either 'Granted' or 'Denied' and both normally must be + // changed using the system's settings application. +#endif // QT_CONFIG(permissions) + + return app.exec(); +} diff --git a/tests/manual/examples/btscanner/service.cpp b/tests/manual/examples/btscanner/service.cpp new file mode 100644 index 00000000..aa6fe43c --- /dev/null +++ b/tests/manual/examples/btscanner/service.cpp @@ -0,0 +1,62 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// Copyright (C) 2013 BlackBerry Limited. All rights reserved. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "service.h" +#include "ui_service.h" + +#include <QtBluetooth/qbluetoothaddress.h> +#include <QtBluetooth/qbluetoothlocaldevice.h> +#include <QtBluetooth/qbluetoothservicediscoveryagent.h> +#include <QtBluetooth/qbluetoothserviceinfo.h> +#include <QtBluetooth/qbluetoothuuid.h> + + +ServiceDiscoveryDialog::ServiceDiscoveryDialog(const QString &name, + const QBluetoothAddress &address, QWidget *parent) + : QDialog(parent), ui(new Ui::ServiceDiscovery) +{ + ui->setupUi(this); + + //Using default Bluetooth adapter + QBluetoothLocalDevice localDevice; + QBluetoothAddress adapterAddress = localDevice.address(); + + // In case of multiple Bluetooth adapters it is possible to + // set which adapter will be used by providing MAC Address. + // Example code: + // + // QBluetoothAddress adapterAddress("XX:XX:XX:XX:XX:XX"); + // discoveryAgent = new QBluetoothServiceDiscoveryAgent(adapterAddress, this); + + discoveryAgent = new QBluetoothServiceDiscoveryAgent(adapterAddress, this); + discoveryAgent->setRemoteAddress(address); + + setWindowTitle(name); + + connect(discoveryAgent, &QBluetoothServiceDiscoveryAgent::serviceDiscovered, + this, &ServiceDiscoveryDialog::addService); + connect(discoveryAgent, &QBluetoothServiceDiscoveryAgent::finished, + ui->status, &QWidget::hide); + + discoveryAgent->start(); +} + +ServiceDiscoveryDialog::~ServiceDiscoveryDialog() +{ + delete ui; +} + +void ServiceDiscoveryDialog::addService(const QBluetoothServiceInfo &info) +{ + if (info.serviceName().isEmpty()) + return; + + QString line = info.serviceName(); + if (!info.serviceDescription().isEmpty()) + line.append("\n\t" + info.serviceDescription()); + if (!info.serviceProvider().isEmpty()) + line.append("\n\t" + info.serviceProvider()); + + ui->list->addItem(line); +} diff --git a/tests/manual/examples/btscanner/service.h b/tests/manual/examples/btscanner/service.h new file mode 100644 index 00000000..1c84f38c --- /dev/null +++ b/tests/manual/examples/btscanner/service.h @@ -0,0 +1,36 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef SERVICE_H +#define SERVICE_H + +#include <QtWidgets/qdialog.h> + +QT_BEGIN_NAMESPACE +class QBluetoothAddress; +class QBluetoothServiceDiscoveryAgent; +class QBluetoothServiceInfo; + +namespace Ui { + class ServiceDiscovery; +} +QT_END_NAMESPACE + +class ServiceDiscoveryDialog : public QDialog +{ + Q_OBJECT + +public: + ServiceDiscoveryDialog(const QString &name, const QBluetoothAddress &address, + QWidget *parent = nullptr); + ~ServiceDiscoveryDialog(); + +public slots: + void addService(const QBluetoothServiceInfo &info); + +private: + QBluetoothServiceDiscoveryAgent *discoveryAgent; + Ui::ServiceDiscovery *ui; +}; + +#endif diff --git a/tests/manual/examples/btscanner/service.ui b/tests/manual/examples/btscanner/service.ui new file mode 100644 index 00000000..4ca12ee0 --- /dev/null +++ b/tests/manual/examples/btscanner/service.ui @@ -0,0 +1,71 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>ServiceDiscovery</class> + <widget class="QDialog" name="ServiceDiscovery"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>539</width> + <height>486</height> + </rect> + </property> + <property name="windowTitle"> + <string>Available Services</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QListWidget" name="list"/> + </item> + <item> + <widget class="QLabel" name="status"> + <property name="text"> + <string>Querying...</string> + </property> + </widget> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="standardButtons"> + <set>QDialogButtonBox::Close</set> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>ServiceDiscovery</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>396</x> + <y>457</y> + </hint> + <hint type="destinationlabel"> + <x>535</x> + <y>443</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>ServiceDiscovery</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>339</x> + <y>464</y> + </hint> + <hint type="destinationlabel"> + <x>535</x> + <y>368</y> + </hint> + </hints> + </connection> + </connections> +</ui> |