Bluetooth Chat Example▲
Sélectionnez
/**
**************************************************************************
**
** 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
"chat.h"
#include
"remoteselector.h"
#include
"chatserver.h"
#include
"chatclient.h"
#include <QtCore/qdebug.h>
#include <QtBluetooth/qbluetoothdeviceinfo.h>
#include <QtBluetooth/qbluetoothlocaldevice.h>
#include <QtBluetooth/qbluetoothuuid.h>
#ifdef Q_OS_ANDROID
#include <QtAndroidExtras/QtAndroid>
#endif
static
const
QLatin1String serviceUuid("e8e10f95-1a70-4b27-9ccf-02010264e9c8"
);
#ifdef Q_OS_ANDROID
static
const
QLatin1String reverseUuid("c8e96402-0102-cf9c-274b-701a950fe1e8"
);
#endif
Chat::
Chat(QWidget *
parent)
:
QDialog(parent), ui(new
Ui_Chat)
{
ui-&
gt;setupUi(this
);
connect(ui-&
gt;quitButton, &
amp;QPushButton::
clicked, this
, &
amp;Chat::
accept);
connect(ui-&
gt;connectButton, &
amp;QPushButton::
clicked, this
, &
amp;Chat::
connectClicked);
connect(ui-&
gt;sendButton, &
amp;QPushButton::
clicked, this
, &
amp;Chat::
sendClicked);
localAdapters =
QBluetoothLocalDevice::
allDevices();
if
(localAdapters.count() &
lt; 2
) {
ui-&
gt;localAdapterBox-&
gt;setVisible(false
);
}
else
{
//we ignore more than two adapters
ui-&
gt;localAdapterBox-&
gt;setVisible(true
);
ui-&
gt;firstAdapter-&
gt;setText(tr("Default (%1)"
, "%1 = Bluetooth address"
).
arg(localAdapters.at(0
).address().toString()));
ui-&
gt;secondAdapter-&
gt;setText(localAdapters.at(1
).address().toString());
ui-&
gt;firstAdapter-&
gt;setChecked(true
);
connect(ui-&
gt;firstAdapter, &
amp;QRadioButton::
clicked, this
, &
amp;Chat::
newAdapterSelected);
connect(ui-&
gt;secondAdapter, &
amp;QRadioButton::
clicked, this
, &
amp;Chat::
newAdapterSelected);
QBluetoothLocalDevice adapter(localAdapters.at(0
).address());
adapter.setHostMode(QBluetoothLocalDevice::
HostDiscoverable);
}
server =
new
ChatServer(this
);
connect(server, QOverload&
lt;const
QString &
amp;&
gt;::
of(&
amp;ChatServer::
clientConnected),
this
, &
amp;Chat::
clientConnected);
connect(server, QOverload&
lt;const
QString &
amp;&
gt;::
of(&
amp;ChatServer::
clientDisconnected),
this
, QOverload&
lt;const
QString &
amp;&
gt;::
of(&
amp;Chat::
clientDisconnected));
connect(server, &
amp;ChatServer::
messageReceived,
this
, &
amp;Chat::
showMessage);
connect(this
, &
amp;Chat::
sendMessage, server, &
amp;ChatServer::
sendMessage);
server-&
gt;startServer();
localName =
QBluetoothLocalDevice().name();
}
Chat::
~
Chat()
{
qDeleteAll(clients);
delete
server;
}
void
Chat::
clientConnected(const
QString &
amp;name)
{
ui-&
gt;chat-&
gt;insertPlainText(QString::
fromLatin1("%1 has joined chat.
\n
"
).arg(name));
}
void
Chat::
clientDisconnected(const
QString &
amp;name)
{
ui-&
gt;chat-&
gt;insertPlainText(QString::
fromLatin1("%1 has left.
\n
"
).arg(name));
}
void
Chat::
connected(const
QString &
amp;name)
{
ui-&
gt;chat-&
gt;insertPlainText(QString::
fromLatin1("Joined chat with %1.
\n
"
).arg(name));
}
void
Chat::
newAdapterSelected()
{
const
int
newAdapterIndex =
adapterFromUserSelection();
if
(currentAdapterIndex !=
newAdapterIndex) {
server-&
gt;stopServer();
currentAdapterIndex =
newAdapterIndex;
const
QBluetoothHostInfo info =
localAdapters.at(currentAdapterIndex);
QBluetoothLocalDevice adapter(info.address());
adapter.setHostMode(QBluetoothLocalDevice::
HostDiscoverable);
server-&
gt;startServer(info.address());
localName =
info.name();
}
}
int
Chat::
adapterFromUserSelection() const
{
int
result =
0
;
QBluetoothAddress newAdapter =
localAdapters.at(0
).address();
if
(ui-&
gt;secondAdapter-&
gt;isChecked()) {
newAdapter =
localAdapters.at(1
).address();
result =
1
;
}
return
result;
}
void
Chat::
reactOnSocketError(const
QString &
amp;error)
{
ui-&
gt;chat-&
gt;insertPlainText(error);
}
void
Chat::
clientDisconnected()
{
ChatClient *
client =
qobject_cast&
lt;ChatClient *&
gt;(sender());
if
(client) {
clients.removeOne(client);
client-&
gt;deleteLater();
}
}
void
Chat::
connectClicked()
{
ui-&
gt;connectButton-&
gt;setEnabled(false
);
// scan for services
const
QBluetoothAddress adapter =
localAdapters.isEmpty() ?
QBluetoothAddress() :
localAdapters.at(currentAdapterIndex).address();
RemoteSelector remoteSelector(adapter);
#ifdef Q_OS_ANDROID
if
(QtAndroid::
androidSdkVersion() &
gt;=
23
)
remoteSelector.startDiscovery(QBluetoothUuid(reverseUuid));
else
remoteSelector.startDiscovery(QBluetoothUuid(serviceUuid));
#else
remoteSelector.startDiscovery(QBluetoothUuid(serviceUuid));
#endif
if
(remoteSelector.exec() ==
QDialog::
Accepted) {
QBluetoothServiceInfo service =
remoteSelector.service();
qDebug() &
lt;&
lt; "Connecting to service 2"
&
lt;&
lt; service.serviceName()
&
lt;&
lt; "on"
&
lt;&
lt; service.device().name();
// Create client
qDebug() &
lt;&
lt; "Going to create client"
;
ChatClient *
client =
new
ChatClient(this
);
qDebug() &
lt;&
lt; "Connecting..."
;
connect(client, &
amp;ChatClient::
messageReceived,
this
, &
amp;Chat::
showMessage);
connect(client, &
amp;ChatClient::
disconnected,
this
, QOverload&
lt;&
gt;::
of(&
amp;Chat::
clientDisconnected));
connect(client, QOverload&
lt;const
QString &
amp;&
gt;::
of(&
amp;ChatClient::
connected),
this
, &
amp;Chat::
connected);
connect(client, &
amp;ChatClient::
socketErrorOccurred,
this
, &
amp;Chat::
reactOnSocketError);
connect(this
, &
amp;Chat::
sendMessage, client, &
amp;ChatClient::
sendMessage);
qDebug() &
lt;&
lt; "Start client"
;
client-&
gt;startClient(service);
clients.append(client);
}
ui-&
gt;connectButton-&
gt;setEnabled(true
);
}
void
Chat::
sendClicked()
{
ui-&
gt;sendButton-&
gt;setEnabled(false
);
ui-&
gt;sendText-&
gt;setEnabled(false
);
showMessage(localName, ui-&
gt;sendText-&
gt;text());
emit sendMessage(ui-&
gt;sendText-&
gt;text());
ui-&
gt;sendText-&
gt;clear();
ui-&
gt;sendText-&
gt;setEnabled(true
);
ui-&
gt;sendButton-&
gt;setEnabled(true
);
}
void
Chat::
showMessage(const
QString &
amp;sender, const
QString &
amp;message)
{
ui-&
gt;chat-&
gt;insertPlainText(QString::
fromLatin1("%1: %2
\n
"
).arg(sender, message));
ui-&
gt;chat-&
gt;ensureCursorVisible();
}