diff options
-rw-r--r-- | examples/bluetooth/bluetooth.pro | 2 | ||||
-rw-r--r-- | examples/bluetooth/pingpong/assets/Board.qml | 180 | ||||
-rw-r--r-- | examples/bluetooth/pingpong/assets/Dialog.qml | 61 | ||||
-rw-r--r-- | examples/bluetooth/pingpong/assets/Menu.qml | 119 | ||||
-rw-r--r-- | examples/bluetooth/pingpong/assets/main.qml | 62 | ||||
-rw-r--r-- | examples/bluetooth/pingpong/doc/images/intro.png | bin | 0 -> 27442 bytes | |||
-rw-r--r-- | examples/bluetooth/pingpong/doc/images/intro1.png | bin | 0 -> 12522 bytes | |||
-rw-r--r-- | examples/bluetooth/pingpong/doc/src/pingpong.qdoc | 80 | ||||
-rw-r--r-- | examples/bluetooth/pingpong/main.cpp | 54 | ||||
-rw-r--r-- | examples/bluetooth/pingpong/pingpong.cpp | 463 | ||||
-rw-r--r-- | examples/bluetooth/pingpong/pingpong.h | 139 | ||||
-rw-r--r-- | examples/bluetooth/pingpong/pingpong.pro | 19 | ||||
-rw-r--r-- | examples/bluetooth/pingpong/resource.qrc | 8 | ||||
-rw-r--r-- | src/bluetooth/doc/src/bluetooth-index.qdoc | 1 | ||||
-rw-r--r-- | src/bluetooth/doc/src/examples.qdoc | 3 |
15 files changed, 1190 insertions, 1 deletions
diff --git a/examples/bluetooth/bluetooth.pro b/examples/bluetooth/bluetooth.pro index e8a6f9a6..251d7dd1 100644 --- a/examples/bluetooth/bluetooth.pro +++ b/examples/bluetooth/bluetooth.pro @@ -6,4 +6,4 @@ qtHaveModule(widgets) { bttennis } -qtHaveModule(quick): SUBDIRS += scanner picturetransfer +qtHaveModule(quick): SUBDIRS += scanner picturetransfer pingpong diff --git a/examples/bluetooth/pingpong/assets/Board.qml b/examples/bluetooth/pingpong/assets/Board.qml new file mode 100644 index 00000000..bd78c18b --- /dev/null +++ b/examples/bluetooth/pingpong/assets/Board.qml @@ -0,0 +1,180 @@ +/*************************************************************************** +** +** Copyright (C) 2014 BlackBerry Limited. All rights reserved. +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the QtBluetooth module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Window 2.1 + +Rectangle { + id: board + width: 600 + height: 300 + + // 1 - server role; left pedal + // 2 - client role; right pedal + property int roleSide: pingPong.role + onRoleSideChanged: { + if (pingPong.role == 1) { + rightMouse.opacity = 0.7 + rightMouse.enabled = false + } + else if (pingPong.role == 2) { + leftMouse.opacity = 0.7 + leftMouse.enabled = false + } + } + + property bool deviceMessage: pingPong.showDialog + onDeviceMessageChanged: { + if (pingPong.showDialog) { + info.visible = true; + board.opacity = 0.5; + } else { + info.visible = false; + board.opacity = 1; + } + } + + property double leftBlockUpdate: pingPong.leftBlockY + onLeftBlockUpdateChanged: leftblock.y = pingPong.leftBlockY + + property double rightBlockUpdate: pingPong.rightBlockY + onRightBlockUpdateChanged: rightblock.y = pingPong.rightBlockY + + property double leftBlockY: leftblock.y + onLeftBlockYChanged: pingPong.updateLeftBlock(leftblock.y) + + property double rightBlockY: rightblock.y + onRightBlockYChanged: pingPong.updateRightBlock(rightblock.y) + + // Left pedal - server role + Rectangle { + id: leftblock + y: (parent.height/2) + width: (parent.width/27) + height: (parent.height/5) + anchors.left: parent.left + color: "#363636" + radius: 10 + + MouseArea { + id: leftMouse + anchors.fill: parent + acceptedButtons: Qt.LeftButton + drag.target: leftblock + drag.axis: Drag.YAxis + drag.minimumY: 0 + drag.maximumY: (board.height - leftblock.height) + } + } + + // Right pedal - client role + Rectangle { + id: rightblock + y: (parent.height/2) + width: (parent.width/27) + height: (parent.height/5) + anchors.right: parent.right + color: "#363636" + radius: 10 + + MouseArea { + id: rightMouse + anchors.fill: parent + acceptedButtons: Qt.LeftButton + drag.target: rightblock + drag.axis: Drag.YAxis + drag.minimumY: 0 + drag.maximumY: (board.height - rightblock.height) + } + } + + Rectangle { + id: splitter + color: "#363636" + anchors.horizontalCenter: parent.horizontalCenter + height: parent.height + width: parent.width/100 + } + + Text { + id: leftResult + text: pingPong.leftResult + font.bold: true + font.pixelSize: 30 + anchors.right: splitter.left + anchors.top: parent.top + anchors.margins: 15 + } + + Text { + id: rightResult + text: pingPong.rightResult + font.bold: true + font.pixelSize: 30 + anchors.left: splitter.right + anchors.top: parent.top + anchors.margins: 15 + } + + Rectangle { + id: ball + width: leftblock.width/2 + height: leftblock.width/2 + radius: width + color: "#363636" + x: pingPong.ballX + y: pingPong.ballY + + SequentialAnimation { + running: true + NumberAnimation { target: ball; property: "x"; duration: 50 } + NumberAnimation { target: ball; property: "y"; duration: 50 } + } + } + + Component.onCompleted: { + if (menulist.height == Screen.height && menulist.width == Screen.width) + pingPong.setSize(Screen.width, Screen.height) + else + pingPong.setSize(board.width, board.height) + pingPong.updateLeftBlock(leftblock.y) + pingPong.updateRightBlock(rightblock.y) + } +} diff --git a/examples/bluetooth/pingpong/assets/Dialog.qml b/examples/bluetooth/pingpong/assets/Dialog.qml new file mode 100644 index 00000000..da7f09d2 --- /dev/null +++ b/examples/bluetooth/pingpong/assets/Dialog.qml @@ -0,0 +1,61 @@ +/*************************************************************************** +** +** Copyright (C) 2014 BlackBerry Limited. All rights reserved. +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the QtBluetooth module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 + +Rectangle { + width: parent.width/2 + height: 100 + z: 50 + border.width: 2 + border.color: "#363636" + radius: 10 + + Text { + id: message + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + anchors.fill: parent + wrapMode: Text.WordWrap + elide: Text.ElideMiddle + text: pingPong.message + color: "#363636" + } +} diff --git a/examples/bluetooth/pingpong/assets/Menu.qml b/examples/bluetooth/pingpong/assets/Menu.qml new file mode 100644 index 00000000..719cac3a --- /dev/null +++ b/examples/bluetooth/pingpong/assets/Menu.qml @@ -0,0 +1,119 @@ +/*************************************************************************** +** +** Copyright (C) 2014 BlackBerry Limited. All rights reserved. +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the QtBluetooth module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 + +Rectangle { + width: 600 + height: 300 + + + Rectangle { + width: parent.width + height: 70 + border.width: 1 + border.color: "#363636" + radius: 5 + + Text { + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + anchors.fill: parent + text: "Welcome to PingPong Game \n Please select an option" + font.pixelSize: 20 + elide: Text.ElideMiddle + color: "#363636" + } + } + + Rectangle { + id: startServer + anchors.centerIn: parent + width: parent.width/2 + height: parent.height/5 + color: "#363636" + + Text { + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + anchors.fill: parent + font.bold: true + text: "Start PingPong server" + color: "#E3E3E3" + elide: Text.ElideMiddle + } + + MouseArea { + anchors.fill: parent + onClicked: { + pageLoader.source = "Board.qml"; + pingPong.startServer(); + } + } + } + + Rectangle { + id: startClient + anchors.horizontalCenter: parent.horizontalCenter + anchors.top: startServer.bottom + anchors.topMargin: 10 + width: parent.width/2 + height: parent.height/5 + color: "#363636" + + Text { + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + anchors.fill: parent + font.bold: true + text: "Start PingPong client" + color: "#E3E3E3" + elide: Text.ElideMiddle + } + + MouseArea { + anchors.fill: parent + onClicked: { + pageLoader.source = "Board.qml"; + pingPong.startClient() + } + } + } +} diff --git a/examples/bluetooth/pingpong/assets/main.qml b/examples/bluetooth/pingpong/assets/main.qml new file mode 100644 index 00000000..2a155662 --- /dev/null +++ b/examples/bluetooth/pingpong/assets/main.qml @@ -0,0 +1,62 @@ +/*************************************************************************** +** +** Copyright (C) 2014 BlackBerry Limited. All rights reserved. +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the QtBluetooth module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Window 2.1 + +Window { + id: menulist + width: 600 + height: 300 + visible: true + + Dialog { + id: info + anchors.centerIn: parent + visible: false + } + + Component.onCompleted: pageLoader.source = "Menu.qml" + + Loader { + id: pageLoader + anchors.fill: parent + } +} diff --git a/examples/bluetooth/pingpong/doc/images/intro.png b/examples/bluetooth/pingpong/doc/images/intro.png Binary files differnew file mode 100644 index 00000000..062b8ea0 --- /dev/null +++ b/examples/bluetooth/pingpong/doc/images/intro.png diff --git a/examples/bluetooth/pingpong/doc/images/intro1.png b/examples/bluetooth/pingpong/doc/images/intro1.png Binary files differnew file mode 100644 index 00000000..c1cedae2 --- /dev/null +++ b/examples/bluetooth/pingpong/doc/images/intro1.png diff --git a/examples/bluetooth/pingpong/doc/src/pingpong.qdoc b/examples/bluetooth/pingpong/doc/src/pingpong.qdoc new file mode 100644 index 00000000..df7fcc34 --- /dev/null +++ b/examples/bluetooth/pingpong/doc/src/pingpong.qdoc @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the documentation of the Qt Toolkit. +** +** $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 pingpong + \title Bluetooth QML Ping Pong example + + The Bluetooth QML Ping Pong example presents the socket communication between two + Bluetooth devices. The basic concept is the ping pong game where two players + communicate via sockets. + + \image intro.png + + At the beginning, the user selects the role. One device acts as a server and the second + one as a client. After selecting the role, adjustments to the screen size are done + (two devices might have different screen sizes). The server side starts a service named + "PingPong server". + + \snippet pingpong/pingpong.cpp Starting the server + + On the client side, the full service discovery on the nearby Bluetooth devices is done. + + \snippet pingpong/pingpong.cpp Searching for the service + + When the ping pong service is discovered, the client connects to the server using the socket. + + \snippet pingpong/pingpong.cpp Connecting the socket + + On the server side, the connected signal is emitted initiating that the client is connected. + The necessary signals and slots on the server side are connected. + + \snippet pingpong/pingpong.cpp Initiating server socket + + The game starts after the devices are connected and the screen is adjusted. + + \snippet pingpong/pingpong.cpp Start the game + + The server updates the ball direction and coordinates. The coordinates of pedals are sent + to each other every 50ms. + + \snippet pingpong/pingpong.cpp Updating coordinates + + The coordinates are updated and exchanged via sockets. As presented, the server sends its + pedal's y coordinate and the ball coordinates whereas, the client sends only its pedal + y coordinate. + + \snippet pingpong/pingpong.cpp Checking the boundaries + + In the code above, it was shown how the server checks whether the ball has reached + the boundaries of the board. In the case of the goal, the server updates + the results via its socket. + + \image intro1.png + +*/ + diff --git a/examples/bluetooth/pingpong/main.cpp b/examples/bluetooth/pingpong/main.cpp new file mode 100644 index 00000000..86cbb8bf --- /dev/null +++ b/examples/bluetooth/pingpong/main.cpp @@ -0,0 +1,54 @@ +/*************************************************************************** +** +** Copyright (C) 2014 BlackBerry Limited. All rights reserved. +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the QtBluetooth module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QQmlContext> +#include <QGuiApplication> +#include <QQmlApplicationEngine> +#include "pingpong.h" + +int main(int argc, char *argv[]) +{ + QGuiApplication app(argc, argv); + PingPong pingPong; + QQmlApplicationEngine engine; + engine.rootContext()->setContextProperty("pingPong", &pingPong); + engine.load(QUrl("qrc:/assets/main.qml")); + return app.exec(); +} diff --git a/examples/bluetooth/pingpong/pingpong.cpp b/examples/bluetooth/pingpong/pingpong.cpp new file mode 100644 index 00000000..d65a56a8 --- /dev/null +++ b/examples/bluetooth/pingpong/pingpong.cpp @@ -0,0 +1,463 @@ +/*************************************************************************** +** +** Copyright (C) 2014 BlackBerry Limited. All rights reserved. +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the QtBluetooth module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "pingpong.h" +#include <QDebug> + +PingPong::PingPong(): + m_serverInfo(0), socket(0), discoveryAgent(0), interval(5), m_resultLeft(0), m_resultRight(0), + m_showDialog(false), m_role(0), m_proportionX(0), m_proportionY(0), m_serviceFound(false) +{ + m_timer = new QTimer(this); + connect(m_timer, SIGNAL(timeout()), this, SLOT(update())); +} + +PingPong::~PingPong() +{ + delete m_timer; + delete m_serverInfo; + delete socket; + delete discoveryAgent; +} + +void PingPong::startGame() +{ + m_showDialog = false; + Q_EMIT showDialogChanged(); + //! [Start the game] + if (m_role == 1) + updateDirection(); + + m_timer->start(50); + //! [Start the game] +} + +void PingPong::update() +{ + QByteArray size; + // Server is only updating the coordinates + //! [Updating coordinates] + if (m_role == 1) { + checkBoundaries(); + m_ballPreviousX = m_ballX; + m_ballPreviousY = m_ballY; + m_ballY = m_direction*(m_ballX+interval) - m_direction*m_ballX + m_ballY; + m_ballX = m_ballX + interval; + + size.setNum(m_ballX); + size.append(' '); + QByteArray size1; + size1.setNum(m_ballY); + size.append(size1); + size.append(' '); + size1.setNum(m_leftBlockY); + size.append(size1); + size.append(" \n"); + socket->write(size.constData()); + Q_EMIT ballChanged(); + } + else if (m_role == 2) { + size.setNum(m_rightBlockY); + size.append(" \n"); + socket->write(size.constData()); + } + //! [Updating coordinates] +} + + + +void PingPong::setSize(const float &x, const float &y) +{ + m_boardWidth = x; + m_boardHeight = y; + m_targetX = m_boardWidth; + m_targetY = m_boardHeight/2; + m_ballPreviousX = m_ballX = m_boardWidth/2; + m_ballPreviousY = m_ballY = m_boardHeight - m_boardWidth/54; + Q_EMIT ballChanged(); +} + +void PingPong::updateBall(const float &bX, const float &bY) +{ + m_ballX = bX; + m_ballY = bY; +} + +void PingPong::updateLeftBlock(const float &lY) +{ + m_leftBlockY = lY; +} + +void PingPong::updateRightBlock(const float &rY) +{ + m_rightBlockY = rY; +} + +void PingPong::checkBoundaries() +{ + float ballWidth = m_boardWidth/54; + float blockSize = m_boardWidth/27; + float blockHeight = m_boardHeight/5; + //! [Checking the boundaries] + if (((m_ballX + ballWidth) > (m_boardWidth - blockSize)) && ((m_ballY + ballWidth) < (m_rightBlockY + blockHeight)) + && (m_ballY > m_rightBlockY)) { + m_targetY = 2 * m_ballY - m_ballPreviousY; + m_targetX = m_ballPreviousX; + interval = -5; + updateDirection(); + } + else if ((m_ballX < blockSize) && ((m_ballY + ballWidth) < (m_leftBlockY + blockHeight)) + && (m_ballY > m_leftBlockY)) { + m_targetY = 2 * m_ballY - m_ballPreviousY; + m_targetX = m_ballPreviousX; + interval = 5; + updateDirection(); + } + else if (m_ballY < 0 || (m_ballY + ballWidth > m_boardHeight)) { + m_targetY = m_ballPreviousY; + m_targetX = m_ballX + interval; + updateDirection(); + } + //! [Checking the boundaries] + else if ((m_ballX + ballWidth) > m_boardWidth) { + m_resultLeft++; + m_targetX = m_boardWidth; + m_targetY = m_boardHeight/2; + m_ballPreviousX = m_ballX = m_boardWidth/2; + m_ballPreviousY = m_ballY = m_boardHeight - m_boardWidth/54; + + updateDirection(); + checkResult(); + QByteArray result; + result.append("result "); + QByteArray res; + res.setNum(m_resultLeft); + result.append(res); + result.append(' '); + res.setNum(m_resultRight); + result.append(res); + result.append(" \n"); + socket->write(result); + qDebug() << result; + Q_EMIT resultChanged(); + } + else if (m_ballX < 0) { + m_resultRight++; + m_targetX = 0; + m_targetY = m_boardHeight/2; + m_ballPreviousX = m_ballX = m_boardWidth/2; + m_ballPreviousY = m_ballY = m_boardHeight - m_boardWidth/54; + updateDirection(); + checkResult(); + QByteArray result; + result.append("result "); + QByteArray res; + res.setNum(m_resultLeft); + result.append(res); + result.append(' '); + res.setNum(m_resultRight); + result.append(res); + result.append(" \n"); + socket->write(result); + Q_EMIT resultChanged(); + } +} + +void PingPong::checkResult() +{ + if (m_resultRight == 10 && m_role == 2) { + setMessage("Game over. You win!"); + m_timer->stop(); + } + else if (m_resultRight == 10 && m_role == 1) { + setMessage("Game over. You lose!"); + m_timer->stop(); + } + else if (m_resultLeft == 10 && m_role == 1) { + setMessage("Game over. You win!"); + m_timer->stop(); + } + else if (m_resultLeft == 10 && m_role == 2) { + setMessage("Game over. You lose!"); + m_timer->stop(); + } +} + +void PingPong::updateDirection() +{ + m_direction = (m_targetY - m_ballY)/(m_targetX - m_ballX); +} + +void PingPong::startServer() +{ + setMessage(QStringLiteral("Starting the server")); + //! [Starting the server] + m_serverInfo = new QBluetoothServer(QBluetoothServiceInfo::RfcommProtocol, this); + connect(m_serverInfo, SIGNAL(newConnection()), this, SLOT(clientConnected())); + connect(m_serverInfo, SIGNAL(error(QBluetoothServer::Error)), + this, SLOT(serverError(QBluetoothServer::Error))); + const QBluetoothUuid uuid(serviceUuid); + + m_serverInfo->listen(uuid, QStringLiteral("PingPong server")); + //! [Starting the server] + setMessage(QStringLiteral("Server started, waiting for the client. You are the left player.")); + // m_role is set to 1 if it is a server + m_role = 1; + Q_EMIT roleChanged(); +} + +void PingPong::startClient() +{ + //! [Searching for the service] + discoveryAgent = new QBluetoothServiceDiscoveryAgent(QBluetoothAddress()); + + connect(discoveryAgent, SIGNAL(serviceDiscovered(QBluetoothServiceInfo)), + this, SLOT(addService(QBluetoothServiceInfo))); + connect(discoveryAgent, SIGNAL(finished()), this, SLOT(done())); + connect(discoveryAgent, SIGNAL(error(QBluetoothServiceDiscoveryAgent::Error)), + this, SLOT(serviceScanError(QBluetoothServiceDiscoveryAgent::Error))); + discoveryAgent->setUuidFilter(QBluetoothUuid(serviceUuid)); + discoveryAgent->start(QBluetoothServiceDiscoveryAgent::FullDiscovery); + //! [Searching for the service] + setMessage(QStringLiteral("Starting server discovery. You are the right player")); + // m_role is set to 2 if it is a client + m_role = 2; + Q_EMIT roleChanged(); +} + +void PingPong::clientConnected() +{ + //! [Initiating server socket] + if (!m_serverInfo->hasPendingConnections()) { + setMessage("FAIL: expected pending server connection"); + return; + } + socket = m_serverInfo->nextPendingConnection(); + if (!socket) + return; + socket->setParent(this); + 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))); + //! [Initiating server socket] + setMessage(QStringLiteral("Client connected.")); + + QByteArray size; + size.setNum(m_boardWidth); + size.append(' '); + QByteArray size1; + size1.setNum(m_boardHeight); + size.append(size1); + size.append(" \n"); + socket->write(size.constData()); + +} + +void PingPong::clientDisconnected() +{ + setMessage(QStringLiteral("Client disconnected")); + m_timer->stop(); +} + +void PingPong::socketError(QBluetoothSocket::SocketError error) +{ + Q_UNUSED(error); + m_timer->stop(); +} + +void PingPong::serverError(QBluetoothServer::Error error) +{ + Q_UNUSED(error); + m_timer->stop(); +} + +void PingPong::done() +{ + qDebug() << "Service scan done"; + if (!m_serviceFound) + setMessage("PingPong service not found"); +} + +void PingPong::addService(const QBluetoothServiceInfo &service) +{ + setMessage("Service found. Setting parameters..."); + //! [Connecting the socket] + socket = new QBluetoothSocket(QBluetoothServiceInfo::L2capProtocol); + socket->connectToService(service); + + connect(socket, SIGNAL(readyRead()), this, SLOT(readSocket())); + connect(socket, SIGNAL(connected()), this, SLOT(serverConnected())); + connect(socket, SIGNAL(disconnected()), this, SLOT(serverDisconnected())); + //! [Connecting the socket] + m_serviceFound = true; +} + +void PingPong::serviceScanError(QBluetoothServiceDiscoveryAgent::Error error) +{ + setMessage(QStringLiteral("Scanning error") + error); +} + +bool PingPong::showDialog() const +{ + return m_showDialog; +} + +QString PingPong::message() const +{ + return m_message; +} + +void PingPong::serverConnected() +{ + setMessage("Server Connected"); + QByteArray size; + size.setNum(m_boardWidth); + size.append(' '); + QByteArray size1; + size1.setNum(m_boardHeight); + size.append(size1); + size.append(" \n"); + socket->write(size.constData()); +} + +void PingPong::serverDisconnected() +{ + setMessage("Server Disconnected"); + m_timer->stop(); +} + +void PingPong::readSocket() +{ + if (!socket) + return; + const char sep = ' '; + QByteArray line; + while (socket->canReadLine()) { + line = socket->readLine(); + //qDebug() << QString::fromUtf8(line.constData(), line.length()); + if (line.contains("result")) { + QList<QByteArray> result = line.split(sep); + if (result.size() > 2) { + QByteArray leftSide = result.at(1); + QByteArray rightSide = result.at(2); + m_resultLeft = leftSide.toInt(); + m_resultRight = rightSide.toInt(); + Q_EMIT resultChanged(); + checkResult(); + } + } + } + if ((m_proportionX == 0 || m_proportionY == 0)) { + QList<QByteArray> boardSize = line.split(sep); + if (boardSize.size() > 1) { + QByteArray boardWidth = boardSize.at(0); + QByteArray boardHeight = boardSize.at(1); + m_proportionX = m_boardWidth/boardWidth.toFloat(); + m_proportionY = m_boardHeight/boardHeight.toFloat(); + setMessage("Screen adjusted. Get ready!"); + QTimer::singleShot(3000, this, SLOT(startGame())); + } + } + else if (m_role == 1) { + QList<QByteArray> boardSize = line.split(sep); + if (boardSize.size() > 1) { + QByteArray rightBlockY = boardSize.at(0); + m_rightBlockY = m_proportionY * rightBlockY.toFloat(); + Q_EMIT rightBlockChanged(); + } + } + else if (m_role == 2) { + QList<QByteArray> boardSize = line.split(sep); + if (boardSize.size() > 2) { + QByteArray ballX = boardSize.at(0); + QByteArray ballY = boardSize.at(1); + QByteArray leftBlockY = boardSize.at(2); + m_ballX = m_proportionX * ballX.toFloat(); + m_ballY = m_proportionY * ballY.toFloat(); + m_leftBlockY = m_proportionY * leftBlockY.toFloat(); + Q_EMIT leftBlockChanged(); + Q_EMIT ballChanged(); + } + } +} + +void PingPong::setMessage(const QString &message) +{ + m_showDialog = true; + m_message = message; + Q_EMIT showDialogChanged(); +} + +int PingPong::role() const +{ + return m_role; +} + +int PingPong::leftResult() const +{ + return m_resultLeft; +} + +int PingPong::rightResult() const +{ + return m_resultRight; +} + +float PingPong::ballX() const +{ + return m_ballX; +} + +float PingPong::ballY() const +{ + return m_ballY; +} + + +float PingPong::leftBlockY() const +{ + return m_leftBlockY; +} + +float PingPong::rightBlockY() const +{ + return m_rightBlockY; +} diff --git a/examples/bluetooth/pingpong/pingpong.h b/examples/bluetooth/pingpong/pingpong.h new file mode 100644 index 00000000..17fe176b --- /dev/null +++ b/examples/bluetooth/pingpong/pingpong.h @@ -0,0 +1,139 @@ +/*************************************************************************** +** +** Copyright (C) 2014 BlackBerry Limited. All rights reserved. +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the QtBluetooth module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PINGPONG_H +#define PINGPONG_H + +#include <QTimer> +#include <QObject> +#include <qbluetoothserver.h> +#include <qbluetoothserviceinfo.h> +#include <qbluetoothlocaldevice.h> +#include <qbluetoothservicediscoveryagent.h> + +static const QString serviceUuid(QStringLiteral("e8e10f95-1a70-4b27-9ccf-02010264e9c9")); + +class PingPong: public QObject +{ + Q_OBJECT + Q_PROPERTY(float ballX READ ballX NOTIFY ballChanged) + Q_PROPERTY(float ballY READ ballY NOTIFY ballChanged) + Q_PROPERTY(float leftBlockY READ leftBlockY NOTIFY leftBlockChanged) + Q_PROPERTY(float rightBlockY READ rightBlockY NOTIFY rightBlockChanged) + Q_PROPERTY(bool showDialog READ showDialog NOTIFY showDialogChanged) + Q_PROPERTY(QString message READ message NOTIFY showDialogChanged) + Q_PROPERTY(int role READ role NOTIFY roleChanged) + Q_PROPERTY(int leftResult READ leftResult NOTIFY resultChanged) + Q_PROPERTY(int rightResult READ rightResult NOTIFY resultChanged) +public: + PingPong(); + ~PingPong(); + float ballX() const; + float ballY() const; + float leftBlockY() const; + float rightBlockY() const; + void checkBoundaries(); + void updateDirection(); + bool showDialog() const; + QString message() const; + void setMessage(const QString &message); + int role() const; + int leftResult() const; + int rightResult() const; + void checkResult(); + +public slots: + void startGame(); + void update(); + void setSize(const float &x, const float &y); + void updateBall(const float &bX, const float &bY); + void updateLeftBlock(const float &lY); + void updateRightBlock(const float &rY); + void startServer(); + void startClient(); + void clientConnected(); + void clientDisconnected(); + void serverConnected(); + void serverDisconnected(); + void socketError(QBluetoothSocket::SocketError); + void serverError(QBluetoothServer::Error); + void serviceScanError(QBluetoothServiceDiscoveryAgent::Error); + void done(); + void addService(const QBluetoothServiceInfo &); + void readSocket(); + +Q_SIGNALS: + void ballChanged(); + void leftBlockChanged(); + void rightBlockChanged(); + void showDialogChanged(); + void roleChanged(); + void resultChanged(); + +private: + QBluetoothServer *m_serverInfo; + QBluetoothServiceInfo m_serviceInfo; + QBluetoothSocket *socket; + QBluetoothServiceDiscoveryAgent *discoveryAgent; + + float m_ballX; + float m_ballY; + float m_ballPreviousX; + float m_ballPreviousY; + float m_leftBlockY; + float m_rightBlockY; + QTimer *m_timer; + float m_boardWidth; + float m_boardHeight; + float m_direction; + float m_targetX; + float m_targetY; + int interval; + int m_resultLeft; + int m_resultRight; + bool m_showDialog; + QString m_message; + int m_role; + float m_proportionX; + float m_proportionY; + bool m_serviceFound; +}; + +#endif // PINGPONG_H diff --git a/examples/bluetooth/pingpong/pingpong.pro b/examples/bluetooth/pingpong/pingpong.pro new file mode 100644 index 00000000..07675f27 --- /dev/null +++ b/examples/bluetooth/pingpong/pingpong.pro @@ -0,0 +1,19 @@ +TEMPLATE = app +TARGET = pingpong + +QT += quick bluetooth + +# Input +SOURCES += main.cpp \ + pingpong.cpp + +OTHER_FILES += assets/*.qml + +RESOURCES += \ + resource.qrc + +HEADERS += \ + pingpong.h + +target.path = $$[QT_INSTALL_EXAMPLES]/bluetooth/pingpong +INSTALLS += target diff --git a/examples/bluetooth/pingpong/resource.qrc b/examples/bluetooth/pingpong/resource.qrc new file mode 100644 index 00000000..1475a7f3 --- /dev/null +++ b/examples/bluetooth/pingpong/resource.qrc @@ -0,0 +1,8 @@ +<RCC> + <qresource prefix="/"> + <file>assets/main.qml</file> + <file>assets/Board.qml</file> + <file>assets/Dialog.qml</file> + <file>assets/Menu.qml</file> + </qresource> +</RCC> diff --git a/src/bluetooth/doc/src/bluetooth-index.qdoc b/src/bluetooth/doc/src/bluetooth-index.qdoc index 583828d9..078596cd 100644 --- a/src/bluetooth/doc/src/bluetooth-index.qdoc +++ b/src/bluetooth/doc/src/bluetooth-index.qdoc @@ -76,6 +76,7 @@ import statement in your \c .qml file: \list \li \l {scanner}{QML Bluetooth Scanner} \li \l {picturetransfer}{QML Bluetooth Picture Push} + \li \l {pingpong}{QML Bluetooth PingPong} \endlist \li C++ \list diff --git a/src/bluetooth/doc/src/examples.qdoc b/src/bluetooth/doc/src/examples.qdoc index d6b73ae8..5ddb1ea3 100644 --- a/src/bluetooth/doc/src/examples.qdoc +++ b/src/bluetooth/doc/src/examples.qdoc @@ -54,6 +54,9 @@ \row \li \l{btscanner}{Bluetooth Scanner} \li Scan for Bluetooth devices. + \row + \li \l{pingpong}{QML Bluetooth PingPong} + \li The ping pong game demonstrates Bluetooth socket communication between two devices. \endtable \section2 QML Examples |