summaryrefslogtreecommitdiffstats
path: root/examples/bluetooth/bttennis
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/bttennis
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/bttennis')
-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
21 files changed, 2573 insertions, 0 deletions
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