diff options
Diffstat (limited to 'examples/bluetooth/btchat')
32 files changed, 502 insertions, 625 deletions
diff --git a/examples/bluetooth/btchat/CMakeLists.txt b/examples/bluetooth/btchat/CMakeLists.txt new file mode 100644 index 00000000..667dc194 --- /dev/null +++ b/examples/bluetooth/btchat/CMakeLists.txt @@ -0,0 +1,66 @@ +# Copyright (C) 2023 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +cmake_minimum_required(VERSION 3.16) +project(btchat LANGUAGES CXX) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/bluetooth/btchat") + +find_package(Qt6 REQUIRED COMPONENTS Bluetooth Core Widgets) + +qt_standard_project_setup() + +qt_add_executable(btchat + chat.cpp chat.h chat.ui + chatclient.cpp chatclient.h + chatserver.cpp chatserver.h + main.cpp + remoteselector.cpp remoteselector.h remoteselector.ui +) + +set(icon_files) +foreach(icon IN ITEMS bluetooth bluetooth_dark send send_dark) + foreach(scale IN ITEMS "" "@2" "@3" "@4") + list(APPEND icon_files "icons/btchat/24x24${scale}/${icon}.png") + endforeach() +endforeach() + +qt_add_resources(btchat "theme" FILES + ${icon_files} + icons/btchat/index.theme +) + +set_target_properties(btchat PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) + +target_link_libraries(btchat PRIVATE + Qt6::Bluetooth + Qt6::Core + Qt6::Widgets +) + +if (APPLE) + # Using absolute path for shared plist files is a Ninja bug workaround + get_filename_component(SHARED_PLIST_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../shared ABSOLUTE) + if (IOS) + set_target_properties(btchat PROPERTIES + MACOSX_BUNDLE_INFO_PLIST "${SHARED_PLIST_DIR}/Info.cmake.ios.plist" + ) + else() + set_target_properties(btchat PROPERTIES + MACOSX_BUNDLE_INFO_PLIST "${SHARED_PLIST_DIR}/Info.cmake.macos.plist" + ) + endif() +endif() + +install(TARGETS btchat + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/examples/bluetooth/btchat/btchat.pro b/examples/bluetooth/btchat/btchat.pro index 9c37dfcf..0d7b5f77 100644 --- a/examples/bluetooth/btchat/btchat.pro +++ b/examples/bluetooth/btchat/btchat.pro @@ -3,7 +3,6 @@ TARGET = btchat QT = core bluetooth widgets requires(qtConfig(listwidget)) -android: QT += androidextras SOURCES = \ main.cpp \ @@ -22,5 +21,31 @@ FORMS = \ chat.ui \ remoteselector.ui +theme_resources.files = \ + icons/btchat/24x24/bluetooth.png \ + icons/btchat/24x24/bluetooth_dark.png \ + icons/btchat/24x24/send.png \ + icons/btchat/24x24/send_dark.png \ + icons/btchat/24x24@2/bluetooth.png \ + icons/btchat/24x24@2/bluetooth_dark.png \ + icons/btchat/24x24@2/send.png \ + icons/btchat/24x24@2/send_dark.png \ + icons/btchat/24x24@3/bluetooth.png \ + icons/btchat/24x24@3/bluetooth_dark.png \ + icons/btchat/24x24@3/send.png \ + icons/btchat/24x24@3/send_dark.png \ + icons/btchat/24x24@4/bluetooth.png \ + icons/btchat/24x24@4/bluetooth_dark.png \ + icons/btchat/24x24@4/send.png \ + icons/btchat/24x24@4/send_dark.png \ + icons/btchat/index.theme + +theme_resources.prefix = / + +RESOURCES += theme_resources + +ios: QMAKE_INFO_PLIST = ../shared/Info.qmake.ios.plist +macos: QMAKE_INFO_PLIST = ../shared/Info.qmake.macos.plist + target.path = $$[QT_INSTALL_EXAMPLES]/bluetooth/btchat INSTALLS += target diff --git a/examples/bluetooth/btchat/chat.cpp b/examples/bluetooth/btchat/chat.cpp index 4cc5f08d..bf794902 100644 --- a/examples/bluetooth/btchat/chat.cpp +++ b/examples/bluetooth/btchat/chat.cpp @@ -1,86 +1,81 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtBluetooth module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause #include "chat.h" -#include "remoteselector.h" -#include "chatserver.h" #include "chatclient.h" +#include "chatserver.h" +#include "remoteselector.h" +#include "ui_chat.h" -#include <QtCore/qdebug.h> +#include <QDebug> -#include <QtBluetooth/qbluetoothdeviceinfo.h> -#include <QtBluetooth/qbluetoothlocaldevice.h> -#include <QtBluetooth/qbluetoothuuid.h> +#include <QBluetoothDeviceInfo> +#include <QBluetoothLocalDevice> +#include <QBluetoothUuid> -#ifdef Q_OS_ANDROID -#include <QtAndroidExtras/QtAndroid> +#include <QGuiApplication> +#include <QStyleHints> + +#if QT_CONFIG(permissions) +#include <QCoreApplication> +#include <QPermissions> + +#include <QMessageBox> #endif -static const QLatin1String serviceUuid("e8e10f95-1a70-4b27-9ccf-02010264e9c8"); +using namespace Qt::StringLiterals; + +static constexpr auto serviceUuid = "e8e10f95-1a70-4b27-9ccf-02010264e9c8"_L1; #ifdef Q_OS_ANDROID -static const QLatin1String reverseUuid("c8e96402-0102-cf9c-274b-701a950fe1e8"); +static constexpr auto reverseUuid = "c8e96402-0102-cf9c-274b-701a950fe1e8"_L1; #endif Chat::Chat(QWidget *parent) - : QDialog(parent), ui(new Ui_Chat) + : QDialog(parent), ui(new Ui::Chat) { //! [Construct UI] ui->setupUi(this); - connect(ui->quitButton, &QPushButton::clicked, this, &Chat::accept); connect(ui->connectButton, &QPushButton::clicked, this, &Chat::connectClicked); connect(ui->sendButton, &QPushButton::clicked, this, &Chat::sendClicked); //! [Construct UI] + ui->connectButton->setFocus(); + + QStyleHints *styleHints = qGuiApp->styleHints(); + updateIcons(styleHints->colorScheme()); + connect(styleHints, &QStyleHints::colorSchemeChanged, this, &Chat::updateIcons); + + initBluetooth(); +} + +Chat::~Chat() +{ + qDeleteAll(clients); + delete ui; +} + +void Chat::initBluetooth() +{ +#if QT_CONFIG(permissions) + QBluetoothPermission permission{}; + switch (qApp->checkPermission(permission)) { + case Qt::PermissionStatus::Undetermined: + qApp->requestPermission(permission, this, &Chat::initBluetooth); + return; + case Qt::PermissionStatus::Denied: + QMessageBox::warning(this, tr("Missing permissions"), + tr("Permissions are needed to use Bluetooth. " + "Please grant the permissions to this " + "application in the system settings.")); + qApp->quit(); + return; + case Qt::PermissionStatus::Granted: + break; // proceed to initialization + } +#endif // QT_CONFIG(permissions) localAdapters = QBluetoothLocalDevice::allDevices(); - if (localAdapters.count() < 2) { + if (localAdapters.size() < 2) { ui->localAdapterBox->setVisible(false); } else { //we ignore more than two adapters @@ -91,8 +86,14 @@ Chat::Chat(QWidget *parent) ui->firstAdapter->setChecked(true); connect(ui->firstAdapter, &QRadioButton::clicked, this, &Chat::newAdapterSelected); connect(ui->secondAdapter, &QRadioButton::clicked, this, &Chat::newAdapterSelected); + } + + // make discoverable + if (!localAdapters.isEmpty()) { QBluetoothLocalDevice adapter(localAdapters.at(0).address()); adapter.setHostMode(QBluetoothLocalDevice::HostDiscoverable); + } else { + qWarning("Local adapter is not found! The application might work incorrectly."); } //! [Create Chat Server] @@ -112,10 +113,13 @@ Chat::Chat(QWidget *parent) //! [Get local device name] } -Chat::~Chat() +void Chat::updateIcons(Qt::ColorScheme scheme) { - qDeleteAll(clients); - delete server; + const QString bluetoothIconName = (scheme == Qt::ColorScheme::Dark) ? u"bluetooth_dark"_s + : u"bluetooth"_s; + const QString sendIconName = (scheme == Qt::ColorScheme::Dark) ? u"send_dark"_s : u"send"_s; + ui->sendButton->setIcon(QIcon::fromTheme(sendIconName)); + ui->connectButton->setIcon(QIcon::fromTheme(bluetoothIconName)); } //! [clientConnected clientDisconnected] @@ -165,7 +169,7 @@ int Chat::adapterFromUserSelection() const void Chat::reactOnSocketError(const QString &error) { - ui->chat->insertPlainText(error); + ui->chat->insertPlainText(QString::fromLatin1("%1\n").arg(error)); } //! [clientDisconnected] @@ -191,23 +195,20 @@ void Chat::connectClicked() RemoteSelector remoteSelector(adapter); #ifdef Q_OS_ANDROID - if (QtAndroid::androidSdkVersion() >= 23) - remoteSelector.startDiscovery(QBluetoothUuid(reverseUuid)); - else - remoteSelector.startDiscovery(QBluetoothUuid(serviceUuid)); + // QTBUG-61392 + Q_UNUSED(serviceUuid); + remoteSelector.startDiscovery(QBluetoothUuid(reverseUuid)); #else remoteSelector.startDiscovery(QBluetoothUuid(serviceUuid)); #endif if (remoteSelector.exec() == QDialog::Accepted) { QBluetoothServiceInfo service = remoteSelector.service(); - qDebug() << "Connecting to service 2" << service.serviceName() + qDebug() << "Connecting to service" << service.serviceName() << "on" << service.device().name(); // Create client - qDebug() << "Going to create client"; ChatClient *client = new ChatClient(this); -qDebug() << "Connecting..."; connect(client, &ChatClient::messageReceived, this, &Chat::showMessage); @@ -218,7 +219,6 @@ qDebug() << "Connecting..."; connect(client, &ChatClient::socketErrorOccurred, this, &Chat::reactOnSocketError); connect(this, &Chat::sendMessage, client, &ChatClient::sendMessage); -qDebug() << "Start client"; client->startClient(service); clients.append(client); @@ -241,12 +241,19 @@ void Chat::sendClicked() ui->sendText->setEnabled(true); ui->sendButton->setEnabled(true); +#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) + // avoid keyboard automatically popping up again on mobile devices + ui->sendButton->setFocus(); +#else + ui->sendText->setFocus(); +#endif } //! [sendClicked] //! [showMessage] void Chat::showMessage(const QString &sender, const QString &message) { + ui->chat->moveCursor(QTextCursor::End); ui->chat->insertPlainText(QString::fromLatin1("%1: %2\n").arg(sender, message)); ui->chat->ensureCursorVisible(); } diff --git a/examples/bluetooth/btchat/chat.h b/examples/bluetooth/btchat/chat.h index e4c81b24..ca5318cc 100644 --- a/examples/bluetooth/btchat/chat.h +++ b/examples/bluetooth/btchat/chat.h @@ -1,60 +1,15 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtBluetooth module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "ui_chat.h" - -#include <QtWidgets/qdialog.h> - -#include <QtBluetooth/qbluetoothhostinfo.h> - -QT_USE_NAMESPACE +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include <QDialog> + +#include <QBluetoothHostInfo> + +QT_BEGIN_NAMESPACE +namespace Ui { + class Chat; +} +QT_END_NAMESPACE class ChatServer; class ChatClient; @@ -85,12 +40,16 @@ private slots: void newAdapterSelected(); + void initBluetooth(); + + void updateIcons(Qt::ColorScheme scheme); + private: int adapterFromUserSelection() const; int currentAdapterIndex = 0; - Ui_Chat *ui; + Ui::Chat *ui; - ChatServer *server; + ChatServer *server = nullptr; QList<ChatClient *> clients; QList<QBluetoothHostInfo> localAdapters; diff --git a/examples/bluetooth/btchat/chat.ui b/examples/bluetooth/btchat/chat.ui index d7829294..bea3d2ee 100644 --- a/examples/bluetooth/btchat/chat.ui +++ b/examples/bluetooth/btchat/chat.ui @@ -50,12 +50,16 @@ <item> <layout class="QHBoxLayout" name="horizontalLayout"> <item> - <widget class="QLineEdit" name="sendText"/> + <widget class="QLineEdit" name="sendText"> + <property name="placeholderText"> + <string>Enter message</string> + </property> + </widget> </item> <item> <widget class="QPushButton" name="sendButton"> <property name="text"> - <string>Send</string> + <string/> </property> <property name="default"> <bool>true</bool> @@ -84,17 +88,26 @@ <property name="text"> <string>Connect</string> </property> + <property name="autoDefault"> + <bool>false</bool> + </property> </widget> </item> + <item> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> </layout> </item> - <item> - <widget class="QPushButton" name="quitButton"> - <property name="text"> - <string>Quit</string> - </property> - </widget> - </item> </layout> </widget> <resources/> diff --git a/examples/bluetooth/btchat/chatclient.cpp b/examples/bluetooth/btchat/chatclient.cpp index cf3e2331..18e100a2 100644 --- a/examples/bluetooth/btchat/chatclient.cpp +++ b/examples/bluetooth/btchat/chatclient.cpp @@ -1,56 +1,14 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtBluetooth module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause #include "chatclient.h" -#include <QtCore/qmetaobject.h> +#include <QMetaEnum> +#include <QMetaObject> + +#include <QBluetoothServiceInfo> + +using namespace Qt::StringLiterals; ChatClient::ChatClient(QObject *parent) : QObject(parent) @@ -77,9 +35,7 @@ void ChatClient::startClient(const QBluetoothServiceInfo &remoteService) connect(socket, &QBluetoothSocket::readyRead, this, &ChatClient::readSocket); connect(socket, &QBluetoothSocket::connected, this, QOverload<>::of(&ChatClient::connected)); connect(socket, &QBluetoothSocket::disconnected, this, &ChatClient::disconnected); - connect(socket, QOverload<QBluetoothSocket::SocketError>::of(&QBluetoothSocket::error), - this, &ChatClient::onSocketErrorOccurred); - + connect(socket, &QBluetoothSocket::errorOccurred, this, &ChatClient::onSocketErrorOccurred); } //! [startClient] @@ -98,7 +54,7 @@ void ChatClient::readSocket() return; while (socket->canReadLine()) { - QByteArray line = socket->readLine(); + QByteArray line = socket->readLine().trimmed(); emit messageReceived(socket->peerName(), QString::fromUtf8(line.constData(), line.length())); } @@ -115,12 +71,12 @@ void ChatClient::sendMessage(const QString &message) void ChatClient::onSocketErrorOccurred(QBluetoothSocket::SocketError error) { - if (error == QBluetoothSocket::NoSocketError) + if (error == QBluetoothSocket::SocketError::NoSocketError) return; QMetaEnum metaEnum = QMetaEnum::fromType<QBluetoothSocket::SocketError>(); - QString errorString = socket->peerName() + QLatin1Char(' ') - + metaEnum.valueToKey(error) + QLatin1String(" occurred"); + QString errorString = socket->peerName() + ' '_L1 + + metaEnum.valueToKey(static_cast<int>(error)) + " occurred"_L1; emit socketErrorOccurred(errorString); } diff --git a/examples/bluetooth/btchat/chatclient.h b/examples/bluetooth/btchat/chatclient.h index 25002f90..da75bf51 100644 --- a/examples/bluetooth/btchat/chatclient.h +++ b/examples/bluetooth/btchat/chatclient.h @@ -1,64 +1,14 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtBluetooth module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause #ifndef CHATCLIENT_H #define CHATCLIENT_H -#include <QtCore/qobject.h> +#include <QObject> -#include <QtBluetooth/qbluetoothserviceinfo.h> -#include <QtBluetooth/qbluetoothsocket.h> +#include <QBluetoothSocket> -QT_FORWARD_DECLARE_CLASS(QBluetoothSocket) - -QT_USE_NAMESPACE +QT_FORWARD_DECLARE_CLASS(QBluetoothServiceInfo) //! [declaration] class ChatClient : public QObject diff --git a/examples/bluetooth/btchat/chatserver.cpp b/examples/bluetooth/btchat/chatserver.cpp index d078a32c..addbc1a9 100644 --- a/examples/bluetooth/btchat/chatserver.cpp +++ b/examples/bluetooth/btchat/chatserver.cpp @@ -1,60 +1,15 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtBluetooth module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause #include "chatserver.h" -#include <QtBluetooth/qbluetoothserver.h> -#include <QtBluetooth/qbluetoothsocket.h> +#include <QBluetoothServer> +#include <QBluetoothSocket> + +using namespace Qt::StringLiterals; //! [Service UUID] -static const QLatin1String serviceUuid("e8e10f95-1a70-4b27-9ccf-02010264e9c8"); +static constexpr auto serviceUuid = "e8e10f95-1a70-4b27-9ccf-02010264e9c8"_L1; //! [Service UUID] ChatServer::ChatServer(QObject *parent) @@ -87,7 +42,7 @@ void ChatServer::startServer(const QBluetoothAddress& localAdapter) QBluetoothServiceInfo::Sequence profileSequence; QBluetoothServiceInfo::Sequence classId; - classId << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::SerialPort)); + classId << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::ServiceClassUuid::SerialPort)); classId << QVariant::fromValue(quint16(0x100)); profileSequence.append(QVariant::fromValue(classId)); serviceInfo.setAttribute(QBluetoothServiceInfo::BluetoothProfileDescriptorList, @@ -95,7 +50,7 @@ void ChatServer::startServer(const QBluetoothAddress& localAdapter) classId.clear(); classId << QVariant::fromValue(QBluetoothUuid(serviceUuid)); - classId << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::SerialPort)); + classId << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::ServiceClassUuid::SerialPort)); serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceClassIds, classId); @@ -111,19 +66,19 @@ void ChatServer::startServer(const QBluetoothAddress& localAdapter) //! [Service UUID set] //! [Service Discoverability] + const auto groupUuid = QBluetoothUuid(QBluetoothUuid::ServiceClassUuid::PublicBrowseGroup); QBluetoothServiceInfo::Sequence publicBrowse; - publicBrowse << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::PublicBrowseGroup)); - serviceInfo.setAttribute(QBluetoothServiceInfo::BrowseGroupList, - publicBrowse); + publicBrowse << QVariant::fromValue(groupUuid); + serviceInfo.setAttribute(QBluetoothServiceInfo::BrowseGroupList, publicBrowse); //! [Service Discoverability] //! [Protocol descriptor list] QBluetoothServiceInfo::Sequence protocolDescriptorList; QBluetoothServiceInfo::Sequence protocol; - protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::L2cap)); + protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::ProtocolUuid::L2cap)); protocolDescriptorList.append(QVariant::fromValue(protocol)); protocol.clear(); - protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::Rfcomm)) + protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::ProtocolUuid::Rfcomm)) << QVariant::fromValue(quint8(rfcommServer->serverPort())); protocolDescriptorList.append(QVariant::fromValue(protocol)); serviceInfo.setAttribute(QBluetoothServiceInfo::ProtocolDescriptorList, @@ -143,6 +98,7 @@ void ChatServer::stopServer() // Close sockets qDeleteAll(clientSockets); + clientNames.clear(); // Close server delete rfcommServer; @@ -155,7 +111,7 @@ void ChatServer::sendMessage(const QString &message) { QByteArray text = message.toUtf8() + '\n'; - for (QBluetoothSocket *socket : qAsConst(clientSockets)) + for (QBluetoothSocket *socket : std::as_const(clientSockets)) socket->write(text); } //! [sendMessage] @@ -168,8 +124,10 @@ void ChatServer::clientConnected() return; connect(socket, &QBluetoothSocket::readyRead, this, &ChatServer::readSocket); - connect(socket, &QBluetoothSocket::disconnected, this, QOverload<>::of(&ChatServer::clientDisconnected)); + connect(socket, &QBluetoothSocket::disconnected, + this, QOverload<>::of(&ChatServer::clientDisconnected)); clientSockets.append(socket); + clientNames[socket] = socket->peerName(); emit clientConnected(socket->peerName()); } //! [clientConnected] @@ -181,9 +139,10 @@ void ChatServer::clientDisconnected() if (!socket) return; - emit clientDisconnected(socket->peerName()); + emit clientDisconnected(clientNames[socket]); clientSockets.removeOne(socket); + clientNames.remove(socket); socket->deleteLater(); } @@ -198,7 +157,7 @@ void ChatServer::readSocket() while (socket->canReadLine()) { QByteArray line = socket->readLine().trimmed(); - emit messageReceived(socket->peerName(), + emit messageReceived(clientNames[socket], QString::fromUtf8(line.constData(), line.length())); } } diff --git a/examples/bluetooth/btchat/chatserver.h b/examples/bluetooth/btchat/chatserver.h index c4191db8..ab60cad6 100644 --- a/examples/bluetooth/btchat/chatserver.h +++ b/examples/bluetooth/btchat/chatserver.h @@ -1,66 +1,17 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtBluetooth module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause #ifndef CHATSERVER_H #define CHATSERVER_H -#include <QtCore/qobject.h> +#include <QObject> -#include <QtBluetooth/qbluetoothaddress.h> -#include <QtBluetooth/qbluetoothserviceinfo.h> +#include <QBluetoothAddress> +#include <QBluetoothServiceInfo> QT_FORWARD_DECLARE_CLASS(QBluetoothServer) QT_FORWARD_DECLARE_CLASS(QBluetoothSocket) -QT_USE_NAMESPACE - //! [declaration] class ChatServer : public QObject { @@ -90,6 +41,7 @@ private: QBluetoothServer *rfcommServer = nullptr; QBluetoothServiceInfo serviceInfo; QList<QBluetoothSocket *> clientSockets; + QMap<QBluetoothSocket *, QString> clientNames; }; //! [declaration] diff --git a/examples/bluetooth/btchat/doc/images/btchat-example.png b/examples/bluetooth/btchat/doc/images/btchat-example.png Binary files differindex 762d49cb..acfadf5c 100644 --- a/examples/bluetooth/btchat/doc/images/btchat-example.png +++ b/examples/bluetooth/btchat/doc/images/btchat-example.png diff --git a/examples/bluetooth/btchat/doc/src/btchat.qdoc b/examples/bluetooth/btchat/doc/src/btchat.qdoc index 42a82bc6..5ad11502 100644 --- a/examples/bluetooth/btchat/doc/src/btchat.qdoc +++ b/examples/bluetooth/btchat/doc/src/btchat.qdoc @@ -1,37 +1,14 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the documentation of the Qt local connectivty modules. -** -** $QT_BEGIN_LICENSE:FDL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Free Documentation License Usage -** Alternatively, this file may be used under the terms of the GNU Free -** Documentation License version 1.3 as published by the Free Software -** Foundation and appearing in the file included in the packaging of -** this file. Please review the following information to ensure -** the GNU Free Documentation License version 1.3 requirements -** will be met: https://www.gnu.org/licenses/fdl-1.3.html. -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only /*! \example btchat - \title Bluetooth Chat Example - \brief An example showing communication through Bluetooth. + \title Bluetooth Chat + \examplecategory {Connectivity} + \brief Shows communication through Bluetooth using RFCOMM protocol. The Bluetooth Chat example shows how to use the \l{Qt Bluetooth} API to communicate - with another application on a remote device using Bluetooth. + with another application on a remote device using Bluetooth RFCOMM protocol. \image btchat-example.png @@ -43,26 +20,28 @@ \section1 Chat Server - The chat server is implemented by the ChatServer class. The ChatServer class is declared as: + The chat server is implemented by the \c ChatServer class. + The \c ChatServer class is declared as: \snippet btchat/chatserver.h declaration - The first thing the chat server needs to do is create an instance of QRfcommServer to listen - for incoming Bluetooth connections. Our clientConnected() slot will be called whenever a new - connection is created. + The first thing the chat server needs to do is create an instance of + QBluetoothServer to listen for incoming Bluetooth connections. The + \c {clientConnected()} slot will be called whenever a new connection is + created. \snippet btchat/chatserver.cpp Create the server The chat server is only useful if others know that it is there. To enable other devices to - discover it, a record describing the service needs to be published in the systems SDP (Service + discover it, a record describing the service needs to be published in the system's SDP (Service Discovery Protocol) database. The QBluetoothServiceInfo class encapsulates a service record. - We will publish a service record that contains some textural descriptions of the services, a + We will publish a service record that contains some textual descriptions of the services, a UUID that uniquely identifies the service, the discoverability attribute, and connection parameters. - The textural description of the service is stored in the ServiceName, ServiceDescription, and - ServiceProvider attributes. + The textual description of the service is stored in the \c {ServiceName}, + \c {ServiceDescription}, and \c {ServiceProvider} attributes. \snippet btchat/chatserver.cpp Service name, description and provider @@ -72,13 +51,14 @@ \snippet btchat/chatserver.cpp Service UUID \snippet btchat/chatserver.cpp Service UUID set - A Bluetooth service is only discoverable if it is in the PublicBrowseGroup. + A Bluetooth service is only discoverable if it is in the + \l {QBluetoothUuid::}{PublicBrowseGroup}. \snippet btchat/chatserver.cpp Service Discoverability - The ProtocolDescriptorList attribute is used to publish the connection parameters that the - remote device requires to connect to our service. Here we specify that the Rfcomm protocol is - used and set the port number to the port that our rfcommServer instance is listening to. + The \c ProtocolDescriptorList attribute is used to publish the connection parameters that the + remote device requires to connect to our service. Here we specify that the \c Rfcomm protocol + is used and set the port number to the port that our \c rfcommServer instance is listening to. \snippet btchat/chatserver.cpp Protocol descriptor list @@ -86,58 +66,92 @@ \snippet btchat/chatserver.cpp Register service - - As mentioned earlier, incoming connections are handled in the clientConnected() slot where - pending connections are connected to the readyRead() and disconnected() signals. The signals - notify others that a new client has connected. + As mentioned earlier, incoming connections are handled in the + \c {clientConnected()} slot where pending connections are connected to the + \l {QBluetoothSocket::}{readyRead()} and + \l {QBluetoothSocket::}{disconnected()} signals. The signals notify others + that a new client has connected. \snippet btchat/chatserver.cpp clientConnected - The readSocket() slot is called whenever data is ready to be read from a client socket. The - slot reads individual lines from the socket, converts them from UTF-8, and emits the - messageReceived() signal. + The \c {readSocket()} slot is called whenever data is ready to be read from + a client socket. The slot reads individual lines from the socket, converts + them from UTF-8, and emits the \c {messageReceived()} signal. \snippet btchat/chatserver.cpp readSocket - The clientDisconnected() slot is called whenever a client disconnects from the service. The - slot emits a signal to notify others that a client has disconnected, and deletes the socket. + The \c {clientDisconnected()} slot is called whenever a client disconnects + from the service. The slot emits a signal to notify others that a client + has disconnected, and deletes the socket. \snippet btchat/chatserver.cpp clientDisconnected - The sendMessage() slot is used to send a message to all connected clients. The message is + The \c {sendMessage()} slot is used to send a message to all connected clients. The message is converted into UTF-8 and appended with a newline before being sent to all clients. \snippet btchat/chatserver.cpp sendMessage - When the chat server is stopped the service record is removed from the system SDP database, all - connected client sockets are deleted, and the QRfcommServer instance is deleted. + When the chat server is stopped, the service record is removed from the + system SDP database, all connected client sockets are deleted, and the + \c rfcommServer instance is deleted. \snippet btchat/chatserver.cpp stopServer + \section1 Service Discovery + + Before connecting to the server, the client needs to scan the nearby + devices and search for the device that is advertising the chat service. + This is done by the \c RemoteSelector class. + + To start service lookup, the \c RemoteSelector creates an instance of + \l QBluetoothServiceDiscoveryAgent and connects to its signals. + + \snippet btchat/remoteselector.cpp createDiscoveryAgent + + An UUID filter is set, so that the service discovery only shows the devices + that advertise the needed service. After that a + \l {QBluetoothServiceDiscoveryAgent::}{FullDiscovery} is started: + + \snippet btchat/remoteselector.cpp startDiscovery + + When a matching service is discovered, a + \l {QBluetoothServiceDiscoveryAgent::}{serviceDiscovered()} signal is + emitted with an instance of \l QBluetoothServiceInfo as a parameter. This + service info is used to extract the device name and the service name, + and add a new entry to the list of discovered remote devices: + + \snippet btchat/remoteselector.cpp serviceDiscovered + + Later the user can select one of the devices from the list and try to + connect to it. + \section1 Chat Client - The chat client is implemented by the ChatClient class. The ChatClient class is declared as: + The chat client is implemented by the \c ChatClient class. + The \c ChatClient class is declared as: \snippet btchat/chatclient.h declaration - The client creates a new QBluetoothSocket and connects to the remote service described by the - \e remoteService parameter. Slots are connected to the sockets readyRead(), connected() and - disconnected() signals. + The client creates a new QBluetoothSocket and connects to the remote + service described by the \c remoteService parameter. Slots are connected + to the socket's \l {QBluetoothSocket::}{readyRead()}, + \l {QBluetoothSocket::}{connected()}, and + \l {QBluetoothSocket::}{disconnected()} signals. \snippet btchat/chatclient.cpp startClient - On successful socket connection we emit a signal to notify others. + On successful socket connection we emit a signal to notify other users. \snippet btchat/chatclient.cpp connected - Similarly to the chat server, the readSocket() slot is called when data is available from the - socket. Lines are read individually and converted from UTF-8. The messageReceived() signal - is emitted. + Similarly to the chat server, the \c readSocket() slot is called when data + is available from the socket. Lines are read individually and converted + from UTF-8. The \c {messageReceived()} signal is emitted. \snippet btchat/chatclient.cpp readSocket - The sendMessage() slot is used to send a message to the remote device. The message is - converted to UTF-8 and a newline is appended. + The \c {sendMessage()} slot is used to send a message to the remote device. + The message is converted to UTF-8 and a newline is appended. \snippet btchat/chatclient.cpp sendMessage @@ -147,9 +161,10 @@ \section1 Chat Dialog - The main window of this example is the chat dialog, implemented in the Chat class. This class - displays a chat session between a single ChatServer and zero or more ChatClients. The Chat - class is declared as: + The main window of this example is the chat dialog, implemented in the + \c Chat class. This class displays a chat session between a single + \c ChatServer and zero or more \c {ChatClient}s. The \c Chat class is + declared as: \snippet btchat/chat.h declaration @@ -157,38 +172,42 @@ \snippet btchat/chat.cpp Construct UI - We create an instance of the ChatServer and respond to its clientConnected(), - clientDiconnected(), and messageReceived() signals. + We create an instance of the \c ChatServer and respond to its + \c {clientConnected()}, \c {clientDiconnected()}, and + \c {messageReceived()} signals. \snippet btchat/chat.cpp Create Chat Server - In response to the clientConnected() and clientDisconnected() signals of the ChatServer, we - display the typical "X has joined chat." and "Y has left." messages in the chat session. + In response to the \c {clientConnected()} and \c {clientDisconnected()} + signals of the \c ChatServer, we display the typical "X has joined chat." + and "Y has left." messages in the chat session. \snippet btchat/chat.cpp clientConnected clientDisconnected - Incoming messages from clients connected to the ChatServer are handled in the showMessage() - slot. The message text tagged with the remote device name is displayed in the chat session. + Incoming messages from clients connected to the \c ChatServer are handled + in the \c {showMessage()} slot. The message text tagged with the remote + device name is displayed in the chat session. \snippet btchat/chat.cpp showMessage In response to the connect button being clicked, the application starts service discovery and - presents a list of discovered chat services on remote devices. A ChatClient for the service + presents a list of discovered chat services on remote devices. A \c ChatClient for the service is selected by the user. \snippet btchat/chat.cpp Connect to remote service - In reponse to the connected() signals from ChatClient, we display the a "Joined chat with X." - message in the chat session. + In reponse to the \c {connected()} signals from \c ChatClient, we display + the "Joined chat with X." message in the chat session. \snippet btchat/chat.cpp connected - Messages are sent to all remote devices via the ChatServer and ChatClient instances by emitting - the sendMessage() signal. + Messages are sent to all remote devices via the \c ChatServer and + \c ChatClient instances by emitting the \c {sendMessage()} signal. \snippet btchat/chat.cpp sendClicked - We need to clean up ChatClient instances when the remote device forces a disconnect. + We need to clean up \c ChatClient instances when the remote device forces + a disconnect. \snippet btchat/chat.cpp clientDisconnected */ diff --git a/examples/bluetooth/btchat/icons/btchat/24x24/bluetooth.png b/examples/bluetooth/btchat/icons/btchat/24x24/bluetooth.png Binary files differnew file mode 100644 index 00000000..832dd042 --- /dev/null +++ b/examples/bluetooth/btchat/icons/btchat/24x24/bluetooth.png diff --git a/examples/bluetooth/btchat/icons/btchat/24x24/bluetooth_dark.png b/examples/bluetooth/btchat/icons/btchat/24x24/bluetooth_dark.png Binary files differnew file mode 100644 index 00000000..48b772d0 --- /dev/null +++ b/examples/bluetooth/btchat/icons/btchat/24x24/bluetooth_dark.png diff --git a/examples/bluetooth/btchat/icons/btchat/24x24/send.png b/examples/bluetooth/btchat/icons/btchat/24x24/send.png Binary files differnew file mode 100644 index 00000000..dfce248a --- /dev/null +++ b/examples/bluetooth/btchat/icons/btchat/24x24/send.png diff --git a/examples/bluetooth/btchat/icons/btchat/24x24/send_dark.png b/examples/bluetooth/btchat/icons/btchat/24x24/send_dark.png Binary files differnew file mode 100644 index 00000000..66e78daf --- /dev/null +++ b/examples/bluetooth/btchat/icons/btchat/24x24/send_dark.png diff --git a/examples/bluetooth/btchat/icons/btchat/24x24@2/bluetooth.png b/examples/bluetooth/btchat/icons/btchat/24x24@2/bluetooth.png Binary files differnew file mode 100644 index 00000000..12bbb81d --- /dev/null +++ b/examples/bluetooth/btchat/icons/btchat/24x24@2/bluetooth.png diff --git a/examples/bluetooth/btchat/icons/btchat/24x24@2/bluetooth_dark.png b/examples/bluetooth/btchat/icons/btchat/24x24@2/bluetooth_dark.png Binary files differnew file mode 100644 index 00000000..f3456e6f --- /dev/null +++ b/examples/bluetooth/btchat/icons/btchat/24x24@2/bluetooth_dark.png diff --git a/examples/bluetooth/btchat/icons/btchat/24x24@2/send.png b/examples/bluetooth/btchat/icons/btchat/24x24@2/send.png Binary files differnew file mode 100644 index 00000000..8c4d5d0e --- /dev/null +++ b/examples/bluetooth/btchat/icons/btchat/24x24@2/send.png diff --git a/examples/bluetooth/btchat/icons/btchat/24x24@2/send_dark.png b/examples/bluetooth/btchat/icons/btchat/24x24@2/send_dark.png Binary files differnew file mode 100644 index 00000000..03b597c3 --- /dev/null +++ b/examples/bluetooth/btchat/icons/btchat/24x24@2/send_dark.png diff --git a/examples/bluetooth/btchat/icons/btchat/24x24@3/bluetooth.png b/examples/bluetooth/btchat/icons/btchat/24x24@3/bluetooth.png Binary files differnew file mode 100644 index 00000000..235b91aa --- /dev/null +++ b/examples/bluetooth/btchat/icons/btchat/24x24@3/bluetooth.png diff --git a/examples/bluetooth/btchat/icons/btchat/24x24@3/bluetooth_dark.png b/examples/bluetooth/btchat/icons/btchat/24x24@3/bluetooth_dark.png Binary files differnew file mode 100644 index 00000000..c64aa4a9 --- /dev/null +++ b/examples/bluetooth/btchat/icons/btchat/24x24@3/bluetooth_dark.png diff --git a/examples/bluetooth/btchat/icons/btchat/24x24@3/send.png b/examples/bluetooth/btchat/icons/btchat/24x24@3/send.png Binary files differnew file mode 100644 index 00000000..3d15b197 --- /dev/null +++ b/examples/bluetooth/btchat/icons/btchat/24x24@3/send.png diff --git a/examples/bluetooth/btchat/icons/btchat/24x24@3/send_dark.png b/examples/bluetooth/btchat/icons/btchat/24x24@3/send_dark.png Binary files differnew file mode 100644 index 00000000..7f1a9f4d --- /dev/null +++ b/examples/bluetooth/btchat/icons/btchat/24x24@3/send_dark.png diff --git a/examples/bluetooth/btchat/icons/btchat/24x24@4/bluetooth.png b/examples/bluetooth/btchat/icons/btchat/24x24@4/bluetooth.png Binary files differnew file mode 100644 index 00000000..bad3e2ea --- /dev/null +++ b/examples/bluetooth/btchat/icons/btchat/24x24@4/bluetooth.png diff --git a/examples/bluetooth/btchat/icons/btchat/24x24@4/bluetooth_dark.png b/examples/bluetooth/btchat/icons/btchat/24x24@4/bluetooth_dark.png Binary files differnew file mode 100644 index 00000000..01f420b0 --- /dev/null +++ b/examples/bluetooth/btchat/icons/btchat/24x24@4/bluetooth_dark.png diff --git a/examples/bluetooth/btchat/icons/btchat/24x24@4/send.png b/examples/bluetooth/btchat/icons/btchat/24x24@4/send.png Binary files differnew file mode 100644 index 00000000..c931f7a0 --- /dev/null +++ b/examples/bluetooth/btchat/icons/btchat/24x24@4/send.png diff --git a/examples/bluetooth/btchat/icons/btchat/24x24@4/send_dark.png b/examples/bluetooth/btchat/icons/btchat/24x24@4/send_dark.png Binary files differnew file mode 100644 index 00000000..8b801207 --- /dev/null +++ b/examples/bluetooth/btchat/icons/btchat/24x24@4/send_dark.png diff --git a/examples/bluetooth/btchat/icons/btchat/index.theme b/examples/bluetooth/btchat/icons/btchat/index.theme new file mode 100644 index 00000000..3209f84f --- /dev/null +++ b/examples/bluetooth/btchat/icons/btchat/index.theme @@ -0,0 +1,22 @@ +[Icon Theme] +Name=btchat +Directories=24x24,24x24@2,24x24@3,24x24@4 + +[24x24] +Size=24 +Type=Fixed + +[24x24@2] +Size=24 +Scale=2 +Type=Fixed + +[24x24@3] +Size=24 +Scale=3 +Type=Fixed + +[24x24@4] +Size=24 +Scale=4 +Type=Fixed diff --git a/examples/bluetooth/btchat/main.cpp b/examples/bluetooth/btchat/main.cpp index e728efd2..1da4f9f5 100644 --- a/examples/bluetooth/btchat/main.cpp +++ b/examples/bluetooth/btchat/main.cpp @@ -1,68 +1,25 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtBluetooth module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause #include "chat.h" -#include <QtWidgets/qapplication.h> -//#include <QtCore/QLoggingCategory> +#include <QLoggingCategory> + +#include <QApplication> + +using namespace Qt::StringLiterals; int main(int argc, char *argv[]) { - //QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true")); - QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + // QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true")); QApplication app(argc, argv); + QIcon::setThemeName(u"btchat"_s); + Chat d; QObject::connect(&d, &Chat::accepted, &app, &QApplication::quit); -#ifdef Q_OS_ANDROID +#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) d.showMaximized(); #else d.show(); diff --git a/examples/bluetooth/btchat/remoteselector.cpp b/examples/bluetooth/btchat/remoteselector.cpp index ec5d207c..dc501c82 100644 --- a/examples/bluetooth/btchat/remoteselector.cpp +++ b/examples/bluetooth/btchat/remoteselector.cpp @@ -1,72 +1,43 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtBluetooth module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause #include "remoteselector.h" #include "ui_remoteselector.h" -#include <QtBluetooth/qbluetoothlocaldevice.h> -#include <QtBluetooth/qbluetoothservicediscoveryagent.h> +#include <QBluetoothAddress> +#include <QBluetoothLocalDevice> +#include <QBluetoothServiceDiscoveryAgent> +#include <QBluetoothUuid> -QT_USE_NAMESPACE +#include <QGuiApplication> +#include <QStyleHints> + +#include <QListWidget> + +using namespace Qt::StringLiterals; RemoteSelector::RemoteSelector(const QBluetoothAddress &localAdapter, QWidget *parent) : QDialog(parent), ui(new Ui::RemoteSelector) { ui->setupUi(this); +#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) + setWindowState(Qt::WindowMaximized); +#endif + + QStyleHints *styleHints = qGuiApp->styleHints(); + updateIcon(styleHints->colorScheme()); + connect(styleHints, &QStyleHints::colorSchemeChanged, this, &RemoteSelector::updateIcon); +//! [createDiscoveryAgent] m_discoveryAgent = new QBluetoothServiceDiscoveryAgent(localAdapter); - connect(m_discoveryAgent, SIGNAL(serviceDiscovered(QBluetoothServiceInfo)), - this, SLOT(serviceDiscovered(QBluetoothServiceInfo))); - connect(m_discoveryAgent, SIGNAL(finished()), this, SLOT(discoveryFinished())); - connect(m_discoveryAgent, SIGNAL(canceled()), this, SLOT(discoveryFinished())); + connect(m_discoveryAgent, &QBluetoothServiceDiscoveryAgent::serviceDiscovered, + this, &RemoteSelector::serviceDiscovered); + connect(m_discoveryAgent, &QBluetoothServiceDiscoveryAgent::finished, + this, &RemoteSelector::discoveryFinished); + connect(m_discoveryAgent, &QBluetoothServiceDiscoveryAgent::canceled, + this, &RemoteSelector::discoveryFinished); +//! [createDiscoveryAgent] } RemoteSelector::~RemoteSelector() @@ -83,9 +54,10 @@ void RemoteSelector::startDiscovery(const QBluetoothUuid &uuid) ui->remoteDevices->clear(); +//! [startDiscovery] m_discoveryAgent->setUuidFilter(uuid); m_discoveryAgent->start(QBluetoothServiceDiscoveryAgent::FullDiscovery); - +//! [startDiscovery] } void RemoteSelector::stopDiscovery() @@ -115,11 +87,12 @@ void RemoteSelector::serviceDiscovered(const QBluetoothServiceInfo &serviceInfo) qDebug() << "\tRFCOMM server channel:" << serviceInfo.serverChannel(); #endif const QBluetoothAddress address = serviceInfo.device().address(); - for (const QBluetoothServiceInfo &info : qAsConst(m_discoveredServices)) { + for (const QBluetoothServiceInfo &info : std::as_const(m_discoveredServices)) { if (info.device().address() == address) return; } +//! [serviceDiscovered] QString remoteName; if (serviceInfo.device().name().isEmpty()) remoteName = address.toString(); @@ -132,6 +105,7 @@ void RemoteSelector::serviceDiscovered(const QBluetoothServiceInfo &serviceInfo) m_discoveredServices.insert(item, serviceInfo); ui->remoteDevices->addItem(item); +//! [serviceDiscovered] } void RemoteSelector::discoveryFinished() @@ -139,9 +113,16 @@ void RemoteSelector::discoveryFinished() ui->status->setText(tr("Select the chat service to connect to.")); } +void RemoteSelector::updateIcon(Qt::ColorScheme scheme) +{ + const QString bluetoothIconName = (scheme == Qt::ColorScheme::Dark) ? u"bluetooth_dark"_s + : u"bluetooth"_s; + const QIcon bluetoothIcon = QIcon::fromTheme(bluetoothIconName); + ui->iconLabel->setPixmap(bluetoothIcon.pixmap(24, 24, QIcon::Normal, QIcon::On)); +} + void RemoteSelector::on_remoteDevices_itemActivated(QListWidgetItem *item) { - qDebug() << "got click" << item->text(); m_service = m_discoveredServices.value(item); if (m_discoveryAgent->isActive()) m_discoveryAgent->stop(); @@ -149,6 +130,25 @@ void RemoteSelector::on_remoteDevices_itemActivated(QListWidgetItem *item) accept(); } +void RemoteSelector::on_remoteDevices_itemClicked(QListWidgetItem *) +{ + ui->connectButton->setEnabled(true); + ui->connectButton->setFocus(); +} + +void RemoteSelector::on_connectButton_clicked() +{ + auto items = ui->remoteDevices->selectedItems(); + if (items.size()) { + QListWidgetItem *item = items[0]; + m_service = m_discoveredServices.value(item); + if (m_discoveryAgent->isActive()) + m_discoveryAgent->stop(); + + accept(); + } +} + void RemoteSelector::on_cancelButton_clicked() { reject(); diff --git a/examples/bluetooth/btchat/remoteselector.h b/examples/bluetooth/btchat/remoteselector.h index 54649ba9..c6fc665b 100644 --- a/examples/bluetooth/btchat/remoteselector.h +++ b/examples/bluetooth/btchat/remoteselector.h @@ -1,68 +1,20 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtBluetooth module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause #ifndef REMOTESELECTOR_H #define REMOTESELECTOR_H -#include <QtWidgets/qdialog.h> +#include <QDialog> -#include <QtBluetooth/qbluetoothaddress.h> -#include <QtBluetooth/qbluetoothserviceinfo.h> -#include <QtBluetooth/qbluetoothuuid.h> +#include <QBluetoothServiceInfo> -QT_FORWARD_DECLARE_CLASS(QBluetoothServiceDiscoveryAgent) -QT_FORWARD_DECLARE_CLASS(QListWidgetItem) +QT_BEGIN_NAMESPACE -QT_USE_NAMESPACE +class QBluetoothAddress; +class QBluetoothServiceDiscoveryAgent; +class QBluetoothUuid; +class QListWidgetItem; -QT_BEGIN_NAMESPACE namespace Ui { class RemoteSelector; } @@ -90,8 +42,11 @@ private: private slots: void serviceDiscovered(const QBluetoothServiceInfo &serviceInfo); void discoveryFinished(); + void updateIcon(Qt::ColorScheme scheme); void on_remoteDevices_itemActivated(QListWidgetItem *item); + void on_remoteDevices_itemClicked(QListWidgetItem *item); void on_cancelButton_clicked(); + void on_connectButton_clicked(); }; #endif // REMOTESELECTOR_H diff --git a/examples/bluetooth/btchat/remoteselector.ui b/examples/bluetooth/btchat/remoteselector.ui index d415f416..853f6105 100644 --- a/examples/bluetooth/btchat/remoteselector.ui +++ b/examples/bluetooth/btchat/remoteselector.ui @@ -15,6 +15,16 @@ </property> <layout class="QVBoxLayout" name="verticalLayout"> <item> + <widget class="QLabel" name="iconLabel"> + <property name="text"> + <string/> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + </item> + <item> <widget class="QLabel" name="status"> <property name="text"> <string>Scanning...</string> @@ -25,11 +35,38 @@ <widget class="QListWidget" name="remoteDevices"/> </item> <item> - <widget class="QPushButton" name="cancelButton"> - <property name="text"> - <string>Cancel</string> - </property> - </widget> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="cancelButton"> + <property name="text"> + <string>Cancel</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="connectButton"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Connect</string> + </property> + </widget> + </item> + </layout> </item> </layout> </widget> |