summaryrefslogtreecommitdiffstats
path: root/examples/bluetooth
diff options
context:
space:
mode:
authorJerome Pasion <jerome.pasion@digia.com>2012-09-25 15:20:41 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2012-09-27 14:43:52 +0200
commitd8a179128c0fa8e9cc482df58b9334c696602be6 (patch)
treedd5032440aa87dfd63c973265adc9947db0918f6 /examples/bluetooth
parent9d89c661395347bdda9362a77d38c86ad60f486b (diff)
Qt Bluetooth: Modularized documentation
-moved documentation to src/bluetooth/doc -added a qdocconf file for Qt Bluetooth -fixed relative paths for snippets -moved examples to examples/bluetooth Change-Id: Id41bac50dca628400568d191f1c3ccfbaac790a1 Reviewed-by: Alex <ablasche@gmail.com>
Diffstat (limited to 'examples/bluetooth')
-rw-r--r--examples/bluetooth/bluetooth.pro9
-rw-r--r--examples/bluetooth/btchat/btchat.pro21
-rw-r--r--examples/bluetooth/btchat/chat.cpp179
-rw-r--r--examples/bluetooth/btchat/chat.h90
-rw-r--r--examples/bluetooth/btchat/chat.ui76
-rw-r--r--examples/bluetooth/btchat/chatclient.cpp108
-rw-r--r--examples/bluetooth/btchat/chatclient.h83
-rw-r--r--examples/bluetooth/btchat/chatserver.cpp182
-rw-r--r--examples/bluetooth/btchat/chatserver.h88
-rw-r--r--examples/bluetooth/btchat/doc/images/btchat-example.pngbin0 -> 6527 bytes
-rw-r--r--examples/bluetooth/btchat/doc/src/btchat.qdoc191
-rw-r--r--examples/bluetooth/btchat/main.cpp62
-rw-r--r--examples/bluetooth/btchat/remoteselector.cpp146
-rw-r--r--examples/bluetooth/btchat/remoteselector.h87
-rw-r--r--examples/bluetooth/btchat/remoteselector.ui38
-rw-r--r--examples/bluetooth/btfiletransfer/btfiletransfer.pro27
-rw-r--r--examples/bluetooth/btfiletransfer/btfiletransfer.qrc6
-rw-r--r--examples/bluetooth/btfiletransfer/busy.gifbin0 -> 847 bytes
-rw-r--r--examples/bluetooth/btfiletransfer/doc/images/btfiletransfer-example.pngbin0 -> 44606 bytes
-rw-r--r--examples/bluetooth/btfiletransfer/doc/src/btfiletransfer.qdoc37
-rw-r--r--examples/bluetooth/btfiletransfer/main.cpp58
-rw-r--r--examples/bluetooth/btfiletransfer/pairing.gifbin0 -> 3951 bytes
-rw-r--r--examples/bluetooth/btfiletransfer/pindisplay.cpp69
-rw-r--r--examples/bluetooth/btfiletransfer/pindisplay.h69
-rw-r--r--examples/bluetooth/btfiletransfer/pindisplay.ui89
-rw-r--r--examples/bluetooth/btfiletransfer/progress.cpp97
-rw-r--r--examples/bluetooth/btfiletransfer/progress.h80
-rw-r--r--examples/bluetooth/btfiletransfer/progress.ui55
-rw-r--r--examples/bluetooth/btfiletransfer/remoteselector.cpp372
-rw-r--r--examples/bluetooth/btfiletransfer/remoteselector.h110
-rw-r--r--examples/bluetooth/btfiletransfer/remoteselector.ui214
-rw-r--r--examples/bluetooth/btscanner/btscanner.pro18
-rw-r--r--examples/bluetooth/btscanner/device.cpp211
-rw-r--r--examples/bluetooth/btscanner/device.h85
-rw-r--r--examples/bluetooth/btscanner/device.ui121
-rw-r--r--examples/bluetooth/btscanner/doc/images/btscanner-example.pngbin0 -> 76746 bytes
-rw-r--r--examples/bluetooth/btscanner/doc/src/btscanner.qdoc36
-rw-r--r--examples/bluetooth/btscanner/main.cpp57
-rw-r--r--examples/bluetooth/btscanner/service.cpp87
-rw-r--r--examples/bluetooth/btscanner/service.h74
-rw-r--r--examples/bluetooth/btscanner/service.ui76
-rw-r--r--examples/bluetooth/bttennis/board.cpp250
-rw-r--r--examples/bluetooth/bttennis/board.h126
-rw-r--r--examples/bluetooth/bttennis/bttennis.pro30
-rw-r--r--examples/bluetooth/bttennis/connect.pngbin0 -> 11074 bytes
-rw-r--r--examples/bluetooth/bttennis/controller.cpp263
-rw-r--r--examples/bluetooth/bttennis/controller.h100
-rw-r--r--examples/bluetooth/bttennis/doc/images/bttennis-example.pngbin0 -> 4890 bytes
-rw-r--r--examples/bluetooth/bttennis/doc/src/bttennis.qdoc37
-rw-r--r--examples/bluetooth/bttennis/handover.cpp130
-rw-r--r--examples/bluetooth/bttennis/handover.h94
-rw-r--r--examples/bluetooth/bttennis/main.cpp63
-rw-r--r--examples/bluetooth/bttennis/tennis.cpp424
-rw-r--r--examples/bluetooth/bttennis/tennis.h140
-rw-r--r--examples/bluetooth/bttennis/tennis.qrc5
-rw-r--r--examples/bluetooth/bttennis/tennis.ui57
-rw-r--r--examples/bluetooth/bttennis/tennisclient.cpp200
-rw-r--r--examples/bluetooth/bttennis/tennisclient.h104
-rw-r--r--examples/bluetooth/bttennis/tennisserver.cpp306
-rw-r--r--examples/bluetooth/bttennis/tennisserver.h106
-rw-r--r--examples/bluetooth/bttennis/tennisview.cpp69
-rw-r--r--examples/bluetooth/bttennis/tennisview.h69
-rw-r--r--examples/bluetooth/scanner/qmlscanner.cpp62
-rw-r--r--examples/bluetooth/scanner/scanner.pro11
-rw-r--r--examples/bluetooth/scanner/scanner.qml246
-rw-r--r--examples/bluetooth/scanner/scanner.qrc5
66 files changed, 6305 insertions, 0 deletions
diff --git a/examples/bluetooth/bluetooth.pro b/examples/bluetooth/bluetooth.pro
new file mode 100644
index 00000000..20bf6c6d
--- /dev/null
+++ b/examples/bluetooth/bluetooth.pro
@@ -0,0 +1,9 @@
+TEMPLATE = subdirs
+!contains(QT_CONFIG, no-widgets) {
+ SUBDIRS += btchat \
+ btscanner \
+ btfiletransfer \
+ bttennis
+}
+
+SUBDIRS += scanner
diff --git a/examples/bluetooth/btchat/btchat.pro b/examples/bluetooth/btchat/btchat.pro
new file mode 100644
index 00000000..f215cb87
--- /dev/null
+++ b/examples/bluetooth/btchat/btchat.pro
@@ -0,0 +1,21 @@
+TEMPLATE = app
+TARGET = btchat
+
+QT += concurrent bluetooth widgets
+
+SOURCES = \
+ main.cpp \
+ chat.cpp \
+ remoteselector.cpp \
+ chatserver.cpp \
+ chatclient.cpp
+
+HEADERS = \
+ chat.h \
+ remoteselector.h \
+ chatserver.h \
+ chatclient.h
+
+FORMS = \
+ chat.ui \
+ remoteselector.ui
diff --git a/examples/bluetooth/btchat/chat.cpp b/examples/bluetooth/btchat/chat.cpp
new file mode 100644
index 00000000..7047cbdd
--- /dev/null
+++ b/examples/bluetooth/btchat/chat.cpp
@@ -0,0 +1,179 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Digia Plc and its Subsidiary(-ies) 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 <qbluetoothuuid.h>
+#include <qrfcommserver.h>
+#include <qbluetoothservicediscoveryagent.h>
+#include <qbluetoothdeviceinfo.h>
+#include <qbluetoothlocaldevice.h>
+
+#include <QTimer>
+
+#include <QDebug>
+
+static const QLatin1String serviceUuid("e8e10f95-1a70-4b27-9ccf-02010264e9c8");
+
+Chat::Chat(QWidget *parent)
+: QDialog(parent), ui(new Ui_Chat)
+{
+ //! [Construct UI]
+ ui->setupUi(this);
+
+#if defined(Q_OS_WINCE) || defined(Q_WS_MAEMO_6)
+ setWindowState(Qt::WindowFullScreen);
+#endif
+
+ connect(ui->quitButton, SIGNAL(clicked()), this, SLOT(accept()));
+ connect(ui->connectButton, SIGNAL(clicked()), this, SLOT(connectClicked()));
+ connect(ui->sendButton, SIGNAL(clicked()), this, SLOT(sendClicked()));
+ //! [Construct UI]
+
+ //! [Create Chat Server]
+ server = new ChatServer(this);
+ connect(server, SIGNAL(clientConnected(QString)), this, SLOT(clientConnected(QString)));
+ connect(server, SIGNAL(clientDisconnected(QString)), this, SLOT(clientDisconnected(QString)));
+ connect(server, SIGNAL(messageReceived(QString,QString)),
+ this, SLOT(showMessage(QString,QString)));
+ connect(this, SIGNAL(sendMessage(QString)), server, SLOT(sendMessage(QString)));
+ server->startServer();
+ //! [Create Chat Server]
+
+ //! [Get local device name]
+ localName = QBluetoothLocalDevice().name();
+ //! [Get local device name]
+}
+
+Chat::~Chat()
+{
+ qDeleteAll(clients);
+ delete server;
+}
+
+//! [clientConnected clientDisconnected]
+void Chat::clientConnected(const QString &name)
+{
+ ui->chat->insertPlainText(QString::fromLatin1("%1 has joined chat.\n").arg(name));
+}
+
+void Chat::clientDisconnected(const QString &name)
+{
+ ui->chat->insertPlainText(QString::fromLatin1("%1 has left.\n").arg(name));
+}
+//! [clientConnected clientDisconnected]
+
+//! [connected]
+void Chat::connected(const QString &name)
+{
+ ui->chat->insertPlainText(QString::fromLatin1("Joined chat with %1.\n").arg(name));
+}
+//! [connected]
+
+//! [clientDisconnected]
+void Chat::clientDisconnected()
+{
+ ChatClient *client = qobject_cast<ChatClient *>(sender());
+ if (client) {
+ clients.removeOne(client);
+ client->deleteLater();
+ }
+}
+//! [clientDisconnected]
+
+//! [Connect to remote service]
+void Chat::connectClicked()
+{
+ ui->connectButton->setEnabled(false);
+
+ // scan for services
+ RemoteSelector remoteSelector;
+ remoteSelector.startDiscovery(QBluetoothUuid(serviceUuid));
+ if (remoteSelector.exec() == QDialog::Accepted) {
+ QBluetoothServiceInfo service = remoteSelector.service();
+
+ qDebug() << "Connecting to service 2" << service.serviceName()
+ << "on" << service.device().name();
+
+ // Create client
+ qDebug() << "Going to create client";
+ ChatClient *client = new ChatClient(this);
+qDebug() << "Connecting...";
+
+ connect(client, SIGNAL(messageReceived(QString,QString)),
+ this, SLOT(showMessage(QString,QString)));
+ connect(client, SIGNAL(disconnected()), this, SLOT(clientDisconnected()));
+ connect(client, SIGNAL(connected(QString)), this, SLOT(connected(QString)));
+ connect(this, SIGNAL(sendMessage(QString)), client, SLOT(sendMessage(QString)));
+qDebug() << "Start client";
+ client->startClient(service);
+
+ clients.append(client);
+ }
+
+ ui->connectButton->setEnabled(true);
+}
+//! [Connect to remote service]
+
+//! [sendClicked]
+void Chat::sendClicked()
+{
+ ui->sendButton->setEnabled(false);
+ ui->sendText->setEnabled(false);
+
+ showMessage(localName, ui->sendText->text());
+ emit sendMessage(ui->sendText->text());
+
+ ui->sendText->clear();
+
+ ui->sendText->setEnabled(true);
+ ui->sendButton->setEnabled(true);
+}
+//! [sendClicked]
+
+//! [showMessage]
+void Chat::showMessage(const QString &sender, const QString &message)
+{
+ ui->chat->insertPlainText(QString::fromLatin1("%1: %2\n").arg(sender, message));
+}
+//! [showMessage]
diff --git a/examples/bluetooth/btchat/chat.h b/examples/bluetooth/btchat/chat.h
new file mode 100644
index 00000000..740999d0
--- /dev/null
+++ b/examples/bluetooth/btchat/chat.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Digia Plc and its Subsidiary(-ies) 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 <QDialog>
+
+#include <qbluetoothserviceinfo.h>
+#include <qbluetoothsocket.h>
+
+#include <QDebug>
+
+QTBLUETOOTH_BEGIN_NAMESPACE
+class QRfcommServer;
+QTBLUETOOTH_END_NAMESPACE
+
+QTBLUETOOTH_USE_NAMESPACE
+
+class ChatServer;
+class ChatClient;
+
+//! [declaration]
+class Chat : public QDialog
+{
+ Q_OBJECT
+
+public:
+ Chat(QWidget *parent = 0);
+ ~Chat();
+
+signals:
+ void sendMessage(const QString &message);
+
+private slots:
+ void connectClicked();
+ void sendClicked();
+
+ void showMessage(const QString &sender, const QString &message);
+
+ void clientConnected(const QString &name);
+ void clientDisconnected(const QString &name);
+ void clientDisconnected();
+ void connected(const QString &name);
+
+private:
+ Ui_Chat *ui;
+
+ ChatServer *server;
+ QList<ChatClient *> clients;
+
+ QString localName;
+};
+//! [declaration]
diff --git a/examples/bluetooth/btchat/chat.ui b/examples/bluetooth/btchat/chat.ui
new file mode 100644
index 00000000..acebc937
--- /dev/null
+++ b/examples/bluetooth/btchat/chat.ui
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Chat</class>
+ <widget class="QDialog" name="Chat">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>400</width>
+ <height>300</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Bluetooth Chat</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QTextEdit" name="chat">
+ <property name="focusPolicy">
+ <enum>Qt::NoFocus</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QLineEdit" name="sendText"/>
+ </item>
+ <item>
+ <widget class="QPushButton" name="sendButton">
+ <property name="text">
+ <string>Send</string>
+ </property>
+ <property name="default">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <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="connectButton">
+ <property name="text">
+ <string>Connect</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QPushButton" name="quitButton">
+ <property name="text">
+ <string>Quit</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/examples/bluetooth/btchat/chatclient.cpp b/examples/bluetooth/btchat/chatclient.cpp
new file mode 100644
index 00000000..8ea66e51
--- /dev/null
+++ b/examples/bluetooth/btchat/chatclient.cpp
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Digia Plc and its Subsidiary(-ies) 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 "chatclient.h"
+
+#include <qbluetoothsocket.h>
+
+ChatClient::ChatClient(QObject *parent)
+: QObject(parent), socket(0)
+{
+}
+
+ChatClient::~ChatClient()
+{
+ stopClient();
+}
+
+//! [startClient]
+void ChatClient::startClient(const QBluetoothServiceInfo &remoteService)
+{
+ if (socket)
+ return;
+
+ // Connect to service
+ socket = new QBluetoothSocket(QBluetoothSocket::RfcommSocket);
+ qDebug() << "Create socket";
+ socket->connectToService(remoteService);
+ qDebug() << "ConnecttoService done";
+
+ connect(socket, SIGNAL(readyRead()), this, SLOT(readSocket()));
+ connect(socket, SIGNAL(connected()), this, SLOT(connected()));
+ connect(socket, SIGNAL(disconnected()), this, SIGNAL(disconnected()));
+}
+//! [startClient]
+
+//! [stopClient]
+void ChatClient::stopClient()
+{
+ delete socket;
+ socket = 0;
+}
+//! [stopClient]
+
+//! [readSocket]
+void ChatClient::readSocket()
+{
+ if (!socket)
+ return;
+
+ while (socket->canReadLine()) {
+ QByteArray line = socket->readLine();
+ emit messageReceived(socket->peerName(),
+ QString::fromUtf8(line.constData(), line.length()));
+ }
+}
+//! [readSocket]
+
+//! [sendMessage]
+void ChatClient::sendMessage(const QString &message)
+{
+ QByteArray text = message.toUtf8() + '\n';
+ socket->write(text);
+}
+//! [sendMessage]
+
+//! [connected]
+void ChatClient::connected()
+{
+ emit connected(socket->peerName());
+}
+//! [connected]
diff --git a/examples/bluetooth/btchat/chatclient.h b/examples/bluetooth/btchat/chatclient.h
new file mode 100644
index 00000000..710634e5
--- /dev/null
+++ b/examples/bluetooth/btchat/chatclient.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Digia Plc and its Subsidiary(-ies) 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$
+**
+****************************************************************************/
+
+#ifndef CHATCLIENT_H
+#define CHATCLIENT_H
+
+#include <qbluetoothserviceinfo.h>
+
+#include <QtCore/QObject>
+
+QTBLUETOOTH_BEGIN_NAMESPACE
+class QBluetoothSocket;
+QTBLUETOOTH_END_NAMESPACE
+
+QTBLUETOOTH_USE_NAMESPACE
+
+//! [declaration]
+class ChatClient : public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit ChatClient(QObject *parent = 0);
+ ~ChatClient();
+
+ void startClient(const QBluetoothServiceInfo &remoteService);
+ void stopClient();
+
+public slots:
+ void sendMessage(const QString &message);
+
+signals:
+ void messageReceived(const QString &sender, const QString &message);
+ void connected(const QString &name);
+ void disconnected();
+
+private slots:
+ void readSocket();
+ void connected();
+
+private:
+ QBluetoothSocket *socket;
+};
+//! [declaration]
+
+#endif // CHATCLIENT_H
diff --git a/examples/bluetooth/btchat/chatserver.cpp b/examples/bluetooth/btchat/chatserver.cpp
new file mode 100644
index 00000000..545a0b03
--- /dev/null
+++ b/examples/bluetooth/btchat/chatserver.cpp
@@ -0,0 +1,182 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Digia Plc and its Subsidiary(-ies) 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 "chatserver.h"
+
+#include <qrfcommserver.h>
+#include <qbluetoothsocket.h>
+
+//! [Service UUID]
+static const QLatin1String serviceUuid("e8e10f95-1a70-4b27-9ccf-02010264e9c8");
+//! [Service UUID]
+
+ChatServer::ChatServer(QObject *parent)
+: QObject(parent), rfcommServer(0)
+{
+}
+
+ChatServer::~ChatServer()
+{
+ stopServer();
+}
+
+void ChatServer::startServer()
+{
+ if (rfcommServer)
+ return;
+
+ //! [Create the server]
+ rfcommServer = new QRfcommServer(this);
+ connect(rfcommServer, SIGNAL(newConnection()), this, SLOT(clientConnected()));
+ rfcommServer->listen();
+ //! [Create the server]
+
+ serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceRecordHandle, (uint)0x00010010);
+
+ //! [Class Uuuid must contain at least 1 entry]
+ QBluetoothServiceInfo::Sequence classId;
+ classId << QVariant::fromValue(QBluetoothUuid(serviceUuid));
+ serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceClassIds, classId);
+ //! [Class Uuuid must contain at least 1 entry]
+
+
+ //! [Service name, description and provider]
+ serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceName, tr("Bt Chat Server"));
+ serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceDescription,
+ tr("Example bluetooth chat server"));
+ serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceProvider, tr("Nokia, QtDF"));
+ //! [Service name, description and provider]
+
+ //! [Service UUID set]
+ serviceInfo.setServiceUuid(QBluetoothUuid(serviceUuid));
+ //! [Service UUID set]
+
+ //! [Service Discoverability]
+ serviceInfo.setAttribute(QBluetoothServiceInfo::BrowseGroupList,
+ QBluetoothUuid(QBluetoothUuid::PublicBrowseGroup));
+ //! [Service Discoverability]
+
+ //! [Protocol descriptor list]
+ QBluetoothServiceInfo::Sequence protocolDescriptorList;
+ QBluetoothServiceInfo::Sequence protocol;
+ protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::L2cap));
+ protocolDescriptorList.append(QVariant::fromValue(protocol));
+ protocol.clear();
+ protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::Rfcomm))
+ << QVariant::fromValue(quint8(rfcommServer->serverPort()));
+ protocolDescriptorList.append(QVariant::fromValue(protocol));
+ serviceInfo.setAttribute(QBluetoothServiceInfo::ProtocolDescriptorList,
+ protocolDescriptorList);
+ //! [Protocol descriptor list]
+
+ //! [Register service]
+ serviceInfo.registerService();
+ //! [Register service]
+}
+
+//! [stopServer]
+void ChatServer::stopServer()
+{
+ // Unregister service
+ serviceInfo.unregisterService();
+
+ // Close sockets
+ qDeleteAll(clientSockets);
+
+ // Close server
+ delete rfcommServer;
+ rfcommServer = 0;
+}
+//! [stopServer]
+
+//! [sendMessage]
+void ChatServer::sendMessage(const QString &message)
+{
+ QByteArray text = message.toUtf8() + '\n';
+
+ foreach (QBluetoothSocket *socket, clientSockets)
+ socket->write(text);
+}
+//! [sendMessage]
+
+//! [clientConnected]
+void ChatServer::clientConnected()
+{
+ QBluetoothSocket *socket = rfcommServer->nextPendingConnection();
+ if (!socket)
+ return;
+
+ connect(socket, SIGNAL(readyRead()), this, SLOT(readSocket()));
+ connect(socket, SIGNAL(disconnected()), this, SLOT(clientDisconnected()));
+ clientSockets.append(socket);
+
+ emit clientConnected(socket->peerName());
+}
+//! [clientConnected]
+
+//! [clientDisconnected]
+void ChatServer::clientDisconnected()
+{
+ QBluetoothSocket *socket = qobject_cast<QBluetoothSocket *>(sender());
+ if (!socket)
+ return;
+
+ emit clientDisconnected(socket->peerName());
+
+ clientSockets.removeOne(socket);
+
+ socket->deleteLater();
+}
+//! [clientDisconnected]
+
+//! [readSocket]
+void ChatServer::readSocket()
+{
+ QBluetoothSocket *socket = qobject_cast<QBluetoothSocket *>(sender());
+ if (!socket)
+ return;
+
+ while (socket->canReadLine()) {
+ QByteArray line = socket->readLine().trimmed();
+ emit messageReceived(socket->peerName(),
+ QString::fromUtf8(line.constData(), line.length()));
+ }
+}
+//! [readSocket]
diff --git a/examples/bluetooth/btchat/chatserver.h b/examples/bluetooth/btchat/chatserver.h
new file mode 100644
index 00000000..ee4728a9
--- /dev/null
+++ b/examples/bluetooth/btchat/chatserver.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Digia Plc and its Subsidiary(-ies) 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$
+**
+****************************************************************************/
+
+#ifndef CHATSERVER_H
+#define CHATSERVER_H
+
+#include <qbluetoothserviceinfo.h>
+
+#include <QtCore/QObject>
+#include <QtCore/QList>
+
+QTBLUETOOTH_BEGIN_NAMESPACE
+class QRfcommServer;
+class QBluetoothSocket;
+QTBLUETOOTH_END_NAMESPACE
+
+QTBLUETOOTH_USE_NAMESPACE
+
+//! [declaration]
+class ChatServer : public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit ChatServer(QObject *parent = 0);
+ ~ChatServer();
+
+ void startServer();
+ void stopServer();
+
+public slots:
+ void sendMessage(const QString &message);
+
+signals:
+ void messageReceived(const QString &sender, const QString &message);
+ void clientConnected(const QString &name);
+ void clientDisconnected(const QString &name);
+
+private slots:
+ void clientConnected();
+ void clientDisconnected();
+ void readSocket();
+
+private:
+ QRfcommServer *rfcommServer;
+ QBluetoothServiceInfo serviceInfo;
+ QList<QBluetoothSocket *> clientSockets;
+};
+//! [declaration]
+
+#endif // CHATSERVER_H
diff --git a/examples/bluetooth/btchat/doc/images/btchat-example.png b/examples/bluetooth/btchat/doc/images/btchat-example.png
new file mode 100644
index 00000000..762d49cb
--- /dev/null
+++ b/examples/bluetooth/btchat/doc/images/btchat-example.png
Binary files differ
diff --git a/examples/bluetooth/btchat/doc/src/btchat.qdoc b/examples/bluetooth/btchat/doc/src/btchat.qdoc
new file mode 100644
index 00000000..20f1ad93
--- /dev/null
+++ b/examples/bluetooth/btchat/doc/src/btchat.qdoc
@@ -0,0 +1,191 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \example btchat
+ \title Bluetooth Chat Example
+
+ The Bluetooth Chat example shows how to use the Qt Connectivity Bluetooth API to communicate
+ with another application on a remote device using Bluetooth.
+
+ \image btchat-example.png
+
+ The Bluetooth Chat example implements a simple chat program between multiple parties. The
+ application always acts as both a server and a client eliminating the need to determine who
+ should connect to whom.
+
+ \section1 Chat Server
+
+ The chat server is implemented by the ChatServer class. The 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.
+
+ \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
+ 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
+ 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.
+
+ \snippet btchat/chatserver.cpp Service name, description and provider
+
+ Bluetooth uses UUIDs as unique identifiers. Our chat service is uses a randomly generated
+ UUID.
+
+ \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.
+
+ \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 port that our rfcommServer instance is listening to.
+
+ \snippet btchat/chatserver.cpp Protocol descriptor list
+
+ Finally we register the service record with the system.
+
+ \snippet btchat/chatserver.cpp Register service
+
+ As mentioned earlier incoming connections are handled in the clientConnected() slot. In this
+ slot we get a pointer a QBluetoothSocket representing the next pending connection connect up
+ slots to the readyRead() and disconnected() signals and emit a signal to 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.
+
+ \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.
+
+ \snippet btchat/chatserver.cpp clientDisconnected
+
+ The 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 stop the service record is removed from the system SDP database, all
+ connected client sockets are deleted and the QRfcommServer instance is deleted.
+
+ \snippet btchat/chatserver.cpp stopServer
+
+ \section1 Chat Client
+
+ The chat client is implemented by the ChatClient class. The 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.
+
+ \snippet btchat/chatclient.cpp startClient
+
+ On sucessfull socket connection we emit a signal to notify other.
+
+ \snippet btchat/chatclient.cpp connected
+
+ Similarily 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.
+
+ \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 appended.
+
+ \snippet btchat/chatclient.cpp sendMessage
+
+ To disconnect from the remote chat service the QBluetoothSocket instance is deleted.
+
+ \snippet btchat/chatclient.cpp stopClient
+
+ \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:
+
+ \snippet btchat/chat.h declaration
+
+ First we construct the user interface
+
+ \snippet btchat/chat.cpp Construct UI
+
+ We create an instance of the ChatServer and respond to its clientConnected(),
+ clientDiconnected() and messageReceived() signals.
+
+ \snippet btchat/chat.cpp Create Chat Server
+
+ In response to the clientConnected() and clientDisconnected() signals of the ChatServer we
+ display the typical "foo has joined chat." and "foo 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.
+
+ \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
+ selected by the user.
+
+ \snippet btchat/chat.cpp Connect to remote service
+
+ In reponse to connected() signals from ChatClient we display the a "Joined chat with foo."
+ 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.
+
+ \snippet btchat/chat.cpp sendClicked
+
+ We need to clean up ChatClient instances when the remote device forces a disconnect.
+
+ \snippet btchat/chat.cpp clientDisconnected
+*/
diff --git a/examples/bluetooth/btchat/main.cpp b/examples/bluetooth/btchat/main.cpp
new file mode 100644
index 00000000..cb32f448
--- /dev/null
+++ b/examples/bluetooth/btchat/main.cpp
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Digia Plc and its Subsidiary(-ies) 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 <QApplication>
+
+int main(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+
+ Chat d;
+ QObject::connect(&d, SIGNAL(accepted()), &app, SLOT(quit()));
+
+#if defined(Q_WS_MAEMO_6)
+ d.showFullScreen();
+#else
+ d.show();
+#endif
+
+ app.exec();
+
+ return 0;
+}
+
diff --git a/examples/bluetooth/btchat/remoteselector.cpp b/examples/bluetooth/btchat/remoteselector.cpp
new file mode 100644
index 00000000..a63c81c2
--- /dev/null
+++ b/examples/bluetooth/btchat/remoteselector.cpp
@@ -0,0 +1,146 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Digia Plc and its Subsidiary(-ies) 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 "remoteselector.h"
+#include "ui_remoteselector.h"
+
+#include <qbluetoothdeviceinfo.h>
+#include <qbluetoothaddress.h>
+
+QTBLUETOOTH_USE_NAMESPACE
+
+RemoteSelector::RemoteSelector(QWidget *parent)
+: QDialog(parent), ui(new Ui::RemoteSelector),
+ m_discoveryAgent(new QBluetoothServiceDiscoveryAgent)
+{
+ ui->setupUi(this);
+
+#if defined(Q_OS_WINCE) || defined(Q_WS_MAEMO_6)
+ setWindowState(Qt::WindowFullScreen);
+#endif
+
+ connect(m_discoveryAgent, SIGNAL(serviceDiscovered(QBluetoothServiceInfo)),
+ this, SLOT(serviceDiscovered(QBluetoothServiceInfo)));
+ connect(m_discoveryAgent, SIGNAL(finished()), this, SLOT(discoveryFinished()));
+}
+
+RemoteSelector::~RemoteSelector()
+{
+ delete ui;
+}
+
+void RemoteSelector::startDiscovery(const QBluetoothUuid &uuid)
+{
+ if (m_discoveryAgent->isActive())
+ m_discoveryAgent->stop();
+
+ ui->remoteDevices->clear();
+
+ m_discoveryAgent->setUuidFilter(uuid);
+ m_discoveryAgent->start();
+
+ ui->status->setText(tr("Scanning..."));
+}
+
+void RemoteSelector::stopDiscovery()
+{
+ if (m_discoveryAgent){
+ m_discoveryAgent->stop();
+ }
+}
+
+QBluetoothServiceInfo RemoteSelector::service() const
+{
+ return m_service;
+}
+
+void RemoteSelector::serviceDiscovered(const QBluetoothServiceInfo &serviceInfo)
+{
+#if 0
+ qDebug() << "Discovered service on"
+ << serviceInfo.device().name() << serviceInfo.device().address().toString();
+ qDebug() << "\tService name:" << serviceInfo.serviceName();
+ qDebug() << "\tDescription:"
+ << serviceInfo.attribute(QBluetoothServiceInfo::ServiceDescription).toString();
+ qDebug() << "\tProvider:"
+ << serviceInfo.attribute(QBluetoothServiceInfo::ServiceProvider).toString();
+ qDebug() << "\tL2CAP protocol service multiplexer:"
+ << serviceInfo.protocolServiceMultiplexer();
+ qDebug() << "\tRFCOMM server channel:" << serviceInfo.serverChannel();
+#endif
+ QMapIterator<QListWidgetItem *, QBluetoothServiceInfo> i(m_discoveredServices);
+ while (i.hasNext()){
+ i.next();
+ if (serviceInfo.device().address() == i.value().device().address()){
+ return;
+ }
+ }
+
+ QString remoteName;
+ if (serviceInfo.device().name().isEmpty())
+ remoteName = serviceInfo.device().address().toString();
+ else
+ remoteName = serviceInfo.device().name();
+
+ QListWidgetItem *item =
+ new QListWidgetItem(QString::fromLatin1("%1 %2").arg(remoteName,
+ serviceInfo.serviceName()));
+
+ m_discoveredServices.insert(item, serviceInfo);
+ ui->remoteDevices->addItem(item);
+}
+
+void RemoteSelector::discoveryFinished()
+{
+ ui->status->setText(tr("Select the chat service to connect to."));
+}
+
+void RemoteSelector::on_remoteDevices_itemActivated(QListWidgetItem *item)
+{
+ qDebug() << "got click" << item->text();
+ m_service = m_discoveredServices.value(item);
+
+ accept();
+}
+
+void RemoteSelector::on_cancelButton_clicked()
+{
+ reject();
+}
diff --git a/examples/bluetooth/btchat/remoteselector.h b/examples/bluetooth/btchat/remoteselector.h
new file mode 100644
index 00000000..eff94895
--- /dev/null
+++ b/examples/bluetooth/btchat/remoteselector.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Digia Plc and its Subsidiary(-ies) 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$
+**
+****************************************************************************/
+
+#ifndef REMOTESELECTOR_H
+#define REMOTESELECTOR_H
+
+#include <QDialog>
+
+#include <qbluetoothuuid.h>
+#include <qbluetoothserviceinfo.h>
+#include <qbluetoothservicediscoveryagent.h>
+
+QT_FORWARD_DECLARE_CLASS(QModelIndex)
+QT_FORWARD_DECLARE_CLASS(QListWidgetItem)
+
+QTBLUETOOTH_USE_NAMESPACE
+
+QT_BEGIN_NAMESPACE
+namespace Ui {
+ class RemoteSelector;
+}
+QT_END_NAMESPACE
+
+class RemoteSelector : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit RemoteSelector(QWidget *parent = 0);
+ ~RemoteSelector();
+
+ void startDiscovery(const QBluetoothUuid &uuid);
+ void stopDiscovery();
+ QBluetoothServiceInfo service() const;
+
+private:
+ Ui::RemoteSelector *ui;
+
+ QBluetoothServiceDiscoveryAgent *m_discoveryAgent;
+ QBluetoothServiceInfo m_service;
+ QMap<QListWidgetItem *, QBluetoothServiceInfo> m_discoveredServices;
+
+private slots:
+ void serviceDiscovered(const QBluetoothServiceInfo &serviceInfo);
+ void discoveryFinished();
+ void on_remoteDevices_itemActivated(QListWidgetItem *item);
+ void on_cancelButton_clicked();
+};
+
+#endif // REMOTESELECTOR_H
diff --git a/examples/bluetooth/btchat/remoteselector.ui b/examples/bluetooth/btchat/remoteselector.ui
new file mode 100644
index 00000000..d415f416
--- /dev/null
+++ b/examples/bluetooth/btchat/remoteselector.ui
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>RemoteSelector</class>
+ <widget class="QDialog" name="RemoteSelector">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>400</width>
+ <height>300</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Available chat services</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLabel" name="status">
+ <property name="text">
+ <string>Scanning...</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QListWidget" name="remoteDevices"/>
+ </item>
+ <item>
+ <widget class="QPushButton" name="cancelButton">
+ <property name="text">
+ <string>Cancel</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/examples/bluetooth/btfiletransfer/btfiletransfer.pro b/examples/bluetooth/btfiletransfer/btfiletransfer.pro
new file mode 100644
index 00000000..bc634193
--- /dev/null
+++ b/examples/bluetooth/btfiletransfer/btfiletransfer.pro
@@ -0,0 +1,27 @@
+TEMPLATE = app
+TARGET = btfiletransfer
+
+QT += concurrent bluetooth widgets
+
+SOURCES = \
+ main.cpp \
+ remoteselector.cpp \
+ progress.cpp \
+ pindisplay.cpp
+
+HEADERS = \
+ remoteselector.h \
+ progress.h \
+ pindisplay.h
+
+FORMS = \
+ remoteselector.ui \
+ progress.ui \
+ pindisplay.ui
+
+OTHER_FILES += \
+ busy.gif \
+ pairing.gif
+
+RESOURCES += \
+ btfiletransfer.qrc
diff --git a/examples/bluetooth/btfiletransfer/btfiletransfer.qrc b/examples/bluetooth/btfiletransfer/btfiletransfer.qrc
new file mode 100644
index 00000000..10697d5b
--- /dev/null
+++ b/examples/bluetooth/btfiletransfer/btfiletransfer.qrc
@@ -0,0 +1,6 @@
+<RCC>
+ <qresource prefix="/icons">
+ <file>busy.gif</file>
+ <file>pairing.gif</file>
+ </qresource>
+</RCC>
diff --git a/examples/bluetooth/btfiletransfer/busy.gif b/examples/bluetooth/btfiletransfer/busy.gif
new file mode 100644
index 00000000..e192ca89
--- /dev/null
+++ b/examples/bluetooth/btfiletransfer/busy.gif
Binary files differ
diff --git a/examples/bluetooth/btfiletransfer/doc/images/btfiletransfer-example.png b/examples/bluetooth/btfiletransfer/doc/images/btfiletransfer-example.png
new file mode 100644
index 00000000..f98241d6
--- /dev/null
+++ b/examples/bluetooth/btfiletransfer/doc/images/btfiletransfer-example.png
Binary files differ
diff --git a/examples/bluetooth/btfiletransfer/doc/src/btfiletransfer.qdoc b/examples/bluetooth/btfiletransfer/doc/src/btfiletransfer.qdoc
new file mode 100644
index 00000000..200b3d6f
--- /dev/null
+++ b/examples/bluetooth/btfiletransfer/doc/src/btfiletransfer.qdoc
@@ -0,0 +1,37 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \example btfiletransfer
+ \title Bluetooth File Transfer Example
+
+ The Bluetooth File Transfer example is an application to transfer files
+ via a bluetooth connection.
+
+ \image btfiletransfer-example.png
+
+*/
diff --git a/examples/bluetooth/btfiletransfer/main.cpp b/examples/bluetooth/btfiletransfer/main.cpp
new file mode 100644
index 00000000..4362c023
--- /dev/null
+++ b/examples/bluetooth/btfiletransfer/main.cpp
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Digia Plc and its Subsidiary(-ies) 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 "remoteselector.h"
+
+#include <QApplication>
+
+int main(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+
+ RemoteSelector d;
+ QObject::connect(&d, SIGNAL(accepted()), &app, SLOT(quit()));
+ d.startDiscovery();
+ d.show();
+
+ app.exec();
+
+ return 0;
+}
+
diff --git a/examples/bluetooth/btfiletransfer/pairing.gif b/examples/bluetooth/btfiletransfer/pairing.gif
new file mode 100644
index 00000000..e147f3ec
--- /dev/null
+++ b/examples/bluetooth/btfiletransfer/pairing.gif
Binary files differ
diff --git a/examples/bluetooth/btfiletransfer/pindisplay.cpp b/examples/bluetooth/btfiletransfer/pindisplay.cpp
new file mode 100644
index 00000000..bdef6b36
--- /dev/null
+++ b/examples/bluetooth/btfiletransfer/pindisplay.cpp
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Digia Plc and its Subsidiary(-ies) 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 "pindisplay.h"
+#include "ui_pindisplay.h"
+
+pinDisplay::pinDisplay(QString title, QString pin, QWidget *parent) :
+ QDialog(parent),
+ ui(new Ui::pinDisplay)
+{
+ ui->setupUi(this);
+ ui->label->setText(title);
+ ui->pin->setText(pin);
+
+ connect(ui->buttonBox, SIGNAL(accepted()), this, SIGNAL(accepted()));
+ connect(ui->buttonBox, SIGNAL(rejected()), this, SIGNAL(rejected()));
+}
+
+pinDisplay::~pinDisplay()
+{
+ delete ui;
+}
+
+void pinDisplay::on_buttonBox_accepted()
+{
+ deleteLater();
+}
+
+void pinDisplay::setOkCancel()
+{
+ ui->buttonBox->addButton(QDialogButtonBox::Cancel);
+}
diff --git a/examples/bluetooth/btfiletransfer/pindisplay.h b/examples/bluetooth/btfiletransfer/pindisplay.h
new file mode 100644
index 00000000..fd1b50aa
--- /dev/null
+++ b/examples/bluetooth/btfiletransfer/pindisplay.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Digia Plc and its Subsidiary(-ies) 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$
+**
+****************************************************************************/
+
+#ifndef PINDISPLAY_H
+#define PINDISPLAY_H
+
+#include <QDialog>
+
+QT_BEGIN_NAMESPACE
+namespace Ui {
+ class pinDisplay;
+}
+QT_END_NAMESPACE
+
+class pinDisplay : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit pinDisplay(QString title, QString pin, QWidget *parent = 0);
+ ~pinDisplay();
+
+ void setOkCancel();
+
+private Q_SLOTS:
+ void on_buttonBox_accepted();
+
+private:
+ Ui::pinDisplay *ui;
+};
+
+#endif // PINDISPLAY_H
diff --git a/examples/bluetooth/btfiletransfer/pindisplay.ui b/examples/bluetooth/btfiletransfer/pindisplay.ui
new file mode 100644
index 00000000..02bf7d50
--- /dev/null
+++ b/examples/bluetooth/btfiletransfer/pindisplay.ui
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>pinDisplay</class>
+ <widget class="QDialog" name="pinDisplay">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>240</width>
+ <height>153</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Enter Pin Code</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLabel" name="pin">
+ <property name="font">
+ <font>
+ <family>Monospace</family>
+ <pointsize>24</pointsize>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>012345</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>TextLabel</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>pinDisplay</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>pinDisplay</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/examples/bluetooth/btfiletransfer/progress.cpp b/examples/bluetooth/btfiletransfer/progress.cpp
new file mode 100644
index 00000000..d589e9b5
--- /dev/null
+++ b/examples/bluetooth/btfiletransfer/progress.cpp
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Digia Plc and its Subsidiary(-ies) 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 "progress.h"
+#include "ui_progress.h"
+
+#include <qbluetoothdeviceinfo.h>
+#include <qbluetoothaddress.h>
+#include <qbluetoothtransferrequest.h>
+#include <qbluetoothtransferreply.h>
+
+QTBLUETOOTH_USE_NAMESPACE
+
+Progress::Progress(QWidget *parent) :
+ QDialog(parent),
+ ui(new Ui::Progress)
+{
+ ui->setupUi(this);
+ ui->progressBar->setRange(0, 1);
+ connect(ui->cancelButton, SIGNAL(clicked()), this, SLOT(close()));
+}
+
+Progress::~Progress()
+{
+ delete ui;
+}
+
+void Progress::setStatus(QString title, QString filename) {
+ ui->titleLabel->setText(title);
+ ui->statusLabel->setText(filename);
+}
+
+void Progress::finished(QBluetoothTransferReply *reply){
+ if (reply->error() != QBluetoothTransferReply::NoError){
+ ui->progressBar->setDisabled(true);
+ ui->statusLabel->setText(tr("Failed: %1").arg(reply->errorString()));
+ }
+ else {
+ ui->statusLabel->setText(tr("Transfer complete"));
+ }
+ ui->cancelButton->setText(tr("Dismiss"));
+}
+
+void Progress::uploadProgress(qint64 bytesSent, qint64 bytesTotal)
+{
+ if (bytesSent == 0){
+ start.start();
+ }
+
+ ui->progressBar->setMaximum(bytesTotal);
+ ui->progressBar->setValue(bytesSent);
+ if (bytesSent && bytesTotal &&
+ (start.elapsed() > 1000) &&
+ (bytesSent > start.elapsed()/1000)) {
+
+ ui->statusLabel->setText(tr("Transferring...ETA: %1s")
+ .arg(((bytesTotal-bytesSent)/(bytesSent/(start.elapsed()/1000)))));
+ }
+}
+
diff --git a/examples/bluetooth/btfiletransfer/progress.h b/examples/bluetooth/btfiletransfer/progress.h
new file mode 100644
index 00000000..400c9b70
--- /dev/null
+++ b/examples/bluetooth/btfiletransfer/progress.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Digia Plc and its Subsidiary(-ies) 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$
+**
+****************************************************************************/
+
+#ifndef PROGRESS_H
+#define PROGRESS_H
+
+#include <QDialog>
+#include <qbluetoothglobal.h>
+#include <QTime>
+
+QTBLUETOOTH_BEGIN_NAMESPACE
+class QBluetoothTransferReply;
+QTBLUETOOTH_END_NAMESPACE
+
+QTBLUETOOTH_USE_NAMESPACE
+
+QT_BEGIN_NAMESPACE
+namespace Ui {
+ class Progress;
+}
+QT_END_NAMESPACE
+
+class Progress : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit Progress(QWidget *parent = 0);
+ ~Progress();
+
+ void setStatus(QString title, QString filename);
+
+public Q_SLOTS:
+ void finished(QBluetoothTransferReply *);
+ void uploadProgress(qint64 bytesSent, qint64 bytesTotal);
+
+private:
+ Ui::Progress *ui;
+
+ QTime start;
+};
+
+#endif // PROGRESS_H
diff --git a/examples/bluetooth/btfiletransfer/progress.ui b/examples/bluetooth/btfiletransfer/progress.ui
new file mode 100644
index 00000000..3b151f06
--- /dev/null
+++ b/examples/bluetooth/btfiletransfer/progress.ui
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Progress</class>
+ <widget class="QDialog" name="Progress">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>408</width>
+ <height>115</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Transfer Progress</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLabel" name="titleLabel">
+ <property name="text">
+ <string>Filename</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QProgressBar" name="progressBar">
+ <property name="minimumSize">
+ <size>
+ <width>390</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="value">
+ <number>24</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="statusLabel">
+ <property name="text">
+ <string>Status</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="cancelButton">
+ <property name="text">
+ <string>Cancel</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/examples/bluetooth/btfiletransfer/remoteselector.cpp b/examples/bluetooth/btfiletransfer/remoteselector.cpp
new file mode 100644
index 00000000..80d8761e
--- /dev/null
+++ b/examples/bluetooth/btfiletransfer/remoteselector.cpp
@@ -0,0 +1,372 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Digia Plc and its Subsidiary(-ies) 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 "remoteselector.h"
+#include "ui_remoteselector.h"
+
+#include <qbluetoothdeviceinfo.h>
+#include <qbluetoothaddress.h>
+#include <qbluetoothtransferrequest.h>
+#include <qbluetoothtransferreply.h>
+#include <qbluetoothlocaldevice.h>
+
+#include <QMovie>
+#include <QMessageBox>
+#include <QFileDialog>
+#include <QCheckBox>
+
+#include "progress.h"
+#include "pindisplay.h"
+
+QTBLUETOOTH_USE_NAMESPACE
+
+RemoteSelector::RemoteSelector(QWidget *parent)
+: QDialog(parent), ui(new Ui::RemoteSelector),
+ m_discoveryAgent(new QBluetoothServiceDiscoveryAgent), m_localDevice(new QBluetoothLocalDevice), m_pindisplay(0)
+{
+ ui->setupUi(this);
+
+ connect(m_discoveryAgent, SIGNAL(serviceDiscovered(QBluetoothServiceInfo)),
+ this, SLOT(serviceDiscovered(QBluetoothServiceInfo)));
+ connect(m_discoveryAgent, SIGNAL(finished()), this, SLOT(discoveryFinished()));
+
+ ui->remoteDevices->setColumnWidth(3, 75);
+ ui->remoteDevices->setColumnWidth(4, 100);
+
+ connect(m_localDevice, SIGNAL(pairingDisplayPinCode(const QBluetoothAddress &,QString)), this, SLOT(displayPin(const QBluetoothAddress &, QString)));
+ connect(m_localDevice, SIGNAL(pairingDisplayConfirmation(QBluetoothAddress,QString)), this, SLOT(displayConfirmation(QBluetoothAddress,QString)));
+ connect(m_localDevice, SIGNAL(pairingFinished(QBluetoothAddress,QBluetoothLocalDevice::Pairing)), this, SLOT(pairingFinished(QBluetoothAddress,QBluetoothLocalDevice::Pairing)));
+
+ ui->busyWidget->setMovie(new QMovie(":/icons/busy.gif"));
+ ui->busyWidget->movie()->start();
+
+ ui->pairingBusy->setMovie(new QMovie(":/icons/pairing.gif"));
+ ui->pairingBusy->hide();
+
+ ui->remoteDevices->clearContents();
+ ui->remoteDevices->setRowCount(0);
+
+
+}
+
+RemoteSelector::~RemoteSelector()
+{
+ delete ui;
+ delete m_discoveryAgent;
+ delete m_localDevice;
+}
+
+void RemoteSelector::startDiscovery(const QBluetoothUuid &uuid)
+{
+ ui->stopButton->setDisabled(false);
+ if (m_discoveryAgent->isActive())
+ m_discoveryAgent->stop();
+
+ m_discoveryAgent->setUuidFilter(uuid);
+ m_discoveryAgent->start();
+
+ ui->status->setText(tr("Scanning..."));
+ ui->busyWidget->show();
+ ui->busyWidget->movie()->start();
+}
+
+QBluetoothServiceInfo RemoteSelector::service() const
+{
+ return m_service;
+}
+
+void RemoteSelector::serviceDiscovered(const QBluetoothServiceInfo &serviceInfo)
+{
+#if 0
+ qDebug() << "Discovered service on"
+ << serviceInfo.device().name() << serviceInfo.device().address().toString();
+ qDebug() << "\tService name:" << serviceInfo.serviceName();
+ qDebug() << "\tDescription:"
+ << serviceInfo.attribute(QBluetoothServiceInfo::ServiceDescription).toString();
+ qDebug() << "\tProvider:"
+ << serviceInfo.attribute(QBluetoothServiceInfo::ServiceProvider).toString();
+ qDebug() << "\tL2CAP protocol service multiplexer:"
+ << serviceInfo.protocolServiceMultiplexer();
+ qDebug() << "\tRFCOMM server channel:" << serviceInfo.serverChannel();
+#endif
+
+ QString remoteName;
+ if (serviceInfo.device().name().isEmpty())
+ remoteName = serviceInfo.device().address().toString();
+ else
+ remoteName = serviceInfo.device().name();
+
+// QListWidgetItem *item =
+// new QListWidgetItem(QString::fromLatin1("%1\t%2\t%3").arg(serviceInfo.device().address().toString(),
+// serviceInfo.device().name(), serviceInfo.serviceName()));
+
+ QMutableMapIterator<int, QBluetoothServiceInfo> i(m_discoveredServices);
+ while (i.hasNext()){
+ i.next();
+ if (serviceInfo.device().address() == i.value().device().address()){
+ i.setValue(serviceInfo);
+ return;
+ }
+ }
+
+ int row = ui->remoteDevices->rowCount();
+ ui->remoteDevices->insertRow(row);
+ QTableWidgetItem *item = new QTableWidgetItem(serviceInfo.device().address().toString());
+ ui->remoteDevices->setItem(row, 0, item);
+ item = new QTableWidgetItem(serviceInfo.device().name());
+ ui->remoteDevices->setItem(row, 1, item);
+ item = new QTableWidgetItem(serviceInfo.serviceName());
+
+ ui->remoteDevices->setItem(row, 2, item);
+
+ QBluetoothLocalDevice::Pairing p;
+
+ p = m_localDevice->pairingStatus(serviceInfo.device().address());
+
+ ui->remoteDevices->blockSignals(true);
+
+ item = new QTableWidgetItem();
+ if ((p&QBluetoothLocalDevice::Paired) || (p&QBluetoothLocalDevice::AuthorizedPaired))
+ item->setCheckState(Qt::Checked);
+ else
+ item->setCheckState(Qt::Unchecked);
+ ui->remoteDevices->setItem(row, 3, item);
+
+ item = new QTableWidgetItem();
+ if (p&QBluetoothLocalDevice::AuthorizedPaired)
+ item->setCheckState(Qt::Checked);
+ else
+ item->setCheckState(Qt::Unchecked);
+
+ ui->remoteDevices->setItem(row, 4, item);
+
+ ui->remoteDevices->blockSignals(false);
+
+
+ m_discoveredServices.insert(row, serviceInfo);
+}
+
+void RemoteSelector::discoveryFinished()
+{
+ ui->status->setText(tr("Select the device to send to."));
+ ui->stopButton->setDisabled(true);
+ ui->busyWidget->movie()->stop();
+ ui->busyWidget->hide();
+}
+
+void RemoteSelector::startDiscovery()
+{
+ startDiscovery(QBluetoothUuid(QBluetoothUuid::ObexObjectPush));
+}
+
+void RemoteSelector::on_refreshPB_clicked()
+{
+ startDiscovery();
+ ui->stopButton->setDisabled(false);
+}
+
+void RemoteSelector::on_fileSelectPB_clicked()
+{
+ ui->fileName->setText(QFileDialog::getOpenFileName());
+ if (m_service.isValid())
+ ui->sendButton->setDisabled(false);
+}
+
+void RemoteSelector::on_sendButton_clicked()
+{
+ QBluetoothTransferManager mgr;
+ QBluetoothTransferRequest req(m_service.device().address());
+
+ m_file = new QFile(ui->fileName->text());
+
+ Progress *p = new Progress;
+ p->setStatus("Sending to: " + m_service.device().name(), "Waiting for start");
+ p->show();
+
+ QBluetoothTransferReply *reply = mgr.put(req, m_file);
+ if (reply->error()){
+ qDebug() << "Failed to send file";
+ delete reply;
+ p->finished(reply);
+ return;
+ }
+
+ connect(reply, SIGNAL(uploadProgress(qint64,qint64)), p, SLOT(uploadProgress(qint64,qint64)));
+ connect(reply, SIGNAL(finished(QBluetoothTransferReply*)), p, SLOT(finished(QBluetoothTransferReply*)));
+ connect(p, SIGNAL(rejected()), reply, SLOT(abort()));
+}
+
+void RemoteSelector::on_stopButton_clicked()
+{
+ m_discoveryAgent->stop();
+}
+
+QString RemoteSelector::addressToName(const QBluetoothAddress &address)
+{
+ QMapIterator<int, QBluetoothServiceInfo> i(m_discoveredServices);
+ while (i.hasNext()){
+ i.next();
+ if (i.value().device().address() == address)
+ return i.value().device().name();
+ }
+ return address.toString();
+}
+
+void RemoteSelector::displayPin(const QBluetoothAddress &address, QString pin)
+{
+ if (m_pindisplay)
+ m_pindisplay->deleteLater();
+ m_pindisplay = new pinDisplay(QString("Enter pairing pin on: %1").arg(addressToName(address)), pin, this);
+ m_pindisplay->show();
+}
+
+void RemoteSelector::displayConfirmation(const QBluetoothAddress &address, QString pin)
+{
+ Q_UNUSED(address);
+
+ if (m_pindisplay)
+ m_pindisplay->deleteLater();
+ m_pindisplay = new pinDisplay(QString("Confirm this pin is the same"), pin, this);
+ connect(m_pindisplay, SIGNAL(accepted()), this, SLOT(displayConfAccepted()));
+ connect(m_pindisplay, SIGNAL(rejected()), this, SLOT(displayConfReject()));
+ m_pindisplay->setOkCancel();
+ m_pindisplay->show();
+}
+
+void RemoteSelector::displayConfAccepted()
+{
+ m_localDevice->pairingConfirmation(true);
+}
+void RemoteSelector::displayConfReject()
+{
+ m_localDevice->pairingConfirmation(false);
+}
+
+void RemoteSelector::pairingFinished(const QBluetoothAddress &address, QBluetoothLocalDevice::Pairing status)
+{
+ QBluetoothServiceInfo service;
+ int row = 0;
+
+ ui->pairingBusy->hide();
+ ui->pairingBusy->movie()->stop();
+
+ ui->remoteDevices->blockSignals(true);
+
+ for (int i = 0; i < m_discoveredServices.count(); i++){
+ if (m_discoveredServices.value(i).device().address() == address){
+ service = m_discoveredServices.value(i);
+ row = i;
+ break;
+ }
+ }
+
+ if (m_pindisplay)
+ delete m_pindisplay;
+
+ QMessageBox msgBox;
+ if (status == QBluetoothLocalDevice::Paired ||
+ status == QBluetoothLocalDevice::AuthorizedPaired){
+ msgBox.setText("Paired successfully with" + address.toString());
+ }
+ else {
+ msgBox.setText("Pairing failed with " + address.toString());
+ }
+
+ if (service.isValid()){
+ if (status == QBluetoothLocalDevice::AuthorizedPaired){
+ ui->remoteDevices->item(row, 3)->setCheckState(Qt::Checked);
+ ui->remoteDevices->item(row, 4)->setCheckState(Qt::Checked);
+ }
+ else if (status == QBluetoothLocalDevice::Paired){
+ ui->remoteDevices->item(row, 3)->setCheckState(Qt::Checked);
+ ui->remoteDevices->item(row, 4)->setCheckState(Qt::Unchecked);
+ }
+ else {
+ ui->remoteDevices->item(row, 3)->setCheckState(Qt::Unchecked);
+ ui->remoteDevices->item(row, 4)->setCheckState(Qt::Unchecked);
+ }
+ }
+
+ msgBox.exec();
+
+ ui->remoteDevices->blockSignals(false);
+
+
+}
+
+void RemoteSelector::on_remoteDevices_cellClicked(int row, int column)
+{
+ Q_UNUSED(column);
+
+ m_service = m_discoveredServices.value(row);
+ if (!ui->fileName->text().isEmpty()) {
+ ui->sendButton->setDisabled(false);
+ }
+}
+
+void RemoteSelector::on_remoteDevices_itemChanged(QTableWidgetItem* item)
+{
+ int row = item->row();
+ int column = item->column();
+ m_service = m_discoveredServices.value(row);
+
+ if (column < 3)
+ return;
+
+ if (item->checkState() == Qt::Unchecked && column == 3){
+ m_localDevice->requestPairing(m_service.device().address(), QBluetoothLocalDevice::Unpaired);
+ return; // don't continue and start movie
+ }
+ else if ((item->checkState() == Qt::Checked && column == 3) ||
+ (item->checkState() == Qt::Unchecked && column == 4)){
+ m_localDevice->requestPairing(m_service.device().address(), QBluetoothLocalDevice::Paired);
+ ui->remoteDevices->blockSignals(true);
+ ui->remoteDevices->item(row, column)->setCheckState(Qt::PartiallyChecked);
+ ui->remoteDevices->blockSignals(false);
+ }
+ else if (item->checkState() == Qt::Checked && column == 4){
+ m_localDevice->requestPairing(m_service.device().address(), QBluetoothLocalDevice::AuthorizedPaired);
+ ui->remoteDevices->blockSignals(true);
+ ui->remoteDevices->item(row, column)->setCheckState(Qt::PartiallyChecked);
+ ui->remoteDevices->blockSignals(false);
+ }
+ ui->pairingBusy->show();
+ ui->pairingBusy->movie()->start();
+}
diff --git a/examples/bluetooth/btfiletransfer/remoteselector.h b/examples/bluetooth/btfiletransfer/remoteselector.h
new file mode 100644
index 00000000..d3300c9a
--- /dev/null
+++ b/examples/bluetooth/btfiletransfer/remoteselector.h
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Digia Plc and its Subsidiary(-ies) 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$
+**
+****************************************************************************/
+
+#ifndef REMOTESELECTOR_H
+#define REMOTESELECTOR_H
+
+#include <QDialog>
+#include <QPointer>
+
+#include <qbluetoothuuid.h>
+#include <qbluetoothserviceinfo.h>
+#include <qbluetoothservicediscoveryagent.h>
+#include <qbluetoothlocaldevice.h>
+
+QT_FORWARD_DECLARE_CLASS(QModelIndex)
+QT_FORWARD_DECLARE_CLASS(QTableWidgetItem)
+QT_FORWARD_DECLARE_CLASS(QFile)
+
+class pinDisplay;
+
+QTBLUETOOTH_USE_NAMESPACE
+
+QT_BEGIN_NAMESPACE
+namespace Ui {
+ class RemoteSelector;
+}
+QT_END_NAMESPACE
+
+class RemoteSelector : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit RemoteSelector(QWidget *parent = 0);
+ ~RemoteSelector();
+
+ void startDiscovery(const QBluetoothUuid &uuid);
+ QBluetoothServiceInfo service() const;
+
+private:
+ Ui::RemoteSelector *ui;
+
+ QBluetoothServiceDiscoveryAgent *m_discoveryAgent;
+ QBluetoothServiceInfo m_service;
+ QMap<int, QBluetoothServiceInfo> m_discoveredServices;
+ QFile *m_file;
+ QBluetoothLocalDevice *m_localDevice;
+ QPointer<pinDisplay> m_pindisplay;
+
+ QString addressToName(const QBluetoothAddress &address);
+
+public Q_SLOTS:
+ void startDiscovery();
+
+private slots:
+ void serviceDiscovered(const QBluetoothServiceInfo &serviceInfo);
+ void discoveryFinished();
+ void on_refreshPB_clicked();
+ void on_fileSelectPB_clicked();
+ void on_sendButton_clicked();
+ void on_stopButton_clicked();
+
+ void pairingFinished(const QBluetoothAddress &address,QBluetoothLocalDevice::Pairing pairing);
+ void displayPin(const QBluetoothAddress &address, QString pin);
+ void displayConfirmation(const QBluetoothAddress &address, QString pin);
+ void displayConfReject();
+ void displayConfAccepted();
+
+ void on_remoteDevices_cellClicked(int row, int column);
+ void on_remoteDevices_itemChanged(QTableWidgetItem* item);
+};
+
+#endif // REMOTESELECTOR_H
diff --git a/examples/bluetooth/btfiletransfer/remoteselector.ui b/examples/bluetooth/btfiletransfer/remoteselector.ui
new file mode 100644
index 00000000..f99deaa7
--- /dev/null
+++ b/examples/bluetooth/btfiletransfer/remoteselector.ui
@@ -0,0 +1,214 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>RemoteSelector</class>
+ <widget class="QDialog" name="RemoteSelector">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>681</width>
+ <height>394</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Available file transfer services</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QGridLayout" name="gridLayout">
+ <property name="horizontalSpacing">
+ <number>6</number>
+ </property>
+ <item row="7" column="0" colspan="2">
+ <widget class="QLineEdit" name="fileName"/>
+ </item>
+ <item row="7" column="2">
+ <widget class="QPushButton" name="fileSelectPB">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Select File</string>
+ </property>
+ </widget>
+ </item>
+ <item row="8" column="0" colspan="3">
+ <widget class="QPushButton" name="sendButton">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Send</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0" colspan="3">
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QLabel" name="busyWidget">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>16</width>
+ <height>16</height>
+ </size>
+ </property>
+ <property name="baseSize">
+ <size>
+ <width>16</width>
+ <height>16</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>TextLabel</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="status">
+ <property name="text">
+ <string>Scanning...</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="pairingBusy">
+ <property name="text">
+ <string>TextLabel</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="stopButton">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Stop</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="refreshPB">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Refresh</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="6" column="0" colspan="3">
+ <widget class="QTableWidget" name="remoteDevices">
+ <property name="horizontalScrollBarPolicy">
+ <enum>Qt::ScrollBarAsNeeded</enum>
+ </property>
+ <property name="editTriggers">
+ <set>QAbstractItemView::NoEditTriggers</set>
+ </property>
+ <property name="showDropIndicator" stdset="0">
+ <bool>false</bool>
+ </property>
+ <property name="alternatingRowColors">
+ <bool>true</bool>
+ </property>
+ <property name="selectionMode">
+ <enum>QAbstractItemView::SingleSelection</enum>
+ </property>
+ <property name="selectionBehavior">
+ <enum>QAbstractItemView::SelectRows</enum>
+ </property>
+ <property name="showGrid">
+ <bool>false</bool>
+ </property>
+ <property name="wordWrap">
+ <bool>false</bool>
+ </property>
+ <property name="rowCount">
+ <number>1</number>
+ </property>
+ <attribute name="horizontalHeaderCascadingSectionResizes">
+ <bool>true</bool>
+ </attribute>
+ <attribute name="horizontalHeaderDefaultSectionSize">
+ <number>150</number>
+ </attribute>
+ <attribute name="horizontalHeaderStretchLastSection">
+ <bool>true</bool>
+ </attribute>
+ <attribute name="verticalHeaderVisible">
+ <bool>false</bool>
+ </attribute>
+ <attribute name="verticalHeaderCascadingSectionResizes">
+ <bool>false</bool>
+ </attribute>
+ <row>
+ <property name="text">
+ <string>Test</string>
+ </property>
+ </row>
+ <column>
+ <property name="text">
+ <string>MAC Address</string>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Device Name</string>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Device Service</string>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Paired</string>
+ </property>
+ <property name="toolTip">
+ <string comment="Paired" extracomment="Paired"/>
+ </property>
+ <property name="whatsThis">
+ <string comment="Paired" extracomment="Paired"/>
+ </property>
+ <property name="textAlignment">
+ <set>AlignHCenter|AlignVCenter|AlignCenter</set>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Authorized</string>
+ </property>
+ <property name="textAlignment">
+ <set>AlignHCenter|AlignVCenter|AlignCenter</set>
+ </property>
+ </column>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/examples/bluetooth/btscanner/btscanner.pro b/examples/bluetooth/btscanner/btscanner.pro
new file mode 100644
index 00000000..cc4675b2
--- /dev/null
+++ b/examples/bluetooth/btscanner/btscanner.pro
@@ -0,0 +1,18 @@
+TARGET = btscanner
+
+QT += concurrent bluetooth widgets
+TEMPLATE = app
+
+SOURCES = \
+ main.cpp \
+ device.cpp \
+ service.cpp
+
+HEADERS = \
+ device.h \
+ service.h
+
+FORMS = \
+ device.ui \
+ service.ui
+
diff --git a/examples/bluetooth/btscanner/device.cpp b/examples/bluetooth/btscanner/device.cpp
new file mode 100644
index 00000000..33b96dc3
--- /dev/null
+++ b/examples/bluetooth/btscanner/device.cpp
@@ -0,0 +1,211 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Digia Plc and its Subsidiary(-ies) 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 "device.h"
+#include "service.h"
+
+#include <qbluetoothaddress.h>
+#include <qbluetoothdevicediscoveryagent.h>
+#include <qbluetoothlocaldevice.h>
+#include <QMenu>
+#include <QDebug>
+
+DeviceDiscoveryDialog::DeviceDiscoveryDialog(QWidget *parent)
+: QDialog(parent), discoveryAgent(new QBluetoothDeviceDiscoveryAgent),
+ localDevice(new QBluetoothLocalDevice),
+ ui(new Ui_DeviceDiscovery)
+{
+ ui->setupUi(this);
+
+#if defined(Q_OS_WINCE) || defined(Q_WS_MAEMO_6)
+ setWindowState(Qt::WindowFullScreen);
+#endif
+
+ connect(ui->inquiryType, SIGNAL(toggled(bool)), this, SLOT(setGeneralUnlimited(bool)));
+ connect(ui->scan, SIGNAL(clicked()), this, SLOT(startScan()));
+
+ connect(discoveryAgent, SIGNAL(deviceDiscovered(const QBluetoothDeviceInfo&)),
+ this, SLOT(addDevice(const QBluetoothDeviceInfo&)));
+ connect(discoveryAgent, SIGNAL(finished()), this, SLOT(scanFinished()));
+
+ connect(ui->list, SIGNAL(itemActivated(QListWidgetItem*)),
+ this, SLOT(itemActivated(QListWidgetItem*)));
+
+ connect(localDevice, SIGNAL(hostModeStateChanged(QBluetoothLocalDevice::HostMode)),
+ this, SLOT(hostModeStateChanged(QBluetoothLocalDevice::HostMode)));
+
+ hostModeStateChanged(localDevice->hostMode());
+ // add context menu for devices to be able to pair device
+ ui->list->setContextMenuPolicy(Qt::CustomContextMenu);
+ connect(ui->list, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(displayPairingMenu(QPoint)));
+ connect(localDevice, SIGNAL(pairingFinished(const QBluetoothAddress&, QBluetoothLocalDevice::Pairing))
+ , this, SLOT(pairingDone(const QBluetoothAddress&, QBluetoothLocalDevice::Pairing)));
+
+}
+
+DeviceDiscoveryDialog::~DeviceDiscoveryDialog()
+{
+ delete discoveryAgent;
+}
+
+void DeviceDiscoveryDialog::addDevice(const QBluetoothDeviceInfo &info)
+{
+ QString label = QString("%1 %2").arg(info.address().toString()).arg(info.name());
+ QList<QListWidgetItem *> items = ui->list->findItems(label, Qt::MatchExactly);
+ if (items.empty()) {
+ QListWidgetItem *item = new QListWidgetItem(label);
+ QBluetoothLocalDevice::Pairing pairingStatus = localDevice->pairingStatus(info.address());
+ if (pairingStatus == QBluetoothLocalDevice::Paired || pairingStatus == QBluetoothLocalDevice::AuthorizedPaired )
+ item->setTextColor(QColor(Qt::green));
+ else
+ item->setTextColor(QColor(Qt::black));
+
+ ui->list->addItem(item);
+ }
+
+}
+
+void DeviceDiscoveryDialog::startScan()
+{
+ discoveryAgent->start();
+ ui->scan->setEnabled(false);
+ ui->inquiryType->setEnabled(false);
+}
+
+void DeviceDiscoveryDialog::scanFinished()
+{
+ ui->scan->setEnabled(true);
+ ui->inquiryType->setEnabled(true);
+}
+
+void DeviceDiscoveryDialog::setGeneralUnlimited(bool unlimited)
+{
+ if (unlimited)
+ discoveryAgent->setInquiryType(QBluetoothDeviceDiscoveryAgent::GeneralUnlimitedInquiry);
+ else
+ discoveryAgent->setInquiryType(QBluetoothDeviceDiscoveryAgent::LimitedInquiry);
+}
+
+void DeviceDiscoveryDialog::itemActivated(QListWidgetItem *item)
+{
+ QString text = item->text();
+
+ int 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)
+{
+ if (mode != QBluetoothLocalDevice::HostPoweredOff)
+ ui->power->setChecked(true);
+ else
+ ui->power->setChecked( false);
+
+ if (mode == QBluetoothLocalDevice::HostDiscoverable)
+ ui->discoverable->setChecked(true);
+ else
+ ui->discoverable->setChecked(false);
+
+ bool on = !(mode == QBluetoothLocalDevice::HostPoweredOff);
+
+
+ ui->scan->setEnabled(on);
+ ui->discoverable->setEnabled(on);
+}
+void DeviceDiscoveryDialog::displayPairingMenu(const QPoint &pos)
+{
+ 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();
+ int 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)
+{
+ QList<QListWidgetItem *> items = ui->list->findItems(address.toString(), Qt::MatchContains);
+
+ if (pairing == QBluetoothLocalDevice::Paired || pairing == QBluetoothLocalDevice::AuthorizedPaired ) {
+ for (int var = 0; var < items.count(); ++var) {
+ QListWidgetItem *item = items.at(var);
+ item->setTextColor(QColor(Qt::green));
+ }
+ } else {
+ for (int var = 0; var < items.count(); ++var) {
+ QListWidgetItem *item = items.at(var);
+ item->setTextColor(QColor(Qt::red));
+ }
+ }
+}
diff --git a/examples/bluetooth/btscanner/device.h b/examples/bluetooth/btscanner/device.h
new file mode 100644
index 00000000..af2d9a7f
--- /dev/null
+++ b/examples/bluetooth/btscanner/device.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Digia Plc and its Subsidiary(-ies) 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$
+**
+****************************************************************************/
+
+#ifndef DEVICE_H
+#define DEVICE_H
+
+#include "ui_device.h"
+
+#include <qbluetoothglobal.h>
+#include <qbluetoothlocaldevice.h>
+
+#include <QDialog>
+
+QTBLUETOOTH_BEGIN_NAMESPACE
+class QBluetoothDeviceDiscoveryAgent;
+class QBluetoothDeviceInfo;
+QTBLUETOOTH_END_NAMESPACE
+
+QTBLUETOOTH_USE_NAMESPACE
+
+class DeviceDiscoveryDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ DeviceDiscoveryDialog(QWidget *parent = 0);
+ ~DeviceDiscoveryDialog();
+
+public slots:
+ void addDevice(const QBluetoothDeviceInfo&);
+ void on_power_clicked(bool clicked);
+ void on_discoverable_clicked(bool clicked);
+ void displayPairingMenu(const QPoint &pos);
+ void pairingDone(const QBluetoothAddress&, QBluetoothLocalDevice::Pairing);
+private slots:
+ void startScan();
+ void scanFinished();
+ void setGeneralUnlimited(bool unlimited);
+ void itemActivated(QListWidgetItem *item);
+ void hostModeStateChanged(QBluetoothLocalDevice::HostMode);
+
+private:
+ QBluetoothDeviceDiscoveryAgent *discoveryAgent;
+ QBluetoothLocalDevice *localDevice;
+ Ui_DeviceDiscovery *ui;
+};
+
+#endif
diff --git a/examples/bluetooth/btscanner/device.ui b/examples/bluetooth/btscanner/device.ui
new file mode 100644
index 00000000..1f62dd96
--- /dev/null
+++ b/examples/bluetooth/btscanner/device.ui
@@ -0,0 +1,121 @@
+<?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>
+ <widget class="QCheckBox" name="inquiryType">
+ <property name="text">
+ <string>General Unlimited Inquiry</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </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="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/examples/bluetooth/btscanner/doc/images/btscanner-example.png b/examples/bluetooth/btscanner/doc/images/btscanner-example.png
new file mode 100644
index 00000000..04fe9f3c
--- /dev/null
+++ b/examples/bluetooth/btscanner/doc/images/btscanner-example.png
Binary files differ
diff --git a/examples/bluetooth/btscanner/doc/src/btscanner.qdoc b/examples/bluetooth/btscanner/doc/src/btscanner.qdoc
new file mode 100644
index 00000000..f5ee3e3a
--- /dev/null
+++ b/examples/bluetooth/btscanner/doc/src/btscanner.qdoc
@@ -0,0 +1,36 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \example btscanner
+ \title Bluetooth Scanner Example
+
+ An example of how to locate Bluetooth devices.
+
+ \image btscanner-example.png
+
+*/
diff --git a/examples/bluetooth/btscanner/main.cpp b/examples/bluetooth/btscanner/main.cpp
new file mode 100644
index 00000000..e185ffca
--- /dev/null
+++ b/examples/bluetooth/btscanner/main.cpp
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Digia Plc and its Subsidiary(-ies) 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 "device.h"
+
+#include <QApplication>
+
+int main(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+
+ DeviceDiscoveryDialog d;
+ QObject::connect(&d, SIGNAL(accepted()), &app, SLOT(quit()));
+ d.show();
+
+ app.exec();
+
+ return 0;
+}
+
diff --git a/examples/bluetooth/btscanner/service.cpp b/examples/bluetooth/btscanner/service.cpp
new file mode 100644
index 00000000..daadb2b2
--- /dev/null
+++ b/examples/bluetooth/btscanner/service.cpp
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Digia Plc and its Subsidiary(-ies) 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 "service.h"
+
+#include <qbluetoothaddress.h>
+#include <qbluetoothservicediscoveryagent.h>
+#include <qbluetoothserviceinfo.h>
+
+
+ServiceDiscoveryDialog::ServiceDiscoveryDialog(const QString &name,
+ const QBluetoothAddress &address, QWidget *parent)
+: QDialog(parent), discoveryAgent(new QBluetoothServiceDiscoveryAgent(address)),
+ ui(new Ui_ServiceDiscovery)
+{
+ ui->setupUi(this);
+
+#if defined(Q_OS_WINCE) || defined(Q_WS_MAEMO_6)
+ setWindowState(Qt::WindowMaximized);
+#endif
+
+ setWindowTitle(name);
+
+ connect(discoveryAgent, SIGNAL(serviceDiscovered(const QBluetoothServiceInfo&)),
+ this, SLOT(addService(const QBluetoothServiceInfo&)));
+ connect(discoveryAgent, SIGNAL(finished()), ui->status, SLOT(hide()));
+
+ discoveryAgent->start();
+}
+
+ServiceDiscoveryDialog::~ServiceDiscoveryDialog()
+{
+ delete discoveryAgent;
+ 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/examples/bluetooth/btscanner/service.h b/examples/bluetooth/btscanner/service.h
new file mode 100644
index 00000000..0e17aa14
--- /dev/null
+++ b/examples/bluetooth/btscanner/service.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Digia Plc and its Subsidiary(-ies) 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$
+**
+****************************************************************************/
+
+#ifndef SERVICE_H
+#define SERVICE_H
+
+#include "ui_service.h"
+
+#include <qbluetoothglobal.h>
+
+#include <QDialog>
+
+QTBLUETOOTH_BEGIN_NAMESPACE
+class QBluetoothServiceDiscoveryAgent;
+class QBluetoothServiceInfo;
+class QBluetoothAddress;
+QTBLUETOOTH_END_NAMESPACE
+
+QTBLUETOOTH_USE_NAMESPACE
+
+class ServiceDiscoveryDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ ServiceDiscoveryDialog(const QString &name, const QBluetoothAddress &address, QWidget *parent = 0);
+ ~ServiceDiscoveryDialog();
+
+public slots:
+ void addService(const QBluetoothServiceInfo&);
+
+private:
+ QBluetoothServiceDiscoveryAgent *discoveryAgent;
+ Ui_ServiceDiscovery *ui;
+};
+
+#endif
diff --git a/examples/bluetooth/btscanner/service.ui b/examples/bluetooth/btscanner/service.ui
new file mode 100644
index 00000000..68ebc5dc
--- /dev/null
+++ b/examples/bluetooth/btscanner/service.ui
@@ -0,0 +1,76 @@
+<?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>400</width>
+ <height>300</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>
+ <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="close">
+ <property name="text">
+ <string>Close</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <tabstops>
+ <tabstop>list</tabstop>
+ <tabstop>close</tabstop>
+ </tabstops>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>close</sender>
+ <signal>clicked()</signal>
+ <receiver>ServiceDiscovery</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>350</x>
+ <y>277</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>237</x>
+ <y>269</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/examples/bluetooth/bttennis/board.cpp b/examples/bluetooth/bttennis/board.cpp
new file mode 100644
index 00000000..d1aab939
--- /dev/null
+++ b/examples/bluetooth/bttennis/board.cpp
@@ -0,0 +1,250 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "board.h"
+
+#include <QGraphicsItem>
+#include <QGraphicsScene>
+#include <QDebug>
+#include <QTextDocument>
+#include <QFontMetrics>
+#include <QPropertyAnimation>
+
+const QColor fg = Qt::white;
+const QColor bg = Qt::black;
+
+Board::Board(QWidget *parent) :
+ QGraphicsView(parent)
+{
+ scene = new QGraphicsScene(QRect(0, 0, 640, 360), this);
+
+ scene->setBackgroundBrush(QBrush(bg));
+
+ ball = scene->addRect(-6, -6, 12, 12, QPen(Qt::SolidLine), QBrush(fg));
+ ball->setPos(Width/2-6, Height/2-6);
+
+ // why is y -1...otherwise we have a gap...
+ topWall = scene->addRect(0, -1, Width, 12, QPen(Qt::SolidLine), QBrush(fg));
+ bottomWall = scene->addRect(0, Height-12, Width, 12, QPen(Qt::SolidLine), QBrush(fg));
+
+ leftPaddle = scene->addRect(0, 12, 12, Paddle, QPen(Qt::SolidLine), QBrush(fg));
+ rightPaddle = scene->addRect(Width-12, 12, 12, Paddle, QPen(Qt::SolidLine), QBrush(fg));
+
+ QPen p;
+ p.setWidth(2);
+ p.setStyle(Qt::DotLine);
+ p.setBrush(QBrush(fg));
+ scene->addLine(Width/2, 0, Width/2, Height, p);
+
+ QFont f;
+ f.setStyleHint(QFont::OldEnglish);
+ f.setPixelSize(50);
+ f.setBold(true);
+ leftScore = scene->addText(QString("0"), f);
+ leftScore->setDefaultTextColor(fg);
+// leftScore->setPos(120, 50);
+
+ rightScore = scene->addText(QString("0"), f);
+// rightScore->setPos(Width-140, 50);
+ rightScore->setDefaultTextColor(fg);
+ setScore(0, 0);
+
+ f.setPixelSize(25);
+ status = scene->addText(QString(), f);
+ status->setDefaultTextColor(fg);
+
+ ball->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
+ leftPaddle->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
+ rightPaddle->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
+
+ icon.load(QString(":/icons/connect.png"));
+ icon = icon.scaled(100, 100, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+ qDebug() << "icon" << icon.isNull();
+ connectIcon = scene->addPixmap(icon);
+ connectIcon->setPos(440,200);
+ connectIcon->setAcceptTouchEvents(true);
+ connectIcon->setTransformOriginPoint(50,50);
+ connectIcon->setTransformationMode(Qt::SmoothTransformation);
+
+ connectAnimation = new QPropertyAnimation(this, "connectRotation");
+ connectAnimation->setDuration(1000);
+ connectAnimation->setLoopCount(-1);
+ connectAnimation->setStartValue(0);
+ connectAnimation->setEndValue(360);
+
+ setCacheMode(QGraphicsView::CacheBackground);
+ setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate);
+
+// connect(scene, SIGNAL(changed(QList<QRectF>)), this, SLOT(sceneChanged(QList<QRectF>)));
+
+}
+void Board::setBall(int x, int y)
+{
+ ball->setPos(x, y);
+ checkBall(x, y);
+}
+
+void Board::setLeftPaddle(int y)
+{
+ leftPaddle->setPos(0, y);
+}
+
+void Board::setRightPaddle(int y)
+{
+ rightPaddle->setPos(0, y);
+}
+
+void Board::sceneChanged(const QList<QRectF> &region)
+{
+ Q_UNUSED(region);
+
+ QList<QGraphicsItem *>items = scene->collidingItems(ball);
+ while (!items.empty()) {
+ QGraphicsItem *i = items.takeFirst();
+ if (i == topWall)
+ emit ballCollision(Top);
+ if (i == bottomWall)
+ emit ballCollision(Bottom);
+ if (i == leftPaddle)
+ emit ballCollision(Left);
+ if (i == rightPaddle)
+ emit ballCollision(Right);
+ }
+
+}
+
+void Board::checkBall(int x, int y)
+{
+ int ly = leftPaddle->y();
+ int ry = rightPaddle->y();
+
+ if (x > 646)
+ emit scored(Right);
+ else if (x < -6)
+ emit scored(Left);
+
+ if (y < 18)
+ emit ballCollision(Top);
+ else if (y > 360-18)
+ emit ballCollision(Bottom);
+
+ if ((x < 18) &&
+ (y > ly-6) &&
+ (y < ly+Paddle+6))
+ emit ballCollision(Left);
+
+ if ((x > 640-18) &&
+ (y > ry-6) &&
+ (y < ry+Paddle+6))
+ emit ballCollision(Right);
+}
+
+void Board::setScore(int l, int r)
+{
+ QString left = QString("%1").arg(l);
+ QString right = QString("%1").arg(r);
+ leftScore->document()->setPlainText(left);
+ rightScore->document()->setPlainText(right);
+ QFontMetrics fm(leftScore->font());
+ leftScore->setPos(Width/4 - fm.width(left)/2, 50);
+ rightScore->setPos(3*Width/4 - fm.width(right)/2, 50);
+
+}
+
+void Board::setStatus(QString text, int opacity_start, int opacity_end)
+{
+
+ status->document()->setPlainText(text);
+ status->setPos(24, Height-25-25);
+ QPropertyAnimation *a = new QPropertyAnimation(status, "opacity");
+ a->setDuration(2000);
+ a->setStartValue(opacity_start/100.0);
+ a->setEndValue(opacity_end/100.0);
+ a->start(QAbstractAnimation::DeleteWhenStopped);
+}
+
+void Board::setConnectRotation(int rot)
+{
+ connectIcon->setRotation(rot);
+// QTransform t;
+// t.rotate(rot);
+// connectIcon->setPixmap(icon.scaled(100, 100).transformed(t, Qt::SmoothTransformation));
+}
+
+void Board::setConnectOpacity(qreal op)
+{
+ connectIcon->setOpacity(op);
+}
+
+void Board::animateConnect(bool start)
+{
+ if (start) {
+ connectAnimation->start();
+ }
+ else {
+ connectAnimation->stop();
+ QPropertyAnimation *a = new QPropertyAnimation(this, "connectRotation");
+// qDebug() << "currentTime" << connectAnimation->currentLoopTime() << "rotation" << connectAnimation->currentValue();
+ a->setDuration(connectAnimation->currentLoopTime()/2);
+ a->setStartValue(connectAnimation->currentValue().toInt( ));
+ a->setEndValue(0);
+// a->setDirection(QAbstractAnimation::Backward);
+ a->start(QAbstractAnimation::DeleteWhenStopped);
+ }
+}
+
+
+void Board::fadeConnect(bool out)
+{
+ qreal start = 100.0;
+ qreal end = 0.0;
+
+ if (!out) {
+ start = 0.0;
+ end = 100.0;
+ }
+
+ QPropertyAnimation *a = new QPropertyAnimation(this, "connectOpacity");
+ a->setDuration(2000);
+ a->setStartValue(start);
+ a->setEndValue(end);
+ a->start(QAbstractAnimation::DeleteWhenStopped);
+}
diff --git a/examples/bluetooth/bttennis/board.h b/examples/bluetooth/bttennis/board.h
new file mode 100644
index 00000000..7b0f279b
--- /dev/null
+++ b/examples/bluetooth/bttennis/board.h
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef BOARD_H
+#define BOARD_H
+
+#include <QObject>
+#include <QGraphicsScene>
+#include <QGraphicsView>
+#include <QGraphicsPixmapItem>
+#include <QPixmap>
+#include <QPropertyAnimation>
+
+class Board : public QGraphicsView
+{
+ Q_OBJECT
+ Q_PROPERTY(int connectRotation READ connectRotation WRITE setConnectRotation)
+ Q_PROPERTY(qreal connectOpacity READ connectOpacity WRITE setConnectOpacity)
+public:
+ explicit Board(QWidget *parent = 0);
+
+ enum Edge {
+ Top = 1,
+ Bottom,
+ Left,
+ Right
+ };
+
+ enum BoardSize {
+ Width = 640,
+ Height = 360,
+ Paddle = 50
+ };
+
+
+ QGraphicsScene *getScene() {
+ return scene;
+ }
+
+ int connectRotation(){
+ return connectIcon->rotation();
+ }
+
+ qreal connectOpacity(){
+ return connectIcon->opacity();
+ }
+
+ void setConnectRotation(int rot);
+ void setConnectOpacity(qreal op);
+
+signals:
+ void ballCollision(Board::Edge pos);
+ void scored(Board::Edge pos);
+
+public slots:
+ void setBall(int x, int y);
+ void setLeftPaddle(int y);
+ void setRightPaddle(int y);
+ void setScore(int l, int r);
+
+ void setStatus(QString text, int opacity_start, int opacity_end);
+
+ void sceneChanged(const QList<QRectF> &region);
+
+ void animateConnect(bool start = true);
+ void fadeConnect(bool out = true);
+
+private:
+ QGraphicsScene *scene;
+ QGraphicsRectItem *ball;
+ QGraphicsRectItem *topWall;
+ QGraphicsRectItem *bottomWall;
+ QGraphicsRectItem *leftPaddle;
+ QGraphicsRectItem *rightPaddle;
+
+ QGraphicsTextItem *leftScore;
+ QGraphicsTextItem *rightScore;
+
+ QGraphicsTextItem *status;
+
+ QPixmap icon;
+ QGraphicsPixmapItem *connectIcon;
+ QPropertyAnimation *connectAnimation;
+
+ void checkBall(int x, int y);
+};
+
+#endif // BOARD_H
diff --git a/examples/bluetooth/bttennis/bttennis.pro b/examples/bluetooth/bttennis/bttennis.pro
new file mode 100644
index 00000000..39e33dcf
--- /dev/null
+++ b/examples/bluetooth/bttennis/bttennis.pro
@@ -0,0 +1,30 @@
+TEMPLATE = app
+TARGET = bttennis
+
+QT += concurrent bluetooth widgets
+#QT += nfc
+
+SOURCES = \
+ main.cpp \
+ board.cpp \
+ tennis.cpp \
+ controller.cpp \
+ tennisserver.cpp \
+ tennisclient.cpp \
+ tennisview.cpp
+# handover.cpp
+
+HEADERS = \
+ board.h \
+ tennis.h \
+ controller.h \
+ tennisserver.h \
+ tennisclient.h \
+ tennisview.h
+# handover.h
+
+FORMS = \
+ tennis.ui
+
+RESOURCES += \
+ tennis.qrc
diff --git a/examples/bluetooth/bttennis/connect.png b/examples/bluetooth/bttennis/connect.png
new file mode 100644
index 00000000..70b64c6c
--- /dev/null
+++ b/examples/bluetooth/bttennis/connect.png
Binary files differ
diff --git a/examples/bluetooth/bttennis/controller.cpp b/examples/bluetooth/bttennis/controller.cpp
new file mode 100644
index 00000000..c137060a
--- /dev/null
+++ b/examples/bluetooth/bttennis/controller.cpp
@@ -0,0 +1,263 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "controller.h"
+
+#include <QDateTime>
+#include <QDebug>
+
+#define FRAME_RATE 60
+
+Controller::Controller(QObject *parent) :
+ QObject(parent), timer(new QTimer), elapsed(new QTime), score_left(0), score_right(0),
+ col_x(0), col_y(0),
+ rightPaddleForce(0), leftPaddleForce(0),
+ rightPaddleLast(0), leftPaddleLast(0),
+ rightPowerUp(0), leftPowerUp(0)
+{
+
+ qsrand(QDateTime::currentDateTime().time().msec());
+
+
+ timer->setInterval(1000/FRAME_RATE);
+// timer->setInterval(0);
+ connect(timer, SIGNAL(timeout()), SLOT(tick()));
+ srand(QDateTime::currentDateTime().time().msec());
+
+ fpscntr = new QTime;
+ frames = 0;
+
+ timer->start();
+ restart_ball();
+}
+
+void Controller::tick()
+{
+ if (col_x)
+ col_x--;
+ if (col_y)
+ col_y--;
+
+// frames++;
+// if (fpscntr->elapsed() > 1000){
+// int f = frames/(fpscntr->elapsed()/1000.0);
+// emit fps(QString("FPS %1").arg(f));
+// frames = 0;
+// fpscntr->restart();
+// }
+
+ int msec = elapsed->elapsed();
+ elapsed->restart();
+
+ ball_x += speed_x*msec/1000;
+ ball_y += speed_y*msec/1000;
+
+
+ const int decay = 5;
+
+ if (leftPaddleForce > decay)
+ leftPaddleForce-=decay;
+ else if (leftPaddleForce < -decay)
+ leftPaddleForce+=decay;
+ if (rightPaddleForce > decay)
+ rightPaddleForce-=decay;
+ else if (rightPaddleForce < -decay)
+ rightPaddleForce+=decay;
+
+ if (rightPaddleForce <= decay)
+ rightPowerUp++;
+
+ if (leftPaddleForce <= decay)
+ leftPowerUp++;
+
+
+// ttf++;
+// if (msec > 1000/FRAME_RATE+2 || msec < 1000/FRAME_RATE-2)
+// dev++;
+
+// if (!(i++%120)) {
+// qDebug() << "powerUp: " << leftPowerUp << rightPowerUp << leftPaddleForce << rightPaddleForce << speed_x*msec/1000 << speed_y*msec/1000 << msec << dev;
+// ttf = dev =0;
+// }
+
+ emit moveBall(ball_x, ball_y);
+}
+
+
+static inline int paddle_boost(int force){
+ if (force > 30)
+ return -3*FRAME_RATE;
+ else if (force > 20)
+ return -2*FRAME_RATE;
+ else if (force > 6)
+ return -1*FRAME_RATE;
+ else if (force < -30)
+ return 3*FRAME_RATE;
+ else if (force < -20)
+ return 2*FRAME_RATE;
+ else if (force < -6)
+ return 1*FRAME_RATE;
+ return 0;
+}
+
+void Controller::ballCollision(Board::Edge pos)
+{
+
+ if ((pos == Board::Top || pos == Board::Bottom) && !col_y) {
+ speed_y *= -1;
+ col_y = 10;
+ }
+
+ if (pos == Board::Left && !col_x) {
+ speed_x *= -1;
+ speed_y += paddle_boost(leftPaddleForce);
+ col_x = 10;
+
+ if (leftPowerUp > 75 && speed_x < 8*FRAME_RATE){
+ speed_x *= 2;
+ leftPowerUp = 0;
+ }
+ }
+ else if (pos == Board::Right && !col_x) {
+ speed_x *= -1;
+ speed_y += paddle_boost(rightPaddleForce);
+ col_x = 10;
+
+ if (rightPowerUp > 75 && speed_x > -8*FRAME_RATE){
+ speed_x *= 2;
+ rightPowerUp = 0;
+ }
+
+ }
+// tick();
+// QMetaObject::invokeMethod(this, "moveBall", Qt::QueuedConnection, Q_ARG(int, ball_x), Q_ARG(int, ball_y));
+// emit moveBall(ball_x, ball_y);
+
+}
+
+void Controller::scored(Board::Edge pos)
+{
+ if (!timer->isActive())
+ return;
+
+ if (pos == Board::Left)
+ emit score(score_left, ++score_right);
+ else if (pos == Board::Right)
+ emit score(++score_left, score_right);
+
+ restart_ball();
+}
+
+void Controller::restart_ball()
+{
+ if (!timer->isActive())
+ return;
+
+ elapsed->start();
+
+ ball_x = Board::Width/2;
+ ball_y = Board::Height/2;
+
+// ball_y = (qrand()%(Board::Height/2))+Board::Height/4;
+ ball_y = (qrand()%(Board::Height-48))+24;
+
+ // Speed in in pixels/second
+
+ const int max = 4*FRAME_RATE;
+ const int min_x = 2*FRAME_RATE;
+ const int min_y = 1.5*FRAME_RATE;
+
+
+ speed_y = min_y+qrand()%(max-min_y);
+ if (speed_y%2)
+ speed_y *= -1;
+
+
+ speed_x = min_x+qrand()%(max-min_y);
+ if (speed_x%2)
+ speed_x *= -1;
+
+ leftPowerUp = rightPowerUp = 0;
+
+ emit moveBall(ball_x, ball_y);
+}
+
+
+void Controller::resetBoard()
+{
+ if (!timer->isActive())
+ return;
+
+ score_left = score_right = 0;
+ restart_ball();
+}
+
+void Controller::stop()
+{
+ timer->stop();
+}
+
+void Controller::start()
+{
+ timer->start();
+ fpscntr->restart();
+ frames = 0;
+}
+
+void Controller::moveLeftPaddle(int y)
+{
+ leftPaddleForce += leftPaddleLast-y;
+ leftPaddleLast = y;
+ leftPowerUp = 0;
+}
+
+void Controller::moveRightPaddle(int y)
+{
+ rightPaddleForce += rightPaddleLast-y;
+ rightPaddleLast =y;
+ rightPowerUp = 0;
+}
+
+void Controller::refresh()
+{
+ emit moveBall(ball_x, ball_y);
+ emit score(score_left, score_right);
+}
diff --git a/examples/bluetooth/bttennis/controller.h b/examples/bluetooth/bttennis/controller.h
new file mode 100644
index 00000000..492f094b
--- /dev/null
+++ b/examples/bluetooth/bttennis/controller.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CONTROLLER_H
+#define CONTROLLER_H
+
+#include <QObject>
+#include <QTimer>
+#include <QTime>
+#include "board.h"
+
+class Controller : public QObject
+{
+ Q_OBJECT
+public:
+ explicit Controller(QObject *parent = 0);
+
+signals:
+ void moveBall(int x, int y);
+ void score(int left, int right);
+ void fps(const QString &str);
+
+public slots:
+ void ballCollision(Board::Edge pos);
+ void scored(Board::Edge pos);
+ void resetBoard();
+ void refresh();
+
+ void moveLeftPaddle(int y);
+ void moveRightPaddle(int y);
+
+ void tick();
+
+ void start();
+ void stop();
+
+private:
+ QTimer *timer;
+ QTime *elapsed;
+ QTime *fpscntr;
+ int frames;
+ int ball_x;
+ int speed_x;
+ int ball_y;
+ int speed_y;
+ int score_left;
+ int score_right;
+ int col_x;
+ int col_y;
+
+ int rightPaddleForce;
+ int leftPaddleForce;
+ int rightPaddleLast;
+ int leftPaddleLast;
+ int rightPowerUp;
+ int leftPowerUp;
+
+ void restart_ball();
+
+};
+
+#endif // CONTROLLER_H
diff --git a/examples/bluetooth/bttennis/doc/images/bttennis-example.png b/examples/bluetooth/bttennis/doc/images/bttennis-example.png
new file mode 100644
index 00000000..53a5486b
--- /dev/null
+++ b/examples/bluetooth/bttennis/doc/images/bttennis-example.png
Binary files differ
diff --git a/examples/bluetooth/bttennis/doc/src/bttennis.qdoc b/examples/bluetooth/bttennis/doc/src/bttennis.qdoc
new file mode 100644
index 00000000..094dbaa3
--- /dev/null
+++ b/examples/bluetooth/bttennis/doc/src/bttennis.qdoc
@@ -0,0 +1,37 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \example bttennis
+ \title Bluetooth Tennis Example
+
+ The Bluetooth Tennis example shows how to use the Qt Connectivity Bluetooth API
+ to implement real-time data transfer for interactive applications.
+
+ \image bttennis-example.png
+
+*/
diff --git a/examples/bluetooth/bttennis/handover.cpp b/examples/bluetooth/bttennis/handover.cpp
new file mode 100644
index 00000000..03ec169b
--- /dev/null
+++ b/examples/bluetooth/bttennis/handover.cpp
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "handover.h"
+
+#include <qnearfieldmanager.h>
+#include <qllcpserver.h>
+#include <qllcpsocket.h>
+#include <qbluetoothlocaldevice.h>
+
+#include <QtCore/QStringList>
+
+static const QLatin1String tennisUri("urn:nfc:sn:com.nokia.qtnfc.tennis");
+
+Handover::Handover(quint16 serverPort, QObject *parent)
+: QObject(parent), m_server(new QLlcpServer(this)),
+ m_client(new QLlcpSocket(this)), m_remote(0), m_serverPort(0), m_localServerPort(serverPort)
+{
+ connect(m_server, SIGNAL(newConnection()), this, SLOT(handleNewConnection()));
+ m_server->listen(tennisUri);
+
+ connect(m_client, SIGNAL(disconnected()), this, SLOT(clientDisconnected()));
+ connect(m_client, SIGNAL(readyRead()), this, SLOT(readBluetoothService()));
+
+ m_client->connectToService(0, tennisUri);
+}
+
+Handover::~Handover()
+{
+}
+
+QBluetoothAddress Handover::bluetoothAddress() const
+{
+ return m_address;
+}
+
+quint16 Handover::serverPort() const
+{
+ return m_serverPort;
+}
+
+void Handover::handleNewConnection()
+{
+ if (m_remote)
+ m_remote->deleteLater();
+
+ m_remote = m_server->nextPendingConnection();
+
+ connect(m_remote, SIGNAL(disconnected()), this, SLOT(remoteDisconnected()));
+
+ sendBluetoothService();
+}
+
+void Handover::remoteDisconnected()
+{
+ m_remote->deleteLater();
+ m_remote = 0;
+}
+
+void Handover::clientDisconnected()
+{
+ m_client->connectToService(0, tennisUri);
+}
+
+void Handover::readBluetoothService()
+{
+ QByteArray rawData = m_client->readAll();
+ QString data = QString::fromUtf8(rawData.constData(), rawData.size());
+ QStringList split = data.split(QLatin1Char(' '));
+
+ QBluetoothAddress address = QBluetoothAddress(split.at(0));
+ quint16 port = split.at(1).toUInt();
+
+ QBluetoothLocalDevice localDevice;
+ QBluetoothAddress localAddress = localDevice.address();
+
+ if (localAddress < address) {
+ m_address = address;
+ m_serverPort = port;
+ emit bluetoothServiceChanged();
+ }
+}
+
+void Handover::sendBluetoothService()
+{
+ QBluetoothLocalDevice localDevice;
+ const QString data = localDevice.address().toString() + QLatin1Char(' ') +
+ QString::number(m_localServerPort);
+
+ m_remote->write(data.toUtf8());
+}
+
diff --git a/examples/bluetooth/bttennis/handover.h b/examples/bluetooth/bttennis/handover.h
new file mode 100644
index 00000000..0e932267
--- /dev/null
+++ b/examples/bluetooth/bttennis/handover.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef HANDOVER_H
+#define HANDOVER_H
+
+#include <QtCore/QObject>
+
+#include <qbluetoothaddress.h>
+#include <qbluetoothuuid.h>
+#include <qnfcglobal.h>
+
+QTNFC_BEGIN_NAMESPACE
+class QNearFieldManager;
+class QNearFieldTarget;
+class QLlcpServer;
+class QLlcpSocket;
+QTNFC_END_NAMESPACE
+
+QTNFC_USE_NAMESPACE
+QTBLUETOOTH_USE_NAMESPACE
+
+class Handover : public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit Handover(quint16 serverPort, QObject *parent = 0);
+ ~Handover();
+
+ QBluetoothAddress bluetoothAddress() const;
+ quint16 serverPort() const;
+
+private slots:
+ void handleNewConnection();
+ void remoteDisconnected();
+
+ void clientDisconnected();
+
+ void readBluetoothService();
+ void sendBluetoothService();
+
+signals:
+ void bluetoothServiceChanged();
+
+private:
+ QLlcpServer *m_server;
+ QLlcpSocket *m_client;
+ QLlcpSocket *m_remote;
+
+ QBluetoothAddress m_address;
+ quint16 m_serverPort;
+ quint16 m_localServerPort;
+};
+
+#endif // HANDOVER_H
diff --git a/examples/bluetooth/bttennis/main.cpp b/examples/bluetooth/bttennis/main.cpp
new file mode 100644
index 00000000..d30632f7
--- /dev/null
+++ b/examples/bluetooth/bttennis/main.cpp
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "tennis.h"
+
+#include <QApplication>
+
+int main(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+
+ Tennis d;
+ QObject::connect(&d, SIGNAL(accepted()), &app, SLOT(quit()));
+
+#if defined(Q_WS_MAEMO_6)
+ d.showFullScreen();
+#else
+ d.show();
+#endif
+
+ app.exec();
+
+ return 0;
+}
+
diff --git a/examples/bluetooth/bttennis/tennis.cpp b/examples/bluetooth/bttennis/tennis.cpp
new file mode 100644
index 00000000..54fe026f
--- /dev/null
+++ b/examples/bluetooth/bttennis/tennis.cpp
@@ -0,0 +1,424 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "tennis.h"
+
+#include <QTimer>
+#include <QKeyEvent>
+#include <QMouseEvent>
+
+#include <QDebug>
+
+#include <QSettings>
+#include <QEvent>
+#include <QResizeEvent>
+
+#include "tennisserver.h"
+#include "tennisclient.h"
+//#include "handover.h"
+
+#include <qbluetooth.h>
+#include <qbluetoothdeviceinfo.h>
+#include <qbluetoothsocket.h>
+#include <qbluetoothservicediscoveryagent.h>
+#include <qbluetoothlocaldevice.h>
+
+//#include <qnearfieldmanager.h>
+//#include <qllcpserver.h>
+//#include <qllcpsocket.h>
+
+Tennis::Tennis(QWidget *parent)
+: QDialog(parent), ui(new Ui_Tennis), board(new Board), controller(new Controller), socket(0),
+ m_discoveryAgent(new QBluetoothServiceDiscoveryAgent)//, m_handover(0)
+{
+ // start Bluetooth if not started
+ QBluetoothLocalDevice *device = new QBluetoothLocalDevice();
+ device->powerOn();
+ delete device;
+ device = 0;
+
+ //! [Construct UI]
+ ui->setupUi(this);
+
+ isClient = false;
+ isConnected = false;
+ quickDiscovery = true;
+
+#if defined(Q_OS_WINCE) || defined(Q_WS_MAEMO_6)
+ setWindowState(Qt::WindowMaximized);
+#endif
+
+ ui->pongView->setScene(board->getScene());
+
+ connect(ui->pongView, SIGNAL(mouseMove(int, int)), this, SLOT(mouseMove(int, int)));
+ ui->pongView->setMouseTracking(false);
+
+ connect(board, SIGNAL(ballCollision(Board::Edge)), controller, SLOT(ballCollision(Board::Edge)));
+ connect(board, SIGNAL(scored(Board::Edge)), controller, SLOT(scored(Board::Edge)));
+ connect(controller, SIGNAL(moveBall(int,int)), board, SLOT(setBall(int,int)));
+ connect(this, SIGNAL(moveLeftPaddle(int)), board, SLOT(setLeftPaddle(int)));
+ connect(this, SIGNAL(moveRightPaddle(int)), board, SLOT(setRightPaddle(int)));
+ connect(controller, SIGNAL(score(int,int)), board, SLOT(setScore(int,int)));
+ connect(controller, SIGNAL(fps(const QString&)), this, SLOT(fps(const QString&)));
+
+ setFocusPolicy(Qt::WheelFocus);
+
+ paddle_pos = (Board::Height-12)/2-Board::Paddle/2;
+ endPaddlePos = paddle_pos;
+
+ emit moveLeftPaddle(paddle_pos);
+ board->setRightPaddle(paddle_pos);
+
+ server = new TennisServer(this);
+
+ connect(controller, SIGNAL(moveBall(int,int)), server, SLOT(moveBall(int,int)));
+ connect(controller, SIGNAL(score(int,int)), server, SLOT(score(int,int)));
+ connect(this, SIGNAL(moveLeftPaddle(int)), server, SLOT(moveLeftPaddle(int)));
+ connect(server, SIGNAL(clientConnected(QString)), this, SLOT(serverConnected(QString)));
+ connect(server, SIGNAL(clientDisconnected(QString)), this, SLOT(serverDisconnected()));
+ connect(server, SIGNAL(moveRightPaddle(int)), board, SLOT(setRightPaddle(int)));
+ connect(server, SIGNAL(lag(int)), this, SLOT(lagReport(int)));
+
+ connect(server, SIGNAL(clientConnected(QString)), controller, SLOT(refresh()));
+
+ server->startServer();
+
+ client = new TennisClient(this);
+
+ connect(client, SIGNAL(moveBall(int,int)), board, SLOT(setBall(int,int)));
+ connect(client, SIGNAL(moveLeftPaddle(int)), board, SLOT(setLeftPaddle(int)));
+ connect(client, SIGNAL(connected(QString)), this, SLOT(clientConnected(QString)));
+ connect(client, SIGNAL(disconnected()), this, SLOT(clientDisconnected()));
+ connect(this, SIGNAL(moveRightPaddle(int)), client, SLOT(moveRightPaddle(int)));
+ connect(client, SIGNAL(score(int,int)), board, SLOT(setScore(int,int)));
+ connect(client, SIGNAL(lag(int)), this, SLOT(lagReport(int)));
+
+ connect(this, SIGNAL(moveLeftPaddle(int)), controller, SLOT(moveLeftPaddle(int)));
+ connect(this, SIGNAL(moveRightPaddle(int)), controller, SLOT(moveRightPaddle(int)));
+ connect(server, SIGNAL(moveRightPaddle(int)), controller, SLOT(moveRightPaddle(int)));
+
+
+// ui->pongView->setBackgroundBrush(QBrush(Qt::white));
+ ui->pongView->setCacheMode(QGraphicsView::CacheBackground);
+
+/* QNearFieldManager nearFieldManager;
+ if (nearFieldManager.isAvailable()) {
+ m_handover = new Handover(server->serverPort(), this);
+ connect(m_handover, SIGNAL(bluetoothServiceChanged()), this, SLOT(nearFieldHandover()));
+
+ connect(m_discoveryAgent, SIGNAL(serviceDiscovered(QBluetoothServiceInfo)),
+ this, SLOT(serviceDiscovered(QBluetoothServiceInfo)));
+ connect(m_discoveryAgent, SIGNAL(finished()), this, SLOT(discoveryFinished()));
+ }*/
+
+
+ m_discoveryAgent->setUuidFilter(QBluetoothUuid(serviceUuid));
+
+
+ QString address;
+ QString port;
+ QStringList args = QCoreApplication::arguments();
+ if (args.length() >= 2){
+ address = args.at(1);
+ if (args.length() >= 3){
+ port = args.at(2);
+ }
+ }
+
+ if (address.isEmpty()){
+ QSettings settings("QtDF", "bttennis");
+ address = settings.value("lastclient").toString();
+ }
+
+ if (!address.isEmpty()){
+ qDebug() << "Connect to" << address << port;
+ QBluetoothDeviceInfo device = QBluetoothDeviceInfo(QBluetoothAddress(address), "", QBluetoothDeviceInfo::ComputerDevice);
+ QBluetoothServiceInfo service;
+ if (!port.isEmpty()) {
+ QBluetoothServiceInfo::Sequence protocolDescriptorList;
+ QBluetoothServiceInfo::Sequence protocol;
+ protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::L2cap))
+ << QVariant::fromValue(port.toUShort());
+ protocolDescriptorList.append(QVariant::fromValue(protocol));
+ service.setAttribute(QBluetoothServiceInfo::ProtocolDescriptorList,
+ protocolDescriptorList);
+ qDebug() << "port" << port.toUShort() << service.protocolServiceMultiplexer();
+ }
+ else {
+ service.setServiceUuid(QBluetoothUuid(serviceUuid));
+ }
+ service.setDevice(device);
+ client->startClient(service);
+ board->setStatus("Connecting", 100, 25);
+ } /*else if (nearFieldManager.isAvailable()) {
+ board->setStatus(tr("Touch to play"), 100, 25);
+ }*/
+
+ setEnabled(true);
+
+ paddleAnimation = new QPropertyAnimation(this, "paddlePos", this);
+ paddleAnimation->setEasingCurve(QEasingCurve::InOutQuad);
+
+ ui->pongView->installEventFilter(this);
+
+}
+
+Tennis::~Tennis()
+{
+}
+
+void Tennis::keyPressEvent(QKeyEvent *event)
+{
+ if (event->matches(QKeySequence::MoveToNextLine)) {
+ moveDown();
+ }
+ else if (event->matches(QKeySequence::MoveToPreviousLine)){
+ moveUp();
+ }
+}
+
+void Tennis::wheelEvent(QWheelEvent *event)
+{
+ if (event->delta() > 0){
+ moveUp();
+ }
+ else {
+ moveDown();
+ }
+}
+
+void Tennis::moveUp(int px)
+{
+ endPaddlePos -= px;
+ if (endPaddlePos <= 0)
+ endPaddlePos = 0;
+ move(endPaddlePos);
+}
+
+void Tennis::moveDown(int px)
+{
+ endPaddlePos += px;
+ if (endPaddlePos > Board::Height-Board::Paddle-24)
+ endPaddlePos = Board::Height-Board::Paddle-24;
+ move(endPaddlePos);
+
+}
+
+void Tennis::move(int px)
+{
+ int distance = abs(paddle_pos - endPaddlePos);
+
+ paddleAnimation->stop();
+ paddleAnimation->setStartValue(paddle_pos);
+ paddleAnimation->setEndValue(px);
+ paddleAnimation->setDuration((1000*distance)/350);
+ paddleAnimation->start();
+}
+
+void Tennis::setPaddlePos(int p)
+{
+ paddle_pos = p;
+ if (isClient)
+ emit moveRightPaddle(paddle_pos);
+ else
+ emit moveLeftPaddle(paddle_pos);
+}
+
+
+void Tennis::mouseMove(int x, int y)
+{
+ if (isConnected == false){
+ // look for clicks in the bt connect icon
+ if (x > 440 && x < 540 && y > 200 && y < 300) {
+ qDebug() << "Got connect click!";
+ if (m_discoveryAgent->isActive()) {
+ qDebug() << "stopping!";
+ m_discoveryAgent->stop();
+ board->animateConnect(false);
+ }
+ else {
+ qDebug() << "starting!";
+ startDiscovery();
+ }
+ }
+
+ }
+ y-=12+Board::Paddle/2;
+ if (y <= 0)
+ y = 0;
+ else if (y > Board::Height-Board::Paddle-24)
+ y = Board::Height-Board::Paddle-24;
+
+ endPaddlePos = y;
+ move(y);
+}
+
+void Tennis::clientConnected(const QString &name)
+{
+ board->setStatus("Connected to " + name, 100, 0);
+ controller->stop();
+ server->stopServer();
+ isClient = true;
+ isConnected = true;
+ board->animateConnect(false);
+ board->fadeConnect(true);
+ emit moveRightPaddle(paddle_pos);
+}
+
+void Tennis::clientDisconnected()
+{
+ board->setStatus("Disconnect", 100, 25);
+ controller->start();
+ server->startServer();
+ client->stopClient();
+ isClient = false;
+ isConnected = false;
+ discoveryFinished();
+}
+
+void Tennis::serverConnected(const QString &name)
+{
+ board->setStatus("Server for " + name, 100, 0);
+ m_discoveryAgent->stop();
+ isConnected = true;
+ board->animateConnect(false);
+ board->fadeConnect(true);
+ emit moveLeftPaddle(paddle_pos);
+}
+
+void Tennis::serverDisconnected()
+{
+ board->setStatus("Disconnected", 100, 25);
+ isConnected = false;
+ discoveryFinished();
+}
+
+void Tennis::serviceDiscovered(const QBluetoothServiceInfo &serviceInfo)
+{
+ qDebug() << "***** Discovered! " << serviceInfo.device().name() << serviceInfo.serviceName() << serviceInfo.serviceUuid();
+ qDebug() << "Found one!" << serviceInfo.protocolServiceMultiplexer();
+ m_discoveryAgent->stop();
+ client->startClient(serviceInfo);
+ QSettings settings("QtDF", "bttennis");
+ settings.setValue("lastclient", serviceInfo.device().address().toString());
+}
+
+void Tennis::discoveryFinished()
+{
+ if (!m_discoveryAgent->isActive()) {
+ if (!isConnected) {
+ board->setStatus("Waiting", 100, 25);
+ // QTimer::singleShot(60000, this, SLOT(startDiscovery()));
+ board->animateConnect(false);
+ board->fadeConnect(false);
+ }
+ }
+}
+
+void Tennis::startDiscovery()
+{
+ qDebug() << "startDiscovery() called";
+ if (!isConnected) {
+ qDebug() << "Scanning!";
+ board->setStatus("Scanning", 100, 25);
+ board->fadeConnect(false);
+ board->animateConnect(true);
+ m_discoveryAgent->start(QBluetoothServiceDiscoveryAgent::MinimalDiscovery);
+// if (quickDiscovery)
+// m_discoveryAgent->start(QBluetoothServiceDiscoveryAgent::MinimalDiscovery);
+// else
+// m_discoveryAgent->start(QBluetoothServiceDiscoveryAgent::FullDiscovery);
+// quickDiscovery = !quickDiscovery;
+ }
+ else {
+ qDebug() << "Stop scanning!";
+ board->setStatus("", 0, 0);
+ board->animateConnect(false);
+ board->fadeConnect(true);
+ }
+}
+
+void Tennis::resizeEvent(QResizeEvent *re)
+{
+ if (re->oldSize().height() > 0){
+ qreal x, y;
+ x = (re->size().width())/qreal(re->oldSize().width());
+ y = (re->size().height())/qreal(re->oldSize().height());
+ ui->pongView->scale(x, y);
+ }
+ ui->pongView->resize(re->size());
+}
+
+void Tennis::lagReport(int ms)
+{
+ if (ms > 250){
+ board->setStatus(QString("Caution Lag %1ms").arg(ms), 100, 0);
+ }
+}
+
+/*void Tennis::nearFieldHandover()
+{
+ qDebug() << "Connecting to NFC provided address" << m_handover->bluetoothAddress().toString();
+
+ QBluetoothDeviceInfo device = QBluetoothDeviceInfo(m_handover->bluetoothAddress(), QString(),
+ QBluetoothDeviceInfo::ComputerDevice);
+
+ QBluetoothServiceInfo service;
+ service.setServiceUuid(QBluetoothUuid(serviceUuid));
+ service.setDevice(device);
+
+ QBluetoothServiceInfo::Sequence protocolDescriptorList;
+ QBluetoothServiceInfo::Sequence protocol;
+ protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::L2cap))
+ << QVariant::fromValue(m_handover->serverPort());
+ protocolDescriptorList.append(QVariant::fromValue(protocol));
+ service.setAttribute(QBluetoothServiceInfo::ProtocolDescriptorList,
+ protocolDescriptorList);
+
+ client->startClient(service);
+ board->setStatus(tr("Connecting: %1 %2").arg(m_handover->bluetoothAddress().toString()).arg(m_handover->serverPort()), 100, 25);
+}*/
+
+void Tennis::fps(const QString &f)
+{
+ board->setStatus(f, 100, 100);
+}
+
diff --git a/examples/bluetooth/bttennis/tennis.h b/examples/bluetooth/bttennis/tennis.h
new file mode 100644
index 00000000..92b5f0fa
--- /dev/null
+++ b/examples/bluetooth/bttennis/tennis.h
@@ -0,0 +1,140 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "ui_tennis.h"
+
+#include <QDialog>
+
+#include <QResizeEvent>
+#include <QMoveEvent>
+#include <QPropertyAnimation>
+#include <qbluetoothserviceinfo.h>
+#include <qbluetoothsocket.h>
+#include <qbluetoothdevicediscoveryagent.h>
+
+#include "board.h"
+#include "controller.h"
+
+#include <QDebug>
+
+QTBLUETOOTH_BEGIN_NAMESPACE
+class QBluetoothServiceDiscoveryAgent;
+QTBLUETOOTH_END_NAMESPACE
+
+QTBLUETOOTH_USE_NAMESPACE
+
+static const QLatin1String serviceUuid("e8e10f95-1a70-4b27-9ccf-02010264e9c9");
+
+class TennisServer;
+class TennisClient;
+//class Handover;
+
+//! [declaration]
+class Tennis : public QDialog
+{
+ Q_OBJECT
+ Q_PROPERTY(int paddlePos READ paddlePos WRITE setPaddlePos)
+
+public:
+ Tennis(QWidget *parent = 0);
+ ~Tennis();
+
+ int paddlePos() { return paddle_pos; }
+ void setPaddlePos(int p);
+
+signals:
+ void moveLeftPaddle(int y);
+ void moveRightPaddle(int y);
+
+protected:
+ void wheelEvent ( QWheelEvent * event );
+ void keyPressEvent ( QKeyEvent * event );
+ void resizeEvent(QResizeEvent *);
+
+private slots:
+ void serverConnected(const QString &name);
+ void serverDisconnected();
+
+ void clientConnected(const QString &name);
+ void clientDisconnected();
+
+ void serviceDiscovered(const QBluetoothServiceInfo &serviceInfo);
+ void discoveryFinished();
+
+ void startDiscovery();
+
+ void mouseMove(int x, int y);
+
+ void lagReport(int ms);
+
+// void nearFieldHandover();
+
+ void fps(const QString &f);
+
+private:
+
+ void moveUp(int px = 10);
+ void moveDown(int px = 10);
+
+ void move(int px);
+
+ Ui_Tennis *ui;
+
+ Board *board;
+ Controller *controller;
+
+ int paddle_pos;
+ int endPaddlePos;
+
+ bool isClient;
+ bool isConnected;
+ bool quickDiscovery;
+
+ QBluetoothSocket *socket;
+ TennisServer *server;
+ TennisClient *client;
+
+ QPropertyAnimation *paddleAnimation;
+
+ QBluetoothServiceDiscoveryAgent *m_discoveryAgent;
+// Handover *m_handover;
+};
+//! [declaration]
diff --git a/examples/bluetooth/bttennis/tennis.qrc b/examples/bluetooth/bttennis/tennis.qrc
new file mode 100644
index 00000000..12aa7464
--- /dev/null
+++ b/examples/bluetooth/bttennis/tennis.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/icons">
+ <file>connect.png</file>
+ </qresource>
+</RCC>
diff --git a/examples/bluetooth/bttennis/tennis.ui b/examples/bluetooth/bttennis/tennis.ui
new file mode 100644
index 00000000..d6625fa8
--- /dev/null
+++ b/examples/bluetooth/bttennis/tennis.ui
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Tennis</class>
+ <widget class="QDialog" name="Tennis">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>640</width>
+ <height>360</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Bluetooth Tennis</string>
+ </property>
+ <widget class="TennisView" name="pongView">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>640</width>
+ <height>366</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Plain</enum>
+ </property>
+ <property name="lineWidth">
+ <number>0</number>
+ </property>
+ <property name="verticalScrollBarPolicy">
+ <enum>Qt::ScrollBarAlwaysOff</enum>
+ </property>
+ <property name="horizontalScrollBarPolicy">
+ <enum>Qt::ScrollBarAlwaysOff</enum>
+ </property>
+ </widget>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>TennisView</class>
+ <extends>QGraphicsView</extends>
+ <header>tennisview.h</header>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/examples/bluetooth/bttennis/tennisclient.cpp b/examples/bluetooth/bttennis/tennisclient.cpp
new file mode 100644
index 00000000..c5487f02
--- /dev/null
+++ b/examples/bluetooth/bttennis/tennisclient.cpp
@@ -0,0 +1,200 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "tennisclient.h"
+
+#include <qbluetoothsocket.h>
+
+#include <QtCore/QDataStream>
+#include <QtCore/QByteArray>
+
+#include <QtCore/QStringList>
+
+TennisClient::TennisClient(QObject *parent)
+: QObject(parent), socket(0), stream(0), elapsed(new QTime), lagTimeout(0)
+{
+ lagTimer.setInterval(1000);
+ connect(&lagTimer, SIGNAL(timeout()), this, SLOT(sendEcho()));
+}
+
+TennisClient::~TennisClient()
+{
+ stopClient();
+}
+
+//! [startClient]
+void TennisClient::startClient(const QBluetoothServiceInfo &remoteService)
+{
+ if (socket)
+ return;
+
+ serviceInfo = remoteService;
+
+ // Connect to service
+ socket = new QBluetoothSocket(QBluetoothSocket::L2capSocket);
+ qDebug() << "Create socket";
+ socket->connectToService(remoteService);
+ qDebug() << "ConnecttoService done";
+
+ connect(socket, SIGNAL(readyRead()), this, SLOT(readSocket()));
+ connect(socket, SIGNAL(connected()), this, SLOT(connected()));
+ connect(socket, SIGNAL(disconnected()), this, SIGNAL(disconnected()));
+ connect(socket, SIGNAL(disconnected()), this, SLOT(socketDisconnected()));
+ connect(socket, SIGNAL(error(QBluetoothSocket::SocketError)), this, SLOT(error(QBluetoothSocket::SocketError)));
+
+ lagTimer.start();
+}
+//! [startClient]
+
+//! [stopClient]
+void TennisClient::stopClient()
+{
+ if (socket == 0) // already stopped
+ return;
+
+ qDebug() << Q_FUNC_INFO << "closing client!";
+
+ lagTimer.stop();
+
+ delete stream;
+ stream = 0;
+
+ socket->deleteLater();
+ socket = 0;
+}
+//! [stopClient]
+
+//! [socketDisconnected]
+void TennisClient::socketDisconnected()
+{
+ qDebug() << "Got socketDisconnected";
+ stopClient();
+}
+//! [socketDisconnected]
+
+//! [readSocket]
+void TennisClient::readSocket()
+{
+ if (!socket)
+ return;
+
+ while (socket->bytesAvailable()) {
+ QString str;
+
+ *stream >> str;
+
+ QStringList args = str.split(QChar(' '));
+ QString s = args.takeFirst();
+
+ if (s == "m" && args.count() == 2) {
+ emit moveBall(args.at(0).toInt(), args.at(1).toInt());
+ }
+ else if (s == "s" && args.count() == 2){
+ emit score(args.at(0).toInt(), args.at(1).toInt());
+ }
+ else if (s == "l" && args.count() == 1){
+ emit moveLeftPaddle(args.at(0).toInt());
+ }
+ else if (s == "e"){ // echo
+ QByteArray b;
+ QDataStream s(&b, QIODevice::WriteOnly);
+ s << str;
+ socket->write(b);
+ }
+ else if (s == "E"){
+ lagTimeout = 0;
+ QTime then = QTime::fromString(args.at(0), "hh:mm:ss.zzz");
+ if (then.isValid()) {
+ emit lag(then.msecsTo(QTime::currentTime()));
+// qDebug() << "RTT: " << then.msecsTo(QTime::currentTime()) << "ms";
+ }
+ }
+ else {
+ qDebug() << Q_FUNC_INFO << "Unknown command" << str;
+ }
+ }
+}
+//! [readSocket]
+
+//! [moveRightPaddle]
+void TennisClient::moveRightPaddle(int y)
+{
+ int msec = elapsed->elapsed();
+
+ if (stream && msec > 50) {
+ QByteArray b;
+ QDataStream s(&b, QIODevice::WriteOnly);
+ s << QString("r %1").arg(y);
+ socket->write(b);
+ elapsed->restart();
+ }
+}
+//! [moveRightPaddle]
+
+//! [connected]
+void TennisClient::connected()
+{
+ stream = new QDataStream(socket);
+ emit connected(socket->peerName());
+}
+//! [connected]
+
+void TennisClient::error(QBluetoothSocket::SocketError err)
+{
+ qDebug() << "Got socket error" <<Q_FUNC_INFO << "error" << err;
+ emit disconnected();
+}
+
+void TennisClient::sendEcho()
+{
+ if (lagTimeout) {
+ lagTimeout--;
+ return;
+ }
+
+ if (stream) {
+ QByteArray b;
+ QDataStream s(&b, QIODevice::WriteOnly);
+ s << QString("E %1").arg(QTime::currentTime().toString("hh:mm:ss.zzz"));
+ socket->write(b);
+ lagTimeout = 10;
+ }
+}
diff --git a/examples/bluetooth/bttennis/tennisclient.h b/examples/bluetooth/bttennis/tennisclient.h
new file mode 100644
index 00000000..aeccfca1
--- /dev/null
+++ b/examples/bluetooth/bttennis/tennisclient.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CHATCLIENT_H
+#define CHATCLIENT_H
+
+#include <qbluetoothserviceinfo.h>
+#include <qbluetoothsocket.h>
+
+#include <QtCore/QObject>
+#include <QtCore/QTime>
+#include <QtCore/QTimer>
+
+QTBLUETOOTH_BEGIN_NAMESPACE
+class QBluetoothSocket;
+QTBLUETOOTH_END_NAMESPACE
+
+QT_BEGIN_NAMESPACE
+class QDataStream;
+QT_END_NAMESPACE
+
+QTBLUETOOTH_USE_NAMESPACE
+
+//! [declaration]
+class TennisClient : public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit TennisClient(QObject *parent = 0);
+ ~TennisClient();
+
+ void startClient(const QBluetoothServiceInfo &remoteService);
+ void stopClient();
+
+public slots:
+ void moveRightPaddle(int y);
+ void error(QBluetoothSocket::SocketError);
+
+signals:
+ void moveBall(int x, int y);
+ void score(int left, int right);
+ void moveLeftPaddle(int y);
+
+ void connected(const QString &name);
+ void disconnected();
+
+ void lag(int ms);
+
+private slots:
+ void readSocket();
+ void connected();
+ void sendEcho();
+ void socketDisconnected();
+
+private:
+ QBluetoothSocket *socket;
+ QDataStream *stream;
+ QBluetoothServiceInfo serviceInfo;
+ QTime *elapsed;
+ QTimer lagTimer;
+ int lagTimeout;
+};
+//! [declaration]
+
+#endif // CHATCLIENT_H
diff --git a/examples/bluetooth/bttennis/tennisserver.cpp b/examples/bluetooth/bttennis/tennisserver.cpp
new file mode 100644
index 00000000..21af2975
--- /dev/null
+++ b/examples/bluetooth/bttennis/tennisserver.cpp
@@ -0,0 +1,306 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "tennisserver.h"
+#include "tennis.h"
+
+#include <ql2capserver.h>
+#include <qbluetoothsocket.h>
+
+#include <QDebug>
+
+TennisServer::TennisServer(QObject *parent)
+: QObject(parent), l2capServer(0), clientSocket(0), stream(0), lagReplyTimeout(0)
+{
+ elapsed.start();
+ ballElapsed.start();
+ lagTimer.setInterval(1000);
+ connect(&lagTimer, SIGNAL(timeout()), this, SLOT(sendEcho()));
+}
+
+TennisServer::~TennisServer()
+{
+ if (stream){
+ QByteArray b;
+ QDataStream s(&b, QIODevice::WriteOnly);
+ s << QString("D");
+ clientSocket->write(b);
+ }
+
+ stopServer();
+}
+
+void TennisServer::startServer()
+{
+ if (l2capServer)
+ return;
+
+ //! [Create the server]
+ l2capServer = new QL2capServer(this);
+ connect(l2capServer, SIGNAL(newConnection()), this, SLOT(clientConnected()));
+ l2capServer->listen();
+ //! [Create the server]
+
+ serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceRecordHandle, (uint)0x00010010);
+
+ //! [Class ServiceClass must contain at least 1 entry]
+ QBluetoothServiceInfo::Sequence classId;
+// classId << QVariant::fromValue(QBluetoothUuid(serviceUuid));
+ classId << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::SerialPort));
+ serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceClassIds, classId);
+ //! [Class ServiceClass must contain at least 1 entry]
+
+
+ //! [Service name, description and provider]
+ serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceName, tr("Example Tennis Server"));
+ serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceDescription,
+ tr("Example bluetooth tennis server"));
+ serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceProvider, tr("Nokia, QtDF"));
+ //! [Service name, description and provider]
+
+ //! [Service UUID set]
+ serviceInfo.setServiceUuid(QBluetoothUuid(serviceUuid));
+ //! [Service UUID set]
+
+ //! [Service Discoverability]
+ serviceInfo.setAttribute(QBluetoothServiceInfo::BrowseGroupList,
+ QBluetoothUuid(QBluetoothUuid::PublicBrowseGroup));
+ //! [Service Discoverability]
+
+
+ //! [Protocol descriptor list]
+ QBluetoothServiceInfo::Sequence protocolDescriptorList;
+ QBluetoothServiceInfo::Sequence protocol;
+ protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::L2cap))
+ << QVariant::fromValue(quint16(l2capServer->serverPort()));
+ protocolDescriptorList.append(QVariant::fromValue(protocol));
+ serviceInfo.setAttribute(QBluetoothServiceInfo::ProtocolDescriptorList,
+ protocolDescriptorList);
+ //! [Protocol descriptor list]
+
+ //! [Register service]
+ serviceInfo.registerService();
+ //! [Register service]
+
+}
+
+//! [stopServer]
+void TennisServer::stopServer()
+{
+ qDebug() <<Q_FUNC_INFO;
+ // Unregister service
+ serviceInfo.unregisterService();
+
+ delete stream;
+ stream = 0;
+
+ // Close sockets
+ delete clientSocket;
+ clientSocket = 0;
+
+ // Close server
+ delete l2capServer;
+ l2capServer = 0;
+}
+//! [stopServer]
+
+quint16 TennisServer::serverPort() const
+{
+ return l2capServer->serverPort();
+}
+
+//! [moveBall]
+void TennisServer::moveBall(int x, int y)
+{
+ int msec = ballElapsed.elapsed();
+
+ if (stream && msec > 30){
+ QByteArray b;
+ QDataStream s(&b, QIODevice::WriteOnly);
+ s << QString("m %1 %2").arg(x).arg(y);
+ //s << QLatin1String("m") << x << y;
+ clientSocket->write(b);
+ ballElapsed.restart();
+ }
+}
+//! [moveBall]
+
+void TennisServer::score(int left, int right)
+{
+ if (stream){
+ QByteArray b;
+ QDataStream s(&b, QIODevice::WriteOnly);
+ s << QString("s %1 %2").arg(left).arg(right);
+// s << QChar('s') << left << right;
+ clientSocket->write(b);
+ }
+}
+
+void TennisServer::moveLeftPaddle(int y)
+{
+
+ int msec = elapsed.elapsed();
+
+ if (stream && msec > 50) {
+ QByteArray b;
+ QDataStream s(&b, QIODevice::WriteOnly);
+ s << QString("l %1").arg(y);
+// s << QChar('l') << y;
+ clientSocket->write(b);
+ elapsed.restart();
+ }
+}
+
+void TennisServer::readSocket()
+{
+ if (!clientSocket)
+ return;
+
+ while (clientSocket->bytesAvailable()) {
+
+ QString str;
+ *stream >> str;
+ QStringList args = str.split(QChar(' '));
+ QString s = args.takeFirst();
+
+ if (s == "r" && args.count() == 1){
+ emit moveRightPaddle(args.at(0).toInt());
+ }
+ else if (s == "e" && args.count() == 1){
+ lagReplyTimeout = 0;
+ QTime then = QTime::fromString(args.at(0), "hh:mm:ss.zzz");
+ if (then.isValid()) {
+ emit lag(then.msecsTo(QTime::currentTime()));
+// qDebug() << "RTT: " << then.msecsTo(QTime::currentTime()) << "ms";
+ }
+ }
+ else if (s == "E"){
+ QByteArray b;
+ QDataStream st(&b, QIODevice::WriteOnly);
+ st << str;
+ clientSocket->write(b);
+ }
+ else if (s == "D"){
+ qDebug() << Q_FUNC_INFO << "closing!";
+ clientSocket->deleteLater();
+ clientSocket = 0;
+ }
+ else {
+ qDebug() << Q_FUNC_INFO << "Unknown command" << str;
+ }
+ }
+}
+
+//! [clientConnected]
+void TennisServer::clientConnected()
+{
+ qDebug() << Q_FUNC_INFO << "connect";
+
+ QBluetoothSocket *socket = l2capServer->nextPendingConnection();
+ if (!socket)
+ return;
+
+ if (clientSocket){
+ qDebug() << Q_FUNC_INFO << "Closing socket!";
+ delete socket;
+ return;
+ }
+
+ connect(socket, SIGNAL(readyRead()), this, SLOT(readSocket()));
+ connect(socket, SIGNAL(disconnected()), this, SLOT(clientDisconnected()));
+ connect(socket, SIGNAL(error(QBluetoothSocket::SocketError)), this, SLOT(socketError(QBluetoothSocket::SocketError)));
+
+ stream = new QDataStream(socket);
+
+ clientSocket = socket;
+
+ qDebug() << Q_FUNC_INFO << "started";
+
+ emit clientConnected(clientSocket->peerName());
+ lagTimer.start();
+}
+//! [clientConnected]
+
+void TennisServer::socketError(QBluetoothSocket::SocketError err)
+{
+ qDebug() << Q_FUNC_INFO << err;
+}
+
+//! [sendEcho]
+void TennisServer::sendEcho()
+{
+ if (lagReplyTimeout) {
+ lagReplyTimeout--;
+ return;
+ }
+
+ if (stream) {
+ QByteArray b;
+ QDataStream s(&b, QIODevice::WriteOnly);
+ s << QString("e %1").arg(QTime::currentTime().toString("hh:mm:ss.zzz"));
+ clientSocket->write(b);
+ lagReplyTimeout = 10;
+ }
+}
+//! [sendEcho]
+
+//! [clientDisconnected]
+void TennisServer::clientDisconnected()
+{
+ qDebug() << Q_FUNC_INFO << "client closing!";
+
+ lagTimer.stop();
+ lagReplyTimeout = 0;
+ QBluetoothSocket *socket = qobject_cast<QBluetoothSocket *>(sender());
+ if (!socket)
+ return;
+
+ emit clientDisconnected(socket->peerName());
+
+ clientSocket->deleteLater();
+ clientSocket = 0;
+ delete stream;
+ stream = 0;
+
+// socket->deleteLater();
+}
+//! [clientDisconnected]
+
diff --git a/examples/bluetooth/bttennis/tennisserver.h b/examples/bluetooth/bttennis/tennisserver.h
new file mode 100644
index 00000000..bfce30ae
--- /dev/null
+++ b/examples/bluetooth/bttennis/tennisserver.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TENNISSERVER_H
+#define TENNISSERVER_H
+
+#include <qbluetoothserviceinfo.h>
+#include <qbluetoothsocket.h>
+
+#include <QtCore/QObject>
+#include <QtCore/QList>
+#include <QtCore/QDataStream>
+#include <QtCore/QTime>
+#include <QtCore/QTimer>
+
+QTBLUETOOTH_BEGIN_NAMESPACE
+class QL2capServer;
+class QBluetoothSocket;
+class QBluetoothServiceInfo;
+QTBLUETOOTH_END_NAMESPACE
+
+QTBLUETOOTH_USE_NAMESPACE
+
+//! [declaration]
+class TennisServer : public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit TennisServer(QObject *parent = 0);
+ ~TennisServer();
+
+ void startServer();
+ void stopServer();
+
+ quint16 serverPort() const;
+
+public slots:
+ void moveBall(int x, int y);
+ void score(int left, int right);
+ void moveLeftPaddle(int y);
+
+signals:
+ void moveRightPaddle(int y);
+ void clientDisconnected(const QString &name);
+ void clientConnected(const QString &name);
+ void lag(int ms);
+
+private slots:
+ void clientConnected();
+ void clientDisconnected();
+ void readSocket();
+ void sendEcho();
+ void socketError(QBluetoothSocket::SocketError err);
+
+private:
+ QL2capServer *l2capServer;
+ QBluetoothServiceInfo serviceInfo;
+ QBluetoothSocket *clientSocket;
+ QDataStream *stream;
+ QTime elapsed;
+ QTime ballElapsed;
+ QTimer lagTimer;
+ int lagReplyTimeout;
+};
+//! [declaration]
+
+#endif // CHATSERVER_H
diff --git a/examples/bluetooth/bttennis/tennisview.cpp b/examples/bluetooth/bttennis/tennisview.cpp
new file mode 100644
index 00000000..74a43354
--- /dev/null
+++ b/examples/bluetooth/bttennis/tennisview.cpp
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "tennisview.h"
+
+#include <QMouseEvent>
+
+TennisView::TennisView(QWidget *parent) :
+ QGraphicsView(parent)
+{
+}
+
+void TennisView::mousePressEvent(QMouseEvent *event)
+{
+ QPointF p = mapToScene(event->x(), event->y());
+ emit mousePress(p.x(), p.y());
+ emit mouseMove(p.x(), p.y());
+ last_y = p.y();
+}
+
+void TennisView::mouseMoveEvent(QMouseEvent *event)
+{
+ if (event->buttons()) {
+ QPointF p = mapToScene(event->x(), event->y());
+ if (10 < abs(last_y - event->y())) {
+// emit mouseMove(p.x(), p.y());
+ last_y = p.y();
+ }
+ }
+}
diff --git a/examples/bluetooth/bttennis/tennisview.h b/examples/bluetooth/bttennis/tennisview.h
new file mode 100644
index 00000000..f6bb767e
--- /dev/null
+++ b/examples/bluetooth/bttennis/tennisview.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef TENNISVIEW_H
+#define TENNISVIEW_H
+
+#include <QGraphicsView>
+
+class TennisView : public QGraphicsView
+{
+ Q_OBJECT
+public:
+ explicit TennisView(QWidget *parent = 0);
+
+signals:
+ void mouseMove(int x, int y);
+ void mousePress(int x, int y);
+
+public slots:
+
+protected:
+ void mousePressEvent(QMouseEvent *event);
+ void mouseMoveEvent(QMouseEvent *ev);
+
+private:
+ int last_y;
+
+};
+
+#endif // TENNISVIEW_H
diff --git a/examples/bluetooth/scanner/qmlscanner.cpp b/examples/bluetooth/scanner/qmlscanner.cpp
new file mode 100644
index 00000000..b86ed72f
--- /dev/null
+++ b/examples/bluetooth/scanner/qmlscanner.cpp
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the examples of the QtBluetooth module.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Digia Plc and its Subsidiary(-ies) 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 <QtGui/QGuiApplication>
+#include <QtQuick/QQuickView>
+#include <QtQml/QQmlEngine>
+
+int main(int argc, char *argv[])
+{
+ QGuiApplication application(argc, argv);
+ const QString mainQmlApp = QLatin1String("qrc:/scanner.qml");
+ QQuickView view;
+ view.setSource(QUrl(mainQmlApp));
+ view.setResizeMode(QQuickView::SizeRootObjectToView);
+ // Qt.quit() called in embedded .qml by default only emits
+ // quit() signal, so do this (optionally use Qt.exit()).
+ QObject::connect(view.engine(), SIGNAL(quit()), qApp, SLOT(quit()));
+#if defined(Q_WS_MAEMO_6)
+ view.showFullScreen();
+#else
+ view.setGeometry(QRect(100, 100, 360, 640));
+ view.show();
+#endif
+ return application.exec();
+}
diff --git a/examples/bluetooth/scanner/scanner.pro b/examples/bluetooth/scanner/scanner.pro
new file mode 100644
index 00000000..ff046a96
--- /dev/null
+++ b/examples/bluetooth/scanner/scanner.pro
@@ -0,0 +1,11 @@
+QT += concurrent network bluetooth quick
+SOURCES += qmlscanner.cpp
+
+TARGET = qml_scanner
+TEMPLATE = app
+
+RESOURCES += \
+ scanner.qrc
+
+OTHER_FILES += \
+ scanner.qml
diff --git a/examples/bluetooth/scanner/scanner.qml b/examples/bluetooth/scanner/scanner.qml
new file mode 100644
index 00000000..e83b0a03
--- /dev/null
+++ b/examples/bluetooth/scanner/scanner.qml
@@ -0,0 +1,246 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the examples of the QtBluetooth module.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Digia Plc and its Subsidiary(-ies) 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$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import QtBluetooth 5.0
+
+Item {
+ id: top
+
+ property BluetoothService currentService
+ property alias minimalDiscovery: myModel.minimalDiscovery
+
+ BluetoothDiscoveryModel {
+ id: myModel
+ minimalDiscovery: true
+ onDiscoveryChanged: busy.running = discovery;
+ onNewServiceDiscovered: console.log("Found new service " + service.deviceAddress + " " + service.deviceName + " " + service.serviceName);
+ }
+
+ Rectangle {
+ id: busy
+ property bool running: true
+
+ width: top.width/1.2;
+ x: top.width/2-width/2
+ anchors.top: top.top;
+ height: 20;
+ radius: 5
+ color: "#1c56f3"
+
+ Text {
+ id: text
+ text: "<b>Scanning</b>"
+ x: busy.width/2-paintedWidth/2
+ y: busy.height/2-paintedHeight/2
+ }
+
+ SequentialAnimation on color {
+ id: busyThrobber
+ ColorAnimation { easing.type: Easing.InOutSine; from: "#1c56f3"; to: "white"; duration: 1000; }
+ ColorAnimation { easing.type: Easing.InOutSine; to: "#1c56f3"; from: "white"; duration: 1000 }
+ loops: Animation.Infinite
+ }
+ states: [
+ State {
+ name: "stopped"
+ when: !busy.running
+ PropertyChanges { target: busy; height: 0; }
+ PropertyChanges { target: busyThrobber; running: false }
+ PropertyChanges { target: text; visible: false }
+ }
+ ]
+ transitions: [
+ Transition {
+ from: "*"
+ to: "stopped"
+ reversible: true
+ NumberAnimation { target: busy; property: "height"; to: 0; duration: 200 }
+ }
+ ]
+ }
+
+ Component {
+ id: del;
+
+ Item {
+ id: item
+
+ function item_clicked(service) {
+ console.log("Clicked " + service.deviceName + service.deviceAddress);
+ top.currentService = service;
+ }
+
+ property int text_height: 5+(bticon.height > bttext.height ? bticon.height : bttext.height)
+
+ height: text_height
+ width: parent.width
+
+ Column {
+ anchors.fill: item
+ Row {
+ width: parent.width
+ Image {
+ id: bticon
+ source: icon;
+ width: del.height;
+ }
+ Text {
+ id: bttext
+ text: name;
+ font.family: "FreeSerif"
+ font.pointSize: 12
+ }
+ }
+ Text {
+ function get_details(s) {
+ var str = "Address: " + s.deviceAddress;
+ if (s.serviceName) { str += "<br>Service: " + s.serviceName; }
+ if (s.serviceDescription) { str += "<br>Description: " + s.serviceDescription; }
+ if (s.serviceProtocol) { str += "<br>Port: " + s.serviceProtocol; }
+ if (s.servicePort) { str += "<br>Port: " + s.servicePort; }
+ return str;
+ }
+
+ id: details
+ opacity: 0.0
+ text: get_details(service)
+ font: bttext.font
+ x: bticon.width
+ }
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: item.state = ((item.state == "details") ? "" : "details")
+ }
+
+ states: [
+ State {
+ name: "details"
+ PropertyChanges { target: item; height: item.text_height+details.height; }
+ PropertyChanges { target: details; opacity: 1.0 }
+ }
+ ]
+ transitions: [
+ Transition {
+ from: "*"
+ to: "details"
+ reversible: true
+ NumberAnimation { target: item; property: "height"; duration: 200 }
+ NumberAnimation { target: details; property: "lopacity"; duration: 200 }
+ }
+ ]
+ }
+ }
+
+ Component {
+ id: highlightBox
+
+ Rectangle {
+ id: background
+ anchors.fill: del
+ border.color: "#34ca57"
+ radius: 5
+ border.width: 2
+ }
+
+ }
+
+ ListView {
+ id: mainList
+ width: top.width
+ anchors.top: busy.bottom
+ anchors.bottom: fullbutton.top
+
+ model: myModel
+ highlight: highlightBox
+ delegate: del
+ focus: true
+ }
+
+ Rectangle {
+ id: fullbutton
+
+ function button_clicked() {
+ myModel.minimalDiscovery = !myModel.minimalDiscovery;
+ fullbutton.state = fullbutton.state == "clicked" ? "" : "clicked";
+ myModel.setDiscovery(true);
+ }
+
+ anchors.bottom: top.bottom
+ anchors.margins: 3
+
+ width: top.width-6
+ x: 3
+ height: 20
+
+ radius: 5
+ border.width: 1
+ color: "white"
+
+ Text {
+ id: label
+ text: "Full Discovery"
+ x: parent.width/2-paintedWidth/2;
+ y: parent.height/2-paintedHeight/2;
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: fullbutton.button_clicked();
+ }
+
+ states: [
+ State {
+ name: "clicked"
+ PropertyChanges { target: fullbutton; color: "#1c56f3" }
+ }
+ ]
+ transitions: [
+ Transition {
+ from: "*"
+ to: "details"
+ reversible: true
+ ColorAnimation { duration: 200 }
+ }
+ ]
+ }
+}
diff --git a/examples/bluetooth/scanner/scanner.qrc b/examples/bluetooth/scanner/scanner.qrc
new file mode 100644
index 00000000..93e9ce08
--- /dev/null
+++ b/examples/bluetooth/scanner/scanner.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/">
+ <file>scanner.qml</file>
+ </qresource>
+</RCC>