diff options
Diffstat (limited to 'examples')
-rw-r--r-- | examples/bttennis/board.cpp | 250 | ||||
-rw-r--r-- | examples/bttennis/board.h | 126 | ||||
-rw-r--r-- | examples/bttennis/bttennis.pro | 36 | ||||
-rw-r--r-- | examples/bttennis/connect.png | bin | 0 -> 11074 bytes | |||
-rw-r--r-- | examples/bttennis/controller.cpp | 263 | ||||
-rw-r--r-- | examples/bttennis/controller.h | 100 | ||||
-rw-r--r-- | examples/bttennis/handover.cpp | 130 | ||||
-rw-r--r-- | examples/bttennis/handover.h | 94 | ||||
-rw-r--r-- | examples/bttennis/main.cpp | 63 | ||||
-rw-r--r-- | examples/bttennis/tennis.cpp | 424 | ||||
-rw-r--r-- | examples/bttennis/tennis.h | 140 | ||||
-rw-r--r-- | examples/bttennis/tennis.qrc | 5 | ||||
-rw-r--r-- | examples/bttennis/tennis.ui | 57 | ||||
-rw-r--r-- | examples/bttennis/tennisclient.cpp | 200 | ||||
-rw-r--r-- | examples/bttennis/tennisclient.h | 102 | ||||
-rw-r--r-- | examples/bttennis/tennisserver.cpp | 306 | ||||
-rw-r--r-- | examples/bttennis/tennisserver.h | 106 | ||||
-rw-r--r-- | examples/bttennis/tennisview.cpp | 69 | ||||
-rw-r--r-- | examples/bttennis/tennisview.h | 69 |
19 files changed, 2540 insertions, 0 deletions
diff --git a/examples/bttennis/board.cpp b/examples/bttennis/board.cpp new file mode 100644 index 00000000..81128657 --- /dev/null +++ b/examples/bttennis/board.cpp @@ -0,0 +1,250 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $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> ®ion) +{ + 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/bttennis/board.h b/examples/bttennis/board.h new file mode 100644 index 00000000..d6baa765 --- /dev/null +++ b/examples/bttennis/board.h @@ -0,0 +1,126 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $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> ®ion); + + 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/bttennis/bttennis.pro b/examples/bttennis/bttennis.pro new file mode 100644 index 00000000..0532a029 --- /dev/null +++ b/examples/bttennis/bttennis.pro @@ -0,0 +1,36 @@ +TARGET = bttennis + +INCLUDEPATH += \ + ../../src/connectivity/bluetooth \ + ../../src/connectivity/nfc + +DEPENDPATH += \ + ../../src/connectivity/bluetooth \ + ../../src/connectivity/nfc + +QT += bluetooth nfc widgets + +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/bttennis/connect.png b/examples/bttennis/connect.png Binary files differnew file mode 100644 index 00000000..70b64c6c --- /dev/null +++ b/examples/bttennis/connect.png diff --git a/examples/bttennis/controller.cpp b/examples/bttennis/controller.cpp new file mode 100644 index 00000000..954470ff --- /dev/null +++ b/examples/bttennis/controller.cpp @@ -0,0 +1,263 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $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/bttennis/controller.h b/examples/bttennis/controller.h new file mode 100644 index 00000000..8f966e29 --- /dev/null +++ b/examples/bttennis/controller.h @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $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/bttennis/handover.cpp b/examples/bttennis/handover.cpp new file mode 100644 index 00000000..1e0bf042 --- /dev/null +++ b/examples/bttennis/handover.cpp @@ -0,0 +1,130 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $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/bttennis/handover.h b/examples/bttennis/handover.h new file mode 100644 index 00000000..885b6284 --- /dev/null +++ b/examples/bttennis/handover.h @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $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/bttennis/main.cpp b/examples/bttennis/main.cpp new file mode 100644 index 00000000..ffb08329 --- /dev/null +++ b/examples/bttennis/main.cpp @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $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) || defined(Q_OS_SYMBIAN) + d.showFullScreen(); +#else + d.show(); +#endif + + app.exec(); + + return 0; +} + diff --git a/examples/bttennis/tennis.cpp b/examples/bttennis/tennis.cpp new file mode 100644 index 00000000..57b872e8 --- /dev/null +++ b/examples/bttennis/tennis.cpp @@ -0,0 +1,424 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $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_SYMBIAN) || defined(Q_OS_WINCE) || defined(Q_WS_MAEMO_5) || 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/bttennis/tennis.h b/examples/bttennis/tennis.h new file mode 100644 index 00000000..6286a0cf --- /dev/null +++ b/examples/bttennis/tennis.h @@ -0,0 +1,140 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $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/bttennis/tennis.qrc b/examples/bttennis/tennis.qrc new file mode 100644 index 00000000..12aa7464 --- /dev/null +++ b/examples/bttennis/tennis.qrc @@ -0,0 +1,5 @@ +<RCC> + <qresource prefix="/icons"> + <file>connect.png</file> + </qresource> +</RCC> diff --git a/examples/bttennis/tennis.ui b/examples/bttennis/tennis.ui new file mode 100644 index 00000000..d6625fa8 --- /dev/null +++ b/examples/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/bttennis/tennisclient.cpp b/examples/bttennis/tennisclient.cpp new file mode 100644 index 00000000..ae7e5ceb --- /dev/null +++ b/examples/bttennis/tennisclient.cpp @@ -0,0 +1,200 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $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/bttennis/tennisclient.h b/examples/bttennis/tennisclient.h new file mode 100644 index 00000000..a5d95200 --- /dev/null +++ b/examples/bttennis/tennisclient.h @@ -0,0 +1,102 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $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 + +class QDataStream; + +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/bttennis/tennisserver.cpp b/examples/bttennis/tennisserver.cpp new file mode 100644 index 00000000..4982bb87 --- /dev/null +++ b/examples/bttennis/tennisserver.cpp @@ -0,0 +1,306 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $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/bttennis/tennisserver.h b/examples/bttennis/tennisserver.h new file mode 100644 index 00000000..4786a760 --- /dev/null +++ b/examples/bttennis/tennisserver.h @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $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/bttennis/tennisview.cpp b/examples/bttennis/tennisview.cpp new file mode 100644 index 00000000..a51b388b --- /dev/null +++ b/examples/bttennis/tennisview.cpp @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $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/bttennis/tennisview.h b/examples/bttennis/tennisview.h new file mode 100644 index 00000000..0c02b7b3 --- /dev/null +++ b/examples/bttennis/tennisview.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $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 |