summaryrefslogtreecommitdiffstats
path: root/chicken-wranglers/src
diff options
context:
space:
mode:
authorTomaz Noleto <tomaz.noleto@openbossa.org>2011-10-25 17:13:31 +0200
committerTomaz Noleto <tomaz.noleto@openbossa.org>2011-10-25 17:14:32 +0200
commit5c722451a2bb6702c628a1b7c1468160fc01734a (patch)
treebf5487fc0f82a0de0d6b7ed38088538acfc1389a /chicken-wranglers/src
parentd7d612ff07253b1cc1ffa4be489a8d90ec750af6 (diff)
chicken-wranglers: Initial commit
Signed-off-by: Tomaz Noleto <tomaz.noleto@openbossa.org>
Diffstat (limited to 'chicken-wranglers/src')
-rw-r--r--chicken-wranglers/src/ai/ai.pri9
-rw-r--r--chicken-wranglers/src/ai/graph.cpp129
-rw-r--r--chicken-wranglers/src/ai/graph.h114
-rw-r--r--chicken-wranglers/src/ai/matchai.cpp408
-rw-r--r--chicken-wranglers/src/ai/matchai.h78
-rw-r--r--chicken-wranglers/src/control/control.cpp79
-rw-r--r--chicken-wranglers/src/control/control.h82
-rw-r--r--chicken-wranglers/src/control/control.pri16
-rw-r--r--chicken-wranglers/src/control/sensormovement.cpp192
-rw-r--r--chicken-wranglers/src/control/sensormovement.h148
-rw-r--r--chicken-wranglers/src/controllers/chickencontroller.cpp116
-rw-r--r--chicken-wranglers/src/controllers/chickencontroller.h89
-rw-r--r--chicken-wranglers/src/controllers/controllers.pri13
-rw-r--r--chicken-wranglers/src/controllers/matchcontroller.cpp246
-rw-r--r--chicken-wranglers/src/controllers/matchcontroller.h132
-rw-r--r--chicken-wranglers/src/controllers/playercontroller.cpp127
-rw-r--r--chicken-wranglers/src/controllers/playercontroller.h93
-rw-r--r--chicken-wranglers/src/main/argumentparser.cpp118
-rw-r--r--chicken-wranglers/src/main/argumentparser.h73
-rw-r--r--chicken-wranglers/src/main/game.cpp206
-rw-r--r--chicken-wranglers/src/main/game.h114
-rw-r--r--chicken-wranglers/src/main/gameclient.cpp423
-rw-r--r--chicken-wranglers/src/main/gameclient.h156
-rw-r--r--chicken-wranglers/src/main/gamehost.cpp199
-rw-r--r--chicken-wranglers/src/main/gamehost.h123
-rw-r--r--chicken-wranglers/src/main/main.cpp93
-rw-r--r--chicken-wranglers/src/main/main.pri18
-rw-r--r--chicken-wranglers/src/main/settings.cpp284
-rw-r--r--chicken-wranglers/src/main/settings.h108
-rw-r--r--chicken-wranglers/src/models/bluetoothdevice.cpp110
-rw-r--r--chicken-wranglers/src/models/bluetoothdevice.h90
-rw-r--r--chicken-wranglers/src/models/charactermodel.cpp217
-rw-r--r--chicken-wranglers/src/models/charactermodel.h121
-rw-r--r--chicken-wranglers/src/models/connectivitylistmodel.cpp151
-rw-r--r--chicken-wranglers/src/models/connectivitylistmodel.h86
-rw-r--r--chicken-wranglers/src/models/models.pri15
-rw-r--r--chicken-wranglers/src/models/playermodel.cpp466
-rw-r--r--chicken-wranglers/src/models/playermodel.h175
-rw-r--r--chicken-wranglers/src/network/bluetoothconnection.cpp119
-rw-r--r--chicken-wranglers/src/network/bluetoothconnection.h89
-rw-r--r--chicken-wranglers/src/network/bluetoothhandler.cpp198
-rw-r--r--chicken-wranglers/src/network/bluetoothhandler.h100
-rw-r--r--chicken-wranglers/src/network/bthandler.cpp88
-rw-r--r--chicken-wranglers/src/network/bthandler.h86
-rw-r--r--chicken-wranglers/src/network/connectionfactory.cpp70
-rw-r--r--chicken-wranglers/src/network/connectionfactory.h65
-rw-r--r--chicken-wranglers/src/network/lanhandler.cpp133
-rw-r--r--chicken-wranglers/src/network/lanhandler.h82
-rw-r--r--chicken-wranglers/src/network/network.h67
-rw-r--r--chicken-wranglers/src/network/network.pri37
-rw-r--r--chicken-wranglers/src/network/networkclient.cpp196
-rw-r--r--chicken-wranglers/src/network/networkclient.h107
-rw-r--r--chicken-wranglers/src/network/networkconnection.cpp144
-rw-r--r--chicken-wranglers/src/network/networkconnection.h85
-rw-r--r--chicken-wranglers/src/network/networkmessage.cpp118
-rw-r--r--chicken-wranglers/src/network/networkmessage.h115
-rw-r--r--chicken-wranglers/src/network/networkserver.cpp255
-rw-r--r--chicken-wranglers/src/network/networkserver.h120
-rw-r--r--chicken-wranglers/src/network/tcpconnection.cpp114
-rw-r--r--chicken-wranglers/src/network/tcpconnection.h87
-rw-r--r--chicken-wranglers/src/network/udphandler.cpp169
-rw-r--r--chicken-wranglers/src/network/udphandler.h90
-rw-r--r--chicken-wranglers/src/qml/Being.qml150
-rw-r--r--chicken-wranglers/src/qml/Character.qml121
-rw-r--r--chicken-wranglers/src/qml/CharacterSelectionView.qml235
-rw-r--r--chicken-wranglers/src/qml/Chicken.qml159
-rw-r--r--chicken-wranglers/src/qml/ClientView.qml121
-rw-r--r--chicken-wranglers/src/qml/HenCoop.qml149
-rw-r--r--chicken-wranglers/src/qml/HostView.qml94
-rw-r--r--chicken-wranglers/src/qml/Laser.qml147
-rw-r--r--chicken-wranglers/src/qml/MatchView.qml345
-rw-r--r--chicken-wranglers/src/qml/PlayerControlView.qml147
-rw-r--r--chicken-wranglers/src/qml/PlayerReadyView.qml115
-rw-r--r--chicken-wranglers/src/qml/Score.qml128
-rw-r--r--chicken-wranglers/src/qml/ScoreBox.qml81
-rw-r--r--chicken-wranglers/src/qml/Splash.qml79
-rw-r--r--chicken-wranglers/src/qml/StartView.qml246
-rw-r--r--chicken-wranglers/src/qml/WaitingRoomView.qml288
-rw-r--r--chicken-wranglers/src/qml/client.js72
-rw-r--r--chicken-wranglers/src/qml/common.js26
-rw-r--r--chicken-wranglers/src/qml/host.js46
-rw-r--r--chicken-wranglers/src/qml/main.qml126
-rw-r--r--chicken-wranglers/src/qml/match.js310
-rw-r--r--chicken-wranglers/src/qml/qml.qrc43
-rw-r--r--chicken-wranglers/src/qml/widgets/BaseDialog.qml112
-rw-r--r--chicken-wranglers/src/qml/widgets/Button.qml133
-rw-r--r--chicken-wranglers/src/qml/widgets/ConfirmationDialog.qml106
-rw-r--r--chicken-wranglers/src/qml/widgets/ConnectivityDialog.qml185
-rw-r--r--chicken-wranglers/src/qml/widgets/ConnectivityListModel.qml82
-rw-r--r--chicken-wranglers/src/qml/widgets/ConnectivityListView.qml138
-rw-r--r--chicken-wranglers/src/qml/widgets/Countdown.qml107
-rw-r--r--chicken-wranglers/src/qml/widgets/Feather.qml126
-rw-r--r--chicken-wranglers/src/qml/widgets/FeatherFall.qml74
-rw-r--r--chicken-wranglers/src/qml/widgets/ImageButton.qml93
-rw-r--r--chicken-wranglers/src/qml/widgets/Loading.qml138
-rw-r--r--chicken-wranglers/src/qml/widgets/MessageDialog.qml85
-rw-r--r--chicken-wranglers/src/qml/widgets/OptionSlider.qml131
-rw-r--r--chicken-wranglers/src/qml/widgets/Screen.qml86
-rw-r--r--chicken-wranglers/src/qml/widgets/Scrollbar.qml87
-rw-r--r--chicken-wranglers/src/qml/widgets/ToggleButton.qml67
-rw-r--r--chicken-wranglers/src/qml/widgets/featherfall.js66
-rw-r--r--chicken-wranglers/src/sound/sound.cpp62
-rw-r--r--chicken-wranglers/src/sound/sound.h67
-rw-r--r--chicken-wranglers/src/sound/sound.pri9
-rw-r--r--chicken-wranglers/src/sound/sound_linux.cpp105
-rw-r--r--chicken-wranglers/src/sound/sound_linux.h70
-rw-r--r--chicken-wranglers/src/sound/sound_linux.pri9
-rw-r--r--chicken-wranglers/src/sound/soundmanager.cpp128
-rw-r--r--chicken-wranglers/src/sound/soundmanager.h76
-rw-r--r--chicken-wranglers/src/utils/global.cpp135
-rw-r--r--chicken-wranglers/src/utils/global.h102
-rw-r--r--chicken-wranglers/src/utils/utils.pri9
112 files changed, 13967 insertions, 0 deletions
diff --git a/chicken-wranglers/src/ai/ai.pri b/chicken-wranglers/src/ai/ai.pri
new file mode 100644
index 0000000..8f9dd78
--- /dev/null
+++ b/chicken-wranglers/src/ai/ai.pri
@@ -0,0 +1,9 @@
+PATH = $$PWD
+
+HEADERS += \
+ $$PATH/matchai.h \
+ $$PATH/graph.h
+
+SOURCES += \
+ $$PATH/matchai.cpp \
+ $$PATH/graph.cpp
diff --git a/chicken-wranglers/src/ai/graph.cpp b/chicken-wranglers/src/ai/graph.cpp
new file mode 100644
index 0000000..34c61c8
--- /dev/null
+++ b/chicken-wranglers/src/ai/graph.cpp
@@ -0,0 +1,129 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+#include "graph.h"
+
+Node::Node(QObject *parent)
+ : QObject(parent), data(Node::Empty), rank(0),
+ chickenCount(0), pos(0, 0), direction(Node::Stop)
+{
+ neighbor[Node::Stop] = this;
+ neighbor[Node::Up] = this;
+ neighbor[Node::Down] = this;
+ neighbor[Node::Right] = this;
+ neighbor[Node::Left] = this;
+}
+
+Global::Direction Node::neighborDirection(Node::Neighbor neighbor)
+{
+ switch (neighbor) {
+ case Node::Up:
+ return Global::DirectionUp;
+ case Node::Down:
+ return Global::DirectionDown;
+ case Node::Right:
+ return Global::DirectionRight;
+ case Node::Left:
+ return Global::DirectionLeft;
+ default:
+ return Global::DirectionStop;
+ }
+}
+
+Node::Neighbor Node::directionNeighbor(Global::Direction direction)
+{
+ switch (direction) {
+ case Global::DirectionUp:
+ return Node::Up;
+ case Global::DirectionDown:
+ return Node::Down;
+ case Global::DirectionRight:
+ return Node::Right;
+ case Global::DirectionLeft:
+ return Node::Left;
+ default:
+ return Node::Stop;
+ }
+}
+
+Graph::Graph(QSize size, QObject *parent)
+ : QObject(parent), m_size(size)
+{
+ initMatrix();
+}
+
+Node *Graph::node(QPoint pos)
+{
+ if (pos.y() < m_size.height() && pos.x() < m_size.width()
+ && pos.y() >= 0 && pos.x() >= 0) {
+ return m_matrix[pos.y()][pos.x()];
+ }
+
+ return 0;
+}
+
+void Graph::initMatrix()
+{
+ if (!m_size.height() || !m_size.width())
+ return;
+
+ // FIXME: Better way to alloc the matrix
+ for (int row = 0; row < m_size.height(); row++)
+ for (int column = 0; column < m_size.width(); column++)
+ m_matrix[row][column] = new Node(this);
+
+ for (int row = 0; row < m_size.height(); row++) {
+ for (int column = 0; column < m_size.width(); column++) {
+ m_matrix[row][column]->pos = QPoint(column, row);
+
+ if (row > 0)
+ m_matrix[row][column]->neighbor[Node::Up] = m_matrix[row - 1][column];
+ if (column > 0)
+ m_matrix[row][column]->neighbor[Node::Left] = m_matrix[row][column - 1];
+ if (row < m_size.height() - 1)
+ m_matrix[row][column]->neighbor[Node::Down] = m_matrix[row + 1][column];
+ if (column < m_size.width() - 1)
+ m_matrix[row][column]->neighbor[Node::Right] = m_matrix[row][column + 1];
+ }
+
+ }
+}
diff --git a/chicken-wranglers/src/ai/graph.h b/chicken-wranglers/src/ai/graph.h
new file mode 100644
index 0000000..322b79f
--- /dev/null
+++ b/chicken-wranglers/src/ai/graph.h
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+#ifndef GRAPH_H
+#define GRAPH_H
+
+#include <QtCore/QList>
+#include <QtCore/QObject>
+#include <QtCore/QPair>
+#include <QtCore/QPoint>
+#include <QtCore/QSize>
+
+#include "global.h"
+
+class Node : public QObject
+{
+ Q_OBJECT
+
+public:
+ enum Neighbor {
+ Right,
+ Left,
+ Up,
+ Down,
+ Stop,
+ MAX_NEIGHBOR
+ };
+
+ enum Data {
+ Empty,
+ Chicken,
+ Player,
+ Hencoop
+ };
+
+ explicit Node(QObject *parent = 0);
+
+ bool isEmpty() { return data == Node::Empty; }
+ bool isChicken() { return data == Node::Chicken; }
+ bool isPlayer() { return data == Node::Player; }
+ bool isHencoop() { return data == Node::Hencoop; }
+ bool isScape() { return !isPlayer() && !isHencoop(); }
+ bool isSafe() { return !rank; }
+ void emitChickenEntered() { emit chickenEntered(chickenCount); }
+
+ static Global::Direction neighborDirection(Node::Neighbor);
+ static Node::Neighbor directionNeighbor(Global::Direction);
+
+ Node *neighbor[MAX_NEIGHBOR];
+ Data data;
+ int rank;
+ int chickenCount;
+ QPoint pos;
+ Node::Neighbor direction;
+
+signals:
+ void chickenEntered(int numChickens);
+};
+
+class Graph : public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit Graph(QSize size, QObject *parent = 0);
+ Node *node(QPoint pos);
+
+private:
+ void initMatrix();
+
+ QSize m_size;
+ Node *m_matrix[20][20];
+};
+
+#endif
diff --git a/chicken-wranglers/src/ai/matchai.cpp b/chicken-wranglers/src/ai/matchai.cpp
new file mode 100644
index 0000000..1870655
--- /dev/null
+++ b/chicken-wranglers/src/ai/matchai.cpp
@@ -0,0 +1,408 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+#include "global.h"
+
+#include "matchai.h"
+
+MatchAI::MatchAI(QSize matchCanvasSize)
+{
+ m_graph = new Graph(matchCanvasSize);
+}
+
+MatchAI::~MatchAI()
+{
+ m_graph->deleteLater();
+}
+
+bool MatchAI::addChicken(QPoint position)
+{
+ Node *chickenNode = m_graph->node(position);
+
+ if (!chickenNode || !chickenNode->isEmpty())
+ return false;
+
+ chickenNode->data = Node::Chicken;
+ chickenNode->chickenCount = 1;
+
+ return true;
+}
+
+Node *MatchAI::addPlayer(QPoint position)
+{
+ Node *playerNode = m_graph->node(position);
+
+ if (!playerNode || !playerNode->isEmpty())
+ return 0;
+
+ Node *hencoop = addHencoop(playerNode);
+
+ if (hencoop) {
+ playerNode->data = Node::Player;
+ doUnSafe(playerNode);
+ }
+
+ return hencoop;
+}
+
+bool MatchAI::toggleLaser(QPoint position, Global::LaserDirection direction)
+{
+ Node *node = m_graph->node(position);
+ Node *neighbor;
+
+ if (!node)
+ return false;
+
+ switch (direction) {
+
+ case Global::LaserUp:
+ neighbor = m_graph->node(position + QPoint(0, -1));
+ if (neighbor) {
+ if (node->neighbor[Node::Up] != neighbor) {
+ // Turn off laser
+ node->neighbor[Node::Up] = neighbor;
+ neighbor->neighbor[Node::Down] = node;
+ return false;
+ } else {
+ // Turn on laser
+ node->neighbor[Node::Up] = node;
+ neighbor->neighbor[Node::Down] = neighbor;
+ return true;
+ }
+ }
+ break;
+
+ case Global::LaserDown:
+ neighbor = m_graph->node(position + QPoint(0, 1));
+ if (neighbor) {
+ if (node->neighbor[Node::Down] != neighbor) {
+ // Turn off laser
+ node->neighbor[Node::Down] = neighbor;
+ neighbor->neighbor[Node::Up] = node;
+ return false;
+ } else {
+ // Turn on laser
+ node->neighbor[Node::Down] = node;
+ neighbor->neighbor[Node::Up] = neighbor;
+ return true;
+ }
+ }
+ break;
+
+ case Global::LaserRight:
+ neighbor = m_graph->node(position + QPoint(1, 0));
+ if (neighbor) {
+ if (node->neighbor[Node::Right] != neighbor) {
+ // Turn off laser
+ node->neighbor[Node::Right] = neighbor;
+ neighbor->neighbor[Node::Left] = node;
+ return false;
+ } else {
+ // Turn on laser
+ node->neighbor[Node::Right] = node;
+ neighbor->neighbor[Node::Left] = neighbor;
+ return true;
+ }
+ }
+ break;
+
+ case Global::LaserLeft:
+ neighbor = m_graph->node(position + QPoint(-1, 0));
+ if (neighbor) {
+ if (node->neighbor[Node::Left] != neighbor) {
+ // Turn off laser
+ node->neighbor[Node::Left] = neighbor;
+ neighbor->neighbor[Node::Right] = node;
+ return false;
+ } else {
+ // Turn on laser
+ node->neighbor[Node::Left] = node;
+ neighbor->neighbor[Node::Right] = neighbor;
+ return true;
+ }
+ }
+ break;
+
+ default:
+ return false;
+ }
+
+ return false;
+}
+
+QPair<QPoint, Global::Direction> MatchAI::moveChicken(QPoint position)
+{
+ Node *chickenNode = m_graph->node(position);
+
+ if (!chickenNode || !chickenNode->isChicken())
+ return QPair<QPoint, Global::Direction>(position, Global::DirectionStop);
+
+ QList<QPair<QPoint, Node::Neighbor> > nextPosList;
+ Node *neighbor;
+ if (chickenNode->isSafe() && chickenNode->chickenCount == 1) {
+ nextPosList.append(QPair<QPoint, Node::Neighbor>(position, Node::Stop));
+ nextPosList.append(QPair<QPoint, Node::Neighbor>(position, Node::Stop));
+ nextPosList.append(QPair<QPoint, Node::Neighbor>(position, Node::Stop));
+ nextPosList.append(QPair<QPoint, Node::Neighbor>(position, Node::Stop));
+ nextPosList.append(QPair<QPoint, Node::Neighbor>(position, Node::Stop));
+ nextPosList.append(QPair<QPoint, Node::Neighbor>(position, Node::Stop));
+ nextPosList.append(QPair<QPoint, Node::Neighbor>(position, Node::Stop));
+ nextPosList.append(QPair<QPoint, Node::Neighbor>(position, Node::Stop));
+ }
+
+ neighbor = chickenNode->neighbor[Node::Up];
+ if (!neighbor->isPlayer() && neighbor->isSafe() && chickenNode != neighbor) {
+ nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Up));
+ if (chickenNode->neighbor[Node::Down]->isPlayer()) {
+ nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Up));
+ nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Up));
+ nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Up));
+ nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Up));
+ nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Up));
+ nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Up));
+ nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Up));
+ nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Up));
+ }
+ }
+
+ neighbor = chickenNode->neighbor[Node::Down];
+ if (!neighbor->isPlayer() && neighbor->isSafe() && chickenNode != neighbor) {
+ nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Down));
+ if (chickenNode->neighbor[Node::Up]->isPlayer()) {
+ nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Down));
+ nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Down));
+ nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Down));
+ nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Down));
+ nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Down));
+ nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Down));
+ nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Down));
+ nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Down));
+ }
+ }
+
+ neighbor = chickenNode->neighbor[Node::Right];
+ if (!neighbor->isPlayer() && neighbor->isSafe() && chickenNode != neighbor) {
+ nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Right));
+ if (chickenNode->neighbor[Node::Left]->isPlayer()) {
+ nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Right));
+ nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Right));
+ nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Right));
+ nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Right));
+ nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Right));
+ nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Right));
+ nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Right));
+ nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Right));
+ }
+ }
+
+ neighbor = chickenNode->neighbor[Node::Left];
+ if (!neighbor->isPlayer() && neighbor->isSafe() && chickenNode != neighbor) {
+ nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Left));
+ if (chickenNode->neighbor[Node::Right]->isPlayer()) {
+ nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Left));
+ nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Left));
+ nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Left));
+ nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Left));
+ nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Left));
+ nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Left));
+ nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Left));
+ nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Left));
+ }
+ }
+
+ if (nextPosList.isEmpty()) {
+ neighbor = chickenNode->neighbor[Node::Up];
+
+ if (neighbor->isScape() && neighbor->rank < chickenNode->rank && chickenNode != neighbor)
+ nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Up));
+
+ neighbor = chickenNode->neighbor[Node::Down];
+ if (neighbor->isScape() && neighbor->rank < chickenNode->rank && chickenNode != neighbor)
+ nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Down));
+
+ neighbor = chickenNode->neighbor[Node::Right];
+ if (neighbor->isScape() && neighbor->rank < chickenNode->rank && chickenNode != neighbor)
+ nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Right));
+
+ neighbor = chickenNode->neighbor[Node::Left];
+ if (neighbor->isScape() && neighbor->rank < chickenNode->rank && chickenNode != neighbor)
+ nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Left));
+ }
+
+ if (nextPosList.isEmpty()) {
+ neighbor = chickenNode->neighbor[Node::Up];
+
+ if (!neighbor->isPlayer() && neighbor->rank < chickenNode->rank && chickenNode != neighbor)
+ nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Up));
+
+ neighbor = chickenNode->neighbor[Node::Down];
+ if (!neighbor->isPlayer() && neighbor->rank < chickenNode->rank && chickenNode != neighbor)
+ nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Down));
+
+ neighbor = chickenNode->neighbor[Node::Right];
+ if (!neighbor->isPlayer() && neighbor->rank < chickenNode->rank && chickenNode != neighbor)
+ nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Right));
+
+ neighbor = chickenNode->neighbor[Node::Left];
+ if (!neighbor->isPlayer() && neighbor->rank < chickenNode->rank && chickenNode != neighbor)
+ nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Left));
+ }
+
+ if (nextPosList.isEmpty())
+ return QPair<QPoint, Global::Direction>(position, Global::DirectionStop);
+
+ QPair<QPoint, Node::Neighbor> nextPos = nextPosList.at(qrand() % nextPosList.size());
+ neighbor = chickenNode->neighbor[nextPos.second];
+ if (neighbor != chickenNode) {
+ chickenNode->chickenCount -= 1;
+ if (!chickenNode->chickenCount)
+ chickenNode->data = Node::Empty;
+
+ neighbor->chickenCount += 1;
+
+ if (neighbor->isHencoop())
+ neighbor->emitChickenEntered();
+ else
+ neighbor->data = Node::Chicken;
+ }
+
+ return QPair<QPoint, Global::Direction>(nextPos.first,
+ Node::neighborDirection(nextPos.second));
+}
+
+QPoint MatchAI::movePlayer(QPoint position, Global::Direction direction)
+{
+ Node *playerNode = m_graph->node(position);
+
+ if (!playerNode || playerNode->data != Node::Player)
+ return position;
+
+ Node *neighbor = playerNode->neighbor[Node::directionNeighbor(direction)];
+ if (neighbor->isEmpty()) {
+ playerNode->data = Node::Empty;
+ neighbor->data = Node::Player;
+
+ doSafe(playerNode);
+
+ playerNode->direction = Node::Stop;
+ neighbor->direction = Node::directionNeighbor(direction);
+
+ doUnSafe(neighbor);
+
+ return neighbor->pos;
+ } else {
+ doSafe(playerNode);
+ playerNode->direction = Node::directionNeighbor(direction);
+ doUnSafe(playerNode);
+ }
+
+ return position;
+}
+
+bool MatchAI::isChickenSafe(QPoint position)
+{
+ Node *chickenNode = m_graph->node(position);
+
+ if (!chickenNode || chickenNode->data != Node::Chicken)
+ return false;
+
+ return chickenNode->isSafe();
+}
+
+Node *MatchAI::addHencoop(Node *node)
+{
+ if (node->neighbor[Node::Right] == node) {
+ node->rank = 1;
+ node->neighbor[Node::Right] = new Node(m_graph);
+ node->neighbor[Node::Right]->data = Node::Hencoop;
+ node->neighbor[Node::Right]->rank = 4;
+ node->neighbor[Node::Right]->pos = node->pos + QPoint(1, 0);
+ return node->neighbor[Node::Right];
+ }
+
+ if (node->neighbor[Node::Left] == node) {
+ node->rank = 1;
+ node->neighbor[Node::Left] = new Node(m_graph);
+ node->neighbor[Node::Left]->data = Node::Hencoop;
+ node->neighbor[Node::Left]->rank = 4;
+ node->neighbor[Node::Left]->pos = node->pos + QPoint(-1, 0);
+ return node->neighbor[Node::Left];
+ }
+
+ return 0;
+}
+
+void MatchAI::doUnSafe(QPoint position)
+{
+ Node *playerNode = m_graph->node(position);
+
+ if (!playerNode || !playerNode->isPlayer())
+ return;
+ doUnSafe(playerNode);
+}
+
+void MatchAI::doSafe(QPoint position)
+{
+ Node *playerNode = m_graph->node(position);
+
+ if (!playerNode || !playerNode->isPlayer())
+ return;
+ doSafe(playerNode);
+}
+
+void MatchAI::doUnSafe(Node *node)
+{
+ node->neighbor[Node::Up]->rank += 2;
+ node->neighbor[Node::Down]->rank += 2;
+ node->neighbor[Node::Right]->rank += 2;
+ node->neighbor[Node::Left]->rank += 2;
+ node->neighbor[node->direction]->rank += 4;
+}
+
+void MatchAI::doSafe(Node *node)
+{
+ node->neighbor[Node::Up]->rank -= 2;
+ node->neighbor[Node::Down]->rank -= 2;
+ node->neighbor[Node::Right]->rank -= 2;
+ node->neighbor[Node::Left]->rank -= 2;
+ node->neighbor[node->direction]->rank -= 4;
+}
diff --git a/chicken-wranglers/src/ai/matchai.h b/chicken-wranglers/src/ai/matchai.h
new file mode 100644
index 0000000..79832fe
--- /dev/null
+++ b/chicken-wranglers/src/ai/matchai.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+#ifndef GLOBALAI_H
+#define GLOBALAI_H
+
+#include <QtCore/QPair>
+#include <QtCore/QPoint>
+
+#include "global.h"
+#include "graph.h"
+
+class MatchAI
+{
+public:
+ MatchAI(QSize);
+ ~MatchAI();
+
+ bool addChicken(QPoint position);
+ QPair<QPoint, Global::Direction> moveChicken(QPoint position);
+ bool isChickenSafe(QPoint position);
+
+ Node *addPlayer(QPoint position);
+ QPoint movePlayer(QPoint position, Global::Direction direction);
+
+ bool toggleLaser(QPoint position, Global::LaserDirection direction);
+
+ void doUnSafe(QPoint position);
+ void doSafe(QPoint position);
+
+private:
+ Node *addHencoop(Node *node);
+ void doUnSafe(Node *node);
+ void doSafe(Node *node);
+
+ Graph *m_graph;
+};
+
+#endif
diff --git a/chicken-wranglers/src/control/control.cpp b/chicken-wranglers/src/control/control.cpp
new file mode 100644
index 0000000..3728bc0
--- /dev/null
+++ b/chicken-wranglers/src/control/control.cpp
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+#include "sensormovement.h"
+
+#include "control.h"
+
+Control::Control(QObject *parent)
+ : QObject(parent)
+{
+ m_sensorMovement = new SensorMovement(this);
+}
+
+void Control::start()
+{
+ connect(m_sensorMovement, SIGNAL(directionChanged(Global::Direction)),
+ this, SLOT(onSensorMovementDirectionChanged(Global::Direction)));
+}
+
+void Control::stop()
+{
+ disconnect(m_sensorMovement, SIGNAL(directionChanged(Global::Direction)),
+ this, SLOT(onSensorMovementDirectionChanged(Global::Direction)));
+}
+
+void Control::onSensorMovementDirectionChanged(Global::Direction direction)
+{
+ setDirection(direction);
+}
+
+void Control::setDirection(Global::Direction direction)
+{
+ if (m_direction == direction)
+ return;
+
+ m_direction = direction;
+
+ emit directionChanged(m_direction);
+ emit directionChanged();
+}
diff --git a/chicken-wranglers/src/control/control.h b/chicken-wranglers/src/control/control.h
new file mode 100644
index 0000000..7f92f00
--- /dev/null
+++ b/chicken-wranglers/src/control/control.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+#ifndef CONTROL_H
+#define CONTROL_H
+
+#include <QtCore/QObject>
+
+#include "global.h"
+
+class SensorMovement;
+
+class Control : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QString directionString READ directionString NOTIFY directionChanged)
+
+public:
+ Control(QObject *parent = 0);
+
+ Global::Direction direction() const { return m_direction; }
+ void setDirection(Global::Direction direction);
+ QString directionString() const { return Global::directionString(m_direction); }
+
+ void start();
+ void stop();
+
+ SensorMovement *sensorMovement() const { return m_sensorMovement; }
+
+signals:
+ void directionChanged(Global::Direction direction);
+ void directionChanged();
+
+protected slots:
+ void onSensorMovementDirectionChanged(Global::Direction direction);
+
+private:
+ SensorMovement *m_sensorMovement;
+ Global::Direction m_direction;
+};
+
+#endif
diff --git a/chicken-wranglers/src/control/control.pri b/chicken-wranglers/src/control/control.pri
new file mode 100644
index 0000000..50f950d
--- /dev/null
+++ b/chicken-wranglers/src/control/control.pri
@@ -0,0 +1,16 @@
+maemo5 {
+ CONFIG += mobility12
+} else {
+ CONFIG += mobility
+}
+MOBILITY += sensors
+
+PATH = $$PWD
+
+HEADERS += \
+ $$PATH/control.h \
+ $$PATH/sensormovement.h
+
+SOURCES += \
+ $$PATH/control.cpp \
+ $$PATH/sensormovement.cpp
diff --git a/chicken-wranglers/src/control/sensormovement.cpp b/chicken-wranglers/src/control/sensormovement.cpp
new file mode 100644
index 0000000..4b032a1
--- /dev/null
+++ b/chicken-wranglers/src/control/sensormovement.cpp
@@ -0,0 +1,192 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+#include "sensormovement.h"
+
+SensorMovement::SensorMovement(QObject *parent)
+ : QObject(parent), m_direction(Global::DirectionStop), m_startX(0),
+ m_startY(0), m_minimumRotation(0),
+ m_threshold(0), m_directionTimeout(0), m_enabled(false)
+{
+ m_sensor.addFilter(this);
+ m_sensor.start();
+
+ setEnabled(true);
+
+ timer.setSingleShot(true);
+
+ connect(&timer, SIGNAL(timeout()), this, SLOT(notifyDirectionChanged()));
+}
+
+void SensorMovement::setEnabled(bool enabled)
+{
+ if (!m_sensor.isActive())
+ return;
+
+ m_enabled = enabled;
+
+ emit enabledChanged();
+}
+
+void SensorMovement::setMinimumRotation(qreal minimumRotation)
+{
+ m_minimumRotation = minimumRotation;
+
+ emit minimumRotationChanged();
+}
+
+void SensorMovement::setThreshold(qreal threshold)
+{
+ m_threshold = threshold;
+
+ emit thresholdChanged();
+}
+
+void SensorMovement::setDirectionTimeout(int directionTimeout)
+{
+ m_directionTimeout = directionTimeout;
+
+ emit directionTimeoutChanged();
+}
+
+void SensorMovement::resetStartPosition()
+{
+ QAccelerometerReading *reading = m_sensor.reading();
+
+ if (!reading)
+ return;
+
+ m_startX = reading->x();
+ m_startY = reading->y();
+}
+
+bool SensorMovement::filter(QAccelerometerReading *reading)
+{
+ if (!m_enabled)
+ return true;
+
+ Global::Direction nextDirection;
+ // XXX: Axis are inverted on N900, thanks to the fact that
+ // is a landscape device by definition.
+ if (Global::environment() == Global::Maemo)
+ nextDirection = calculateDirectionMaemo5(reading->x(), reading->y());
+ else
+ nextDirection = calculateDirection(reading->x(), reading->y());
+
+ if (nextDirection != m_direction) {
+ m_direction = nextDirection;
+
+ timer.stop();
+ timer.start(m_directionTimeout);
+ }
+
+ return true;
+}
+
+Global::Direction SensorMovement::calculateDirection(qreal x, qreal y)
+{
+ m_actualY = y - m_startY;
+ m_actualX = x - m_startX;
+
+ if (qAbs(m_actualX) > qAbs(m_actualY)) {
+ if (m_actualX > 0) {
+ if (m_actualX > m_minimumRotation + m_threshold)
+ return Global::DirectionDown;
+ else if (m_actualX < m_minimumRotation - m_threshold && m_actualX > m_threshold)
+ return Global::DirectionStop;
+ } else {
+ if (m_actualX < -m_minimumRotation - m_threshold)
+ return Global::DirectionUp;
+ else if (m_actualX > -m_minimumRotation + m_threshold && m_actualX < -m_threshold)
+ return Global::DirectionStop;
+ }
+ } else if (m_actualY > 0) {
+ if (m_actualY > m_minimumRotation + m_threshold)
+ return Global::DirectionRight;
+ else if (m_actualY < m_minimumRotation - m_threshold && m_actualY > m_threshold)
+ return Global::DirectionStop;
+ } else {
+ if (m_actualY < -m_minimumRotation - m_threshold)
+ return Global::DirectionLeft;
+ else if (m_actualY > -m_minimumRotation + m_threshold && m_actualY < -m_threshold)
+ return Global::DirectionStop;
+ }
+
+ return m_direction;
+}
+
+Global::Direction SensorMovement::calculateDirectionMaemo5(qreal x, qreal y)
+{
+ m_actualY = y - m_startY;
+ m_actualX = x - m_startX;
+
+ if (qAbs(m_actualX) > qAbs(m_actualY)) {
+ if (m_actualX > 0) {
+ if (m_actualX > m_minimumRotation + m_threshold)
+ return Global::DirectionLeft;
+ else if (m_actualX < m_minimumRotation - m_threshold && m_actualX > m_threshold)
+ return Global::DirectionStop;
+ } else {
+ if (m_actualX < -m_minimumRotation - m_threshold)
+ return Global::DirectionRight;
+ else if (m_actualX > -m_minimumRotation + m_threshold && m_actualX < -m_threshold)
+ return Global::DirectionStop;
+ }
+ } else if (m_actualY > 0) {
+ if (m_actualY > m_minimumRotation + m_threshold)
+ return Global::DirectionDown;
+ else if (m_actualY < m_minimumRotation - m_threshold && m_actualY > m_threshold)
+ return Global::DirectionStop;
+ } else {
+ if (m_actualY < -m_minimumRotation - m_threshold)
+ return Global::DirectionUp;
+ else if (m_actualY > -m_minimumRotation + m_threshold && m_actualY < -m_threshold)
+ return Global::DirectionStop;
+ }
+
+ return m_direction;
+}
+
+void SensorMovement::notifyDirectionChanged()
+{
+ emit directionChanged(m_direction);
+}
diff --git a/chicken-wranglers/src/control/sensormovement.h b/chicken-wranglers/src/control/sensormovement.h
new file mode 100644
index 0000000..d4e4b07
--- /dev/null
+++ b/chicken-wranglers/src/control/sensormovement.h
@@ -0,0 +1,148 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+#ifndef SENSORMOVEMENT_H
+#define SENSORMOVEMENT_H
+
+#include "global.h"
+
+#include <QtCore/QObject>
+#include <QtCore/QTimer>
+#include <QAccelerometer>
+
+QTM_USE_NAMESPACE
+
+class SensorMovement : public QObject, public QAccelerometerFilter
+{
+ Q_OBJECT
+
+public:
+ SensorMovement(QObject *parent = 0);
+
+ Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged)
+ Q_PROPERTY(qreal minimumRotation READ minimumRotation WRITE setMinimumRotation NOTIFY minimumRotationChanged)
+ Q_PROPERTY(qreal threshold READ threshold WRITE setThreshold NOTIFY thresholdChanged)
+ Q_PROPERTY(int directionTimeout READ directionTimeout WRITE setDirectionTimeout NOTIFY directionTimeoutChanged)
+
+ /**
+ * Defines if sensor is \a enabled, if it will forward direction change signals.
+ */
+ bool isEnabled() const { return m_enabled; }
+ void setEnabled(bool enabled);
+
+ /**
+ * Defines a minimum absolute rotation value required to
+ * detect a direction change in a axis. Note that DirectionStop
+ * is also considered a direction.
+ */
+ qreal minimumRotation() const { return m_minimumRotation; }
+ void setMinimumRotation(qreal minimumRotation);
+
+ /**
+ * Defines an angle interval as [-threshold, threshold], where the device
+ * rotation is not considered to be at any direction.
+ *
+ * For instance, if threshold was set to 5 and device is moving along
+ * vertical axis, it will not notify any direction change when the the
+ * rotation sensor value for that axis is between -5 and 5.
+ */
+ qreal threshold() const { return m_threshold; }
+ void setThreshold(qreal threshold);
+
+ /**
+ * Defines a time required for the device to stand in a given direction,
+ * before actually notifying a direction change.
+ *
+ * When devices is moved to a direction A and changed to a direction B in
+ * less than \a timeout miliseconds, it won't emit directionChange signal
+ * for direction A.
+ */
+ int directionTimeout() const { return m_directionTimeout; }
+ void setDirectionTimeout(int directionTimeout);
+
+ Global::Direction direction() const { return m_direction; }
+
+public slots:
+ /**
+ * Resets the device's start position.
+ *
+ * When this method is called, the current device position is read
+ * from sensor and all the direction calculations will be based on
+ * these offsets for both axis (x = 0 + m_startX, y = 0 + m_startY).
+ */
+ void resetStartPosition();
+
+signals:
+ void directionChanged(Global::Direction direction);
+ void minimumRotationChanged();
+ void thresholdChanged();
+ void directionTimeoutChanged();
+ void enabledChanged();
+
+protected:
+ bool filter(QAccelerometerReading *reading);
+
+private slots:
+ void notifyDirectionChanged();
+
+private:
+ Global::Direction calculateDirection(qreal x, qreal y);
+ Global::Direction calculateDirectionMaemo5(qreal x, qreal y);
+
+ QAccelerometer m_sensor;
+
+ Global::Direction m_direction;
+
+ qreal m_startX;
+ qreal m_startY;
+ qreal m_actualX;
+ qreal m_actualY;
+
+ qreal m_minimumRotation;
+ qreal m_threshold;
+ int m_directionTimeout;
+ bool m_enabled;
+
+ QTimer timer;
+};
+
+#endif
diff --git a/chicken-wranglers/src/controllers/chickencontroller.cpp b/chicken-wranglers/src/controllers/chickencontroller.cpp
new file mode 100644
index 0000000..e358ec7
--- /dev/null
+++ b/chicken-wranglers/src/controllers/chickencontroller.cpp
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+#include "chickencontroller.h"
+
+#include "matchai.h"
+
+#include <QtCore/QTime>
+
+ChickenController::ChickenController(QObject *parent)
+ : QObject(parent), m_isSafe(true), m_matchAI(0)
+{
+ initPosition();
+}
+
+ChickenController::ChickenController(MatchAI *matchAI, QObject *parent)
+ : QObject(parent), m_matchAI(matchAI)
+{
+ initPosition();
+}
+
+ChickenController::~ChickenController()
+{
+}
+
+void ChickenController::setPosition(const QPoint &position)
+{
+ if (position == m_position)
+ return;
+
+ m_position = position;
+
+ emit positionChanged();
+}
+
+void ChickenController::setDirection(const QString &direction)
+{
+ if (direction == m_direction)
+ return;
+
+ m_direction = direction;
+
+ emit directionChanged();
+}
+
+void ChickenController::setSafe(bool isSafe)
+{
+ if (m_isSafe == isSafe)
+ return;
+
+ m_isSafe = isSafe;
+
+ emit isSafeChanged();
+}
+
+void ChickenController::move()
+{
+ Q_ASSERT(m_matchAI);
+
+ setSafe(m_matchAI->isChickenSafe(m_position));
+
+ QPair<QPoint, Global::Direction> nextPos = m_matchAI->moveChicken(m_position);
+
+ setDirection(Global::directionString(nextPos.second));
+ setPosition(nextPos.first);
+}
+
+void ChickenController::initPosition()
+{
+ Q_ASSERT(m_matchAI);
+
+ qsrand(QTime::currentTime().msec());
+ do {
+ m_position = QPoint(qrand() % 10, qrand() % 10);
+ } while (!m_matchAI->addChicken(m_position));
+
+ m_direction = Global::directionString(Global::DirectionStop);
+}
diff --git a/chicken-wranglers/src/controllers/chickencontroller.h b/chicken-wranglers/src/controllers/chickencontroller.h
new file mode 100644
index 0000000..a12a393
--- /dev/null
+++ b/chicken-wranglers/src/controllers/chickencontroller.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+#ifndef CHICKENCONTROLLER_H
+#define CHICKENCONTROLLER_H
+
+#include <QtCore/QObject>
+#include <QtCore/QPoint>
+#include <QtCore/QString>
+
+class MatchAI;
+
+class ChickenController : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QPoint position READ position NOTIFY positionChanged)
+ Q_PROPERTY(QString direction READ direction NOTIFY directionChanged)
+ Q_PROPERTY(bool isSafe READ isSafe NOTIFY isSafeChanged)
+
+public:
+ explicit ChickenController(QObject *parent = 0); // don't use it
+ explicit ChickenController(MatchAI *matchAI, QObject *parent = 0);
+ ~ChickenController();
+
+ QPoint position() const { return m_position; }
+ void setPosition(const QPoint &position);
+
+ QString direction() const { return m_direction; }
+ void setDirection(const QString &direction);
+
+ bool isSafe() const { return m_isSafe; }
+
+ Q_INVOKABLE void move();
+
+signals:
+ void positionChanged();
+ void directionChanged();
+ void isSafeChanged();
+
+private:
+ void initPosition();
+ void setSafe(bool isSafe);
+
+ QPoint m_position;
+ QString m_direction;
+ bool m_isSafe;
+ MatchAI *m_matchAI;
+};
+
+#endif
diff --git a/chicken-wranglers/src/controllers/controllers.pri b/chicken-wranglers/src/controllers/controllers.pri
new file mode 100644
index 0000000..e92e330
--- /dev/null
+++ b/chicken-wranglers/src/controllers/controllers.pri
@@ -0,0 +1,13 @@
+QT += declarative
+
+PATH = $$PWD
+
+HEADERS += \
+ $$PATH/matchcontroller.h \
+ $$PATH/chickencontroller.h \
+ $$PATH/playercontroller.h
+
+SOURCES += \
+ $$PATH/matchcontroller.cpp \
+ $$PATH/chickencontroller.cpp \
+ $$PATH/playercontroller.cpp
diff --git a/chicken-wranglers/src/controllers/matchcontroller.cpp b/chicken-wranglers/src/controllers/matchcontroller.cpp
new file mode 100644
index 0000000..e25d3db
--- /dev/null
+++ b/chicken-wranglers/src/controllers/matchcontroller.cpp
@@ -0,0 +1,246 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+#include "matchcontroller.h"
+
+#include "chickencontroller.h"
+#include "matchai.h"
+#include "playercontroller.h"
+#include "playermodel.h"
+#include "settings.h"
+
+#include <QtDeclarative>
+
+MatchController::MatchController(QObject *parent)
+ : QObject(parent)
+{
+}
+
+MatchController::MatchController(PlayerListModel *model, int chickens, int elapsedTime, QObject *parent)
+ : QObject(parent), m_playerListModel(model), m_matchAI(0),
+ m_chickens(chickens), m_elapsedTime(elapsedTime), m_status(Ready)
+{
+ qmlRegisterType<ChickenController>("game.types", 1, 0, "ChickenController");
+ qmlRegisterType<PlayerController>("game.types", 1, 0, "PlayerController");
+}
+
+MatchController::~MatchController()
+{
+ if (m_matchAI)
+ delete m_matchAI;
+}
+
+void MatchController::updateElapsedTime()
+{
+ m_time = m_time.addSecs(-1);
+ m_elapsedTime--;
+
+ emit elapsedTimeChanged();
+}
+
+QString MatchController::elapsedTime() const
+{
+ return m_time.toString("mm:ss");
+}
+
+void MatchController::setStatus(Status status)
+{
+ if (m_status == status)
+ return;
+
+ m_status = status;
+
+ switch (status) {
+ case Started:
+ start();
+ break;
+ case Paused:
+ pause();
+ break;
+ case Running:
+ resume();
+ break;
+ case Over:
+ leave();
+ break;
+ default:
+ qWarning("Invalid match status");
+ }
+
+ emit statusChanged();
+}
+
+void MatchController::start()
+{
+ m_timer.start();
+
+ m_status = Running;
+}
+
+void MatchController::pause()
+{
+ m_timer.stop();
+}
+
+void MatchController::resume()
+{
+ m_timer.start();
+}
+
+void MatchController::leave()
+{
+ emit matchOver();
+}
+
+void MatchController::matchTimeout()
+{
+ m_timer.stop();
+
+ emit matchFinished();
+}
+
+void MatchController::setupMatch()
+{
+ // FIXME: These should not be hardcoded
+ m_playerStartPositionList.append(QPoint(0, 0));
+ m_playerStartPositionList.append(QPoint(9, 9));
+ m_playerStartPositionList.append(QPoint(0, 9));
+ m_playerStartPositionList.append(QPoint(9, 0));
+
+ m_matchAI = new MatchAI(QSize(10, 10));
+
+ m_time.setHMS(0, 0, 0);
+ m_time = m_time.addSecs(m_elapsedTime);
+ m_timer.setInterval(1000);
+ connect(&m_timer, SIGNAL(timeout()),
+ this, SLOT(onTimerTick()));
+
+ createPlayers();
+ createChickens();
+}
+
+void MatchController::createChickens()
+{
+ m_chickenCount = m_chickens;
+
+ for (int i = 0; i < m_chickenCount; i++) {
+ ChickenController *chickenController = new ChickenController(m_matchAI, this);
+ chickenControllerList.append(chickenController);
+
+ emit chickenCreated(i);
+ }
+}
+
+void MatchController::createPlayers()
+{
+ int i;
+
+ for (i = 0; i < m_playerListModel->rowCount() && i < m_playerStartPositionList.size(); i++) {
+ PlayerModel *playerModel = m_playerListModel->get(i);
+
+ PlayerController *playerController = new PlayerController(playerModel, m_matchAI, this);
+ playerController->setPosition(m_playerStartPositionList.at(i));
+ Node *henCoop = m_matchAI->addPlayer(m_playerStartPositionList.at(i));
+ if (!henCoop) {
+ qWarning("Error adding player to match AI");
+ playerController->deleteLater();
+ continue;
+ }
+
+ connect(henCoop, SIGNAL(chickenEntered(int)),
+ playerController, SLOT(onScore(int)));
+
+ connect(henCoop, SIGNAL(chickenEntered(int)),
+ this, SLOT(onChickenEntered(int)));
+
+ playerControllerList.append(playerController);
+
+ emit playerCreated(i);
+ }
+}
+
+ChickenController *MatchController::getChicken(int id) const
+{
+ if (id >= chickenControllerList.size() || id < 0)
+ return 0;
+
+ return chickenControllerList.at(id);
+}
+
+PlayerController *MatchController::getPlayer(int id) const
+{
+ if (id >= playerControllerList.size() || id < 0)
+ return 0;
+
+ return playerControllerList.at(id);
+}
+
+void MatchController::toggleLaser(int x, int y, int laserDirection)
+{
+ foreach(PlayerController *playerController, playerControllerList)
+ m_matchAI->doSafe(playerController->position());
+
+ bool isOn = m_matchAI->toggleLaser(QPoint(x, y),
+ static_cast<Global::LaserDirection>(laserDirection));
+
+ foreach(PlayerController *playerController, playerControllerList)
+ m_matchAI->doUnSafe(playerController->position());
+
+ emit laserUpdated(x, y, laserDirection, isOn);
+}
+
+void MatchController::onTimerTick()
+{
+ updateElapsedTime();
+
+ if (m_elapsedTime == 0)
+ matchTimeout();
+}
+
+void MatchController::onChickenEntered(int)
+{
+ if (--m_chickenCount > 0)
+ return;
+
+ m_timer.stop();
+
+ emit matchFinished();
+}
diff --git a/chicken-wranglers/src/controllers/matchcontroller.h b/chicken-wranglers/src/controllers/matchcontroller.h
new file mode 100644
index 0000000..c6c4e0f
--- /dev/null
+++ b/chicken-wranglers/src/controllers/matchcontroller.h
@@ -0,0 +1,132 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+#ifndef MATCHCONTROLLER_H
+#define MATCHCONTROLLER_H
+
+#include "global.h"
+
+#include <QtCore/QObject>
+#include <QtCore/QPoint>
+#include <QtCore/QTime>
+#include <QtCore/QTimer>
+
+class ChickenController;
+class MatchAI;
+class PlayerController;
+class PlayerListModel;
+
+class MatchController : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QString elapsedTime READ elapsedTime NOTIFY elapsedTimeChanged)
+ Q_PROPERTY(Status status READ status WRITE setStatus NOTIFY statusChanged)
+
+ Q_ENUMS(Status)
+
+public:
+ MatchController(QObject *parent = 0);
+ MatchController(PlayerListModel *model, int chickens, int elapsedTime, QObject *parent = 0);
+ ~MatchController();
+
+ enum Status {
+ Ready,
+ Started,
+ Paused,
+ Running,
+ Over
+ };
+
+ QString elapsedTime() const;
+
+ void setStatus(Status status);
+ Status status() const { return m_status; }
+
+ Q_INVOKABLE void setupMatch();
+ Q_INVOKABLE ChickenController *getChicken(int id) const;
+ Q_INVOKABLE PlayerController *getPlayer(int id) const;
+
+ Q_INVOKABLE void toggleLaser(int x, int y, int laserDirection);
+
+signals:
+ void chickenCreated(int id);
+ void playerCreated(int id);
+ void laserUpdated(int x, int y, int laserDirection, bool isOn);
+ void elapsedTimeChanged();
+ void statusChanged();
+ void matchFinished();
+ void matchOver();
+
+ void aborted();
+
+private slots:
+ void onTimerTick();
+ void onChickenEntered(int);
+
+private:
+ void setup();
+ void createChickens();
+ void createPlayers();
+ void updateElapsedTime();
+ void start();
+ void pause();
+ void resume();
+ void leave();
+ void matchTimeout();
+
+ QList<QPoint> m_playerStartPositionList;
+
+ QList<ChickenController *> chickenControllerList;
+ QList<PlayerController *> playerControllerList;
+
+ PlayerListModel *m_playerListModel;
+ MatchAI *m_matchAI;
+ QTimer m_timer;
+ QTime m_time;
+ int m_chickens;
+ int m_elapsedTime;
+ Status m_status;
+ int m_chickenCount;
+};
+
+#endif
diff --git a/chicken-wranglers/src/controllers/playercontroller.cpp b/chicken-wranglers/src/controllers/playercontroller.cpp
new file mode 100644
index 0000000..98f17fa
--- /dev/null
+++ b/chicken-wranglers/src/controllers/playercontroller.cpp
@@ -0,0 +1,127 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+#include "playercontroller.h"
+
+#include "matchai.h"
+#include "matchcontroller.h"
+#include "playermodel.h"
+#include "soundmanager.h"
+
+PlayerController::PlayerController(QObject *parent)
+ : QObject(parent)
+{
+}
+
+PlayerController::PlayerController(PlayerModel *model, MatchAI *matchAI, QObject *parent)
+ : QObject(parent), m_model(model), m_matchAI(matchAI), m_score(0)
+{
+ connect(m_model, SIGNAL(laserToggleRequested(Global::LaserDirection)),
+ this, SLOT(onLaserToggleRequested(Global::LaserDirection)));
+}
+
+PlayerController::~PlayerController()
+{
+}
+
+void PlayerController::setPosition(const QPoint &position)
+{
+ if (position == m_position)
+ return;
+
+ m_position = position;
+
+ emit positionChanged();
+}
+
+void PlayerController::onScore(int score)
+{
+ SoundManager::play(SoundManager::Score);
+
+ m_model->setScore(score);
+}
+
+void PlayerController::move()
+{
+ Q_ASSERT(m_matchAI);
+
+ Global::Direction direction = m_model->direction();
+ QPoint nextPosition = m_matchAI->movePlayer(m_position, direction);
+ setPosition(nextPosition);
+}
+
+bool PlayerController::isSameDirection(Global::LaserDirection laserDirection)
+{
+ Global::Direction currentDirection = m_model->direction();
+
+ if (currentDirection == Global::DirectionStop)
+ return true;
+
+ if (laserDirection == Global::LaserUp && currentDirection == Global::DirectionUp)
+ return true;
+
+ if (laserDirection == Global::LaserDown && currentDirection == Global::DirectionDown)
+ return true;
+
+ if (laserDirection == Global::LaserLeft && currentDirection == Global::DirectionLeft)
+ return true;
+
+ if (laserDirection == Global::LaserRight && currentDirection == Global::DirectionRight)
+ return true;
+
+ return false;
+}
+
+void PlayerController::onLaserToggleRequested(Global::LaserDirection laserDirection)
+{
+ SoundManager::play(SoundManager::Laser);
+
+ if (isSameDirection(laserDirection)) {
+ MatchController *matchController = qobject_cast<MatchController *>(parent());
+ if (!matchController) {
+ qWarning("Error getting MatchController from PlayerController");
+ return;
+ }
+
+ matchController->toggleLaser(m_position.x(), m_position.y(), laserDirection);
+ } else
+ emit laserToggleRequested(laserDirection);
+}
diff --git a/chicken-wranglers/src/controllers/playercontroller.h b/chicken-wranglers/src/controllers/playercontroller.h
new file mode 100644
index 0000000..2295d03
--- /dev/null
+++ b/chicken-wranglers/src/controllers/playercontroller.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+#ifndef PLAYERCONTROLLER_H
+#define PLAYERCONTROLLER_H
+
+#include <QtCore/QObject>
+#include <QtCore/QPoint>
+
+#include "global.h"
+
+class MatchAI;
+class PlayerModel;
+
+class PlayerController : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QPoint position READ position NOTIFY positionChanged)
+
+public:
+ PlayerController(QObject *parent = 0);
+ PlayerController(PlayerModel *model, MatchAI *matchAI, QObject *parent = 0);
+ ~PlayerController();
+
+ PlayerModel *model() const { return m_model; }
+
+ QPoint position() const { return m_position; }
+ void setPosition(const QPoint &position);
+ int score() const { return m_score; }
+
+ Q_INVOKABLE void move();
+
+public slots:
+ void onScore(int score);
+
+signals:
+ void positionChanged();
+ void scoreChanged();
+ void laserToggleRequested(int laserDirection);
+
+private slots:
+ void onLaserToggleRequested(Global::LaserDirection direction);
+
+private:
+ bool isSameDirection(Global::LaserDirection laserDirection);
+
+ PlayerModel *m_model;
+ MatchAI *m_matchAI;
+ QPoint m_position;
+ int m_score;
+};
+
+#endif
diff --git a/chicken-wranglers/src/main/argumentparser.cpp b/chicken-wranglers/src/main/argumentparser.cpp
new file mode 100644
index 0000000..151ff8b
--- /dev/null
+++ b/chicken-wranglers/src/main/argumentparser.cpp
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+#include "argumentparser.h"
+
+ArgumentProcessor::ArgumentProcessor(QStringList options)
+ : m_args(options)
+{
+}
+
+QSize ArgumentProcessor::display()
+{
+ QSize result;
+ // -displaysize
+ QStringList displaySizeList = valueForOption("-displaysize").split("x");
+ if (displaySizeList.size() == 2) {
+ result.setWidth(displaySizeList.at(0).toInt());
+ result.setHeight(displaySizeList.at(1).toInt());
+ }
+
+ return result;
+}
+
+QString ArgumentProcessor::connectivity()
+{
+ QString result("bluetooth");
+ // -connectivity bluetooth | lan
+ QString argument = valueForOption("-connectivity");
+ if (argument == "lan") {
+ result = "lan";
+ }
+
+ return result;
+}
+
+QString ArgumentProcessor::tcpPort()
+{
+ QString result("-1");
+ // -tcpport
+ QString argument = valueForOption("-tcpport");
+ if (!argument.isEmpty())
+ result = argument;
+
+ return result;
+}
+
+QString ArgumentProcessor::udpPort()
+{
+ QString result("-1");
+ // -udpport
+ QString argument = valueForOption("-udpport");
+ if (!argument.isEmpty())
+ result = argument;
+
+ return result;
+}
+
+QString ArgumentProcessor::graphicsMode()
+{
+ QString result("opengl");
+ // - opengl | raster
+ QString argument = valueForOption("-graphicsmode");
+ if (argument == "raster") {
+ result = "raster";
+ }
+
+ return result;
+}
+
+QString ArgumentProcessor::valueForOption(const QString &option)
+{
+ int optionIndex = m_args.indexOf(option);
+
+ if ((optionIndex != -1) && (optionIndex + 1 < m_args.size()))
+ return m_args.at(optionIndex + 1);
+
+ return QString();
+}
+
diff --git a/chicken-wranglers/src/main/argumentparser.h b/chicken-wranglers/src/main/argumentparser.h
new file mode 100644
index 0000000..c77e644
--- /dev/null
+++ b/chicken-wranglers/src/main/argumentparser.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+#ifndef ARGUMENTPARSER_H
+#define ARGUMENTPARSER_H
+
+#include <QtCore/QSize>
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+
+class ArgumentProcessor
+{
+public:
+ ArgumentProcessor(QStringList options);
+
+ QSize display();
+
+ QString connectivity();
+
+ QString tcpPort();
+
+ QString udpPort();
+
+ QString graphicsMode();
+
+ //TODO: move to another file, etc
+
+private:
+ QString valueForOption(const QString &option);
+
+ QStringList m_args;
+};
+
+#endif
diff --git a/chicken-wranglers/src/main/game.cpp b/chicken-wranglers/src/main/game.cpp
new file mode 100644
index 0000000..e168503
--- /dev/null
+++ b/chicken-wranglers/src/main/game.cpp
@@ -0,0 +1,206 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+#include <QtDeclarative>
+#include <QtGui/QApplication>
+#include <QtOpenGL/QGLWidget>
+
+#include "charactermodel.h"
+#include "connectivitylistmodel.h"
+#include "global.h"
+#include "settings.h"
+#include "soundmanager.h"
+#include "gameclient.h"
+#include "gamehost.h"
+#include "soundmanager.h"
+
+#include "game.h"
+
+Game::Game(const GraphicsMode &mode, QObject *parent)
+ : QObject(parent), m_gameClient(0), m_gameHost(0),
+ m_connectivity("bluetooth"), m_mode(None)
+{
+ qmlRegisterType<Global>("game.types", 1, 0, "Global");
+ qmlRegisterType<Game>("game.types", 1, 0, "Game");
+ qmlRegisterType<GameClient>("game.types", 1, 0, "GameClient");
+ qmlRegisterType<GameHost>("game.types", 1, 0, "GameHost");
+ // FIXME: Register this model later when GameClient is created.
+ qmlRegisterType<ConnectivityListModel>("game.types", 1, 0, "ConnectivityListModel");
+
+ m_view = new QDeclarativeView;
+ if (mode == OpenGL) {
+ //XXX: for some reason, setting the GLWidget is not enabling
+ //ogl in Symbian
+ if (Global::environment() == Global::Symbian) {
+ QApplication::setGraphicsSystem("opengl");
+ } else {
+ m_view->setViewport(new QGLWidget);
+ }
+ } else {
+ QApplication::setGraphicsSystem("raster");
+ }
+
+ m_view->setResizeMode(QDeclarativeView::SizeRootObjectToView);
+ m_view->rootContext()->setContextProperty("game", this);
+ m_view->rootContext()->setContextProperty("settings", Settings::instance());
+}
+
+Game::~Game()
+{
+ delete m_gameHost;
+ delete m_gameClient;
+ delete m_view;
+}
+
+void Game::setMode(Mode mode)
+{
+ if (mode == ClientMode)
+ startClientMode();
+ else if (mode == HostMode)
+ startHostMode();
+}
+
+void Game::startClientMode()
+{
+ m_mode = ClientMode;
+ if (m_gameClient) {
+ emit modeChanged();
+ return;
+ }
+
+ if (!m_gameClient) {
+ m_gameClient = new GameClient(m_view->rootContext(), m_connectivity, this);
+ m_view->rootContext()->setContextProperty("gameClient", m_gameClient);
+ connect(m_gameClient, SIGNAL(ended()), this, SLOT(onClientModeEnded()));
+ } else
+ ;//TODO: client has not a way to update the connectivity
+
+ emit modeChanged();
+}
+
+void Game::startHostMode()
+{
+ m_mode = HostMode;
+ if (m_gameHost) {
+ m_gameHost->setConnectivity(m_connectivity);
+ emit modeChanged();
+ return;
+ }
+
+ if (!m_gameHost) {
+ m_gameHost = new GameHost(m_view->rootContext(), m_connectivity, this);
+ m_view->rootContext()->setContextProperty("gameHost", m_gameHost);
+ connect(m_gameHost, SIGNAL(ended()), this, SLOT(onHostModeEnded()));
+ }
+
+
+ emit modeChanged();
+}
+
+void Game::start(const QSize &displaySize)
+{
+#ifdef CW_DEBUG
+ m_view->setSource(Global::rootDirectory().absoluteFilePath() + "/src/qml/main.qml");
+#else
+ m_view->setSource(QUrl("qrc:/main.qml"));
+#endif
+
+ QObject::connect(m_view->engine(), SIGNAL(quit()), m_view, SLOT(close()));
+
+ if (displaySize.isValid()) {
+ m_view->resize(displaySize);
+ m_view->show();
+ } else {
+ m_view->showFullScreen();
+ }
+}
+
+QSize Game::displaySize() const
+{
+ return m_view->size();
+}
+
+void Game::onHostModeEnded()
+{
+ m_mode = None;
+}
+
+void Game::onClientModeEnded()
+{
+ //TODO: client has not a way to update the connectivity
+ if (m_gameClient) {
+ delete m_gameClient;
+ m_gameClient = 0;
+ }
+ m_mode = None;
+}
+
+void Game::startBackgroundSound()
+{
+ SoundManager::play(SoundManager::Background);
+}
+
+int Game::environment()
+{
+ return Global::environment();
+}
+
+QString Game::connectivity() const
+{
+ return m_connectivity;
+}
+
+void Game::setConnectivity(const QString &type)
+{
+ if (m_connectivity == type)
+ return;
+
+ m_connectivity = type;
+ if (m_mode == HostMode) {
+ onHostModeEnded();
+ startHostMode();
+ } else {
+ onClientModeEnded();
+ startClientMode();
+ }
+}
+
diff --git a/chicken-wranglers/src/main/game.h b/chicken-wranglers/src/main/game.h
new file mode 100644
index 0000000..bf297b4
--- /dev/null
+++ b/chicken-wranglers/src/main/game.h
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+#ifndef GAME_H
+#define GAME_H
+
+#include <QtCore/QObject>
+#include <QtCore/QSize>
+
+#include "gameclient.h"
+#include "gamehost.h"
+
+class GameClient;
+class GameHost;
+class QDeclarativeView;
+
+class Game : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QSize displaySize READ displaySize NOTIFY displaySizeChanged)
+ Q_PROPERTY(Mode mode READ mode WRITE setMode NOTIFY modeChanged)
+ Q_PROPERTY(QString connectivity READ connectivity WRITE setConnectivity)
+
+ Q_ENUMS(Mode)
+
+public:
+ enum Mode {
+ None,
+ HostMode,
+ ClientMode
+ };
+
+ enum GraphicsMode {
+ OpenGL,
+ Raster
+ };
+
+ Game(const GraphicsMode &mode = OpenGL, QObject *parent = 0);
+ ~Game();
+
+ void start(const QSize &size = QSize());
+
+ Mode mode() { return m_mode; }
+ void setMode(Mode mode);
+
+ QSize displaySize() const;
+
+ QString connectivity() const;
+ Q_INVOKABLE void setConnectivity(const QString &type);
+
+ Q_INVOKABLE void startBackgroundSound();
+ Q_INVOKABLE int environment();
+
+signals:
+ void modeChanged();
+ void displaySizeChanged();
+
+private slots:
+ void onClientModeEnded();
+ void onHostModeEnded();
+
+private:
+ void startClientMode();
+ void startHostMode();
+ void setupSounds();
+
+ QDeclarativeView *m_view;
+ GameClient *m_gameClient;
+ GameHost *m_gameHost;
+ QString m_connectivity;
+ Mode m_mode;
+};
+
+#endif
diff --git a/chicken-wranglers/src/main/gameclient.cpp b/chicken-wranglers/src/main/gameclient.cpp
new file mode 100644
index 0000000..4d2e461
--- /dev/null
+++ b/chicken-wranglers/src/main/gameclient.cpp
@@ -0,0 +1,423 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+#include <QtCore/QStringList>
+#include <QtDeclarative/QDeclarativeContext>
+
+#include "charactermodel.h"
+#include "connectivitylistmodel.h"
+#include "control.h"
+#include "global.h"
+#include "networkclient.h"
+#include "sensormovement.h"
+#include "settings.h"
+
+#include "gameclient.h"
+
+GameClient::GameClient(QObject *parent)
+ : QObject(parent)
+{
+}
+
+GameClient::GameClient(QDeclarativeContext *context, const QString &connectivity, QObject *parent)
+ : QObject(parent), m_declarativeContext(context), m_networkClient(0),
+ m_characterListModel(0), m_connectivityListModel(0), m_control(new Control(this)),
+ m_status(NoStatus), m_error(NoError)
+{
+ m_networkClient = new NetworkClient(connectivity, Settings::lanUdpDiscoveryTimeout(),
+ Settings::lanUdpDiscoveryClientAttempts(), this);
+ m_networkClient->setLanPorts(Settings::lanUdpPort(), Settings::lanTcpPort());
+
+ connect(m_networkClient, SIGNAL(serverDiscoveryTimeout()),
+ this, SLOT(onServerDiscoveryTimeout()));
+ connect(m_networkClient, SIGNAL(connected()),
+ this, SLOT(onConnected()));
+ connect(m_networkClient, SIGNAL(disconnected()),
+ this, SLOT(onDisconnected()));
+ connect(m_networkClient, SIGNAL(socketError(QAbstractSocket::SocketError)),
+ this, SLOT(onSocketError(QAbstractSocket::SocketError)));
+ connect(m_networkClient, SIGNAL(messageReceived(NetworkMessage)),
+ this, SLOT(onMessageReceived(NetworkMessage)));
+
+ m_connectivityListModel = new ConnectivityListModel(this);
+ connect(m_networkClient, SIGNAL(bluetoothDeviceDiscovered(const BluetoothDevice &)),
+ m_connectivityListModel, SLOT(addDevice(const BluetoothDevice &)));
+ connect(m_connectivityListModel, SIGNAL(selectedDevice(const QString &)),
+ m_networkClient, SLOT(stopDiscovery()));
+ connect(m_connectivityListModel, SIGNAL(selectedDevice(const QString &)),
+ m_networkClient, SLOT(connectToBluetoothServer(const QString &)));
+ m_declarativeContext->setContextProperty("connectivityListModel", m_connectivityListModel);
+
+ SensorMovement *sensorMovement = m_control->sensorMovement();
+ sensorMovement->setMinimumRotation(1);
+ sensorMovement->setThreshold(0.2);
+
+ connect(m_control, SIGNAL(directionChanged(Global::Direction)),
+ this, SLOT(onControlDirectionChanged(Global::Direction)));
+
+ // TODO: This was tested only on Maemo5. There should
+ // be specific implementations for Maemo6 and Symbian
+ //
+ // m_backlightTimer.setInterval(20000);
+ // connect(&m_backlightTimer, SIGNAL(timeout()), this, SLOT(forceBackLightOn()));
+}
+
+void GameClient::setStatus(GameClient::Status status)
+{
+ if (m_status == status)
+ return;
+
+ m_status = status;
+
+ emit statusChanged();
+}
+
+void GameClient::setLeader(bool isLeader)
+{
+ if (m_isLeader == isLeader)
+ return;
+
+ m_isLeader = isLeader;
+
+ emit isLeaderChanged();
+}
+
+void GameClient::startConnection()
+{
+ m_error = NoError;
+ m_status = NoStatus;
+
+ m_connectivityListModel->loadLastHostDevice();
+ m_networkClient->startDiscovery();
+}
+
+void GameClient::toggleLaserUp()
+{
+ notifyPlayerControlLaser(CW::PlayerControlLaserUp);
+}
+
+void GameClient::toggleLaserDown()
+{
+ notifyPlayerControlLaser(CW::PlayerControlLaserDown);
+}
+
+void GameClient::toggleLaserLeft()
+{
+ notifyPlayerControlLaser(CW::PlayerControlLaserLeft);
+}
+
+void GameClient::toggleLaserRight()
+{
+ notifyPlayerControlLaser(CW::PlayerControlLaserRight);
+}
+
+void GameClient::moveUp()
+{
+ onControlDirectionChanged(Global::DirectionUp);
+}
+
+void GameClient::moveDown()
+{
+ onControlDirectionChanged(Global::DirectionDown);
+}
+
+void GameClient::moveLeft()
+{
+ onControlDirectionChanged(Global::DirectionLeft);
+}
+
+void GameClient::moveRight()
+{
+ onControlDirectionChanged(Global::DirectionRight);
+}
+
+void GameClient::moveStop()
+{
+ onControlDirectionChanged(Global::DirectionStop);
+}
+
+void GameClient::quit()
+{
+ m_error = NoError;
+ m_status = NoStatus;
+
+ m_networkClient->stopDiscovery();
+
+ emit ended();
+}
+
+void GameClient::onServerDiscoveryTimeout()
+{
+ m_error = ServerDiscoveryTimeoutError;
+
+ setStatus(Error);
+
+ quit();
+}
+
+void GameClient::onConnected()
+{
+ m_connectivityListModel->storeLastHostDevice();
+
+ disconnect(m_networkClient, SIGNAL(connected()), this, SLOT(onConnected()));
+
+ loadCharacters();
+
+ setStatus(Joined);
+}
+
+void GameClient::onDisconnected()
+{
+ disconnect(m_networkClient, SIGNAL(disconnected()), this, SLOT(onDisconnected()));
+
+ setStatus(NoStatus);
+}
+
+void GameClient::onMessageReceived(const NetworkMessage &message)
+{
+ switch (message.type()) {
+ case CW::CharacterMessageType:
+ handleCharacterMessage(message);
+ break;
+ case CW::MatchMessageType:
+ handleMatchMessage(message);
+ break;
+ case CW::PlayerInfoMessageType:
+ handlePlayerInfoMessage(message);
+ break;
+ default:
+ qWarning("Invalid message type");
+ }
+}
+
+void GameClient::onSocketError(QAbstractSocket::SocketError error)
+{
+ Q_UNUSED(error);
+
+ m_error = SocketError;
+
+ setStatus(Error);
+}
+
+void GameClient::loadCharacters()
+{
+ if (!m_characterListModel)
+ m_characterListModel = new CharacterListModel(this);
+
+ if (!m_characterListModel->load()) {}
+
+ m_declarativeContext->setContextProperty("characterListModel", m_characterListModel);
+
+ connect(m_characterListModel, SIGNAL(selectedIndexChanged()),
+ this, SLOT(onModelSelectedIndexChanged()));
+}
+
+void GameClient::onModelSelectedIndexChanged()
+{
+ int selectedIndex = m_characterListModel->selectedIndex();
+
+ if (selectedIndex != -1) {
+ CharacterModel *characterModel = m_characterListModel->get(selectedIndex);
+ notifyCharacterSelected(characterModel->name());
+ } else {
+ notifyCharacterReleased();
+ }
+}
+
+void GameClient::notifyCharacterSelected(const QString &characterName)
+{
+ NetworkMessage message(CW::CharacterMessageType, CW::CharacterSelected);
+ message.setData(characterName.toLatin1());
+
+ m_networkClient->send(message);
+}
+
+void GameClient::notifyCharacterReleased()
+{
+ NetworkMessage message(CW::CharacterMessageType, CW::CharacterReleased);
+
+ m_networkClient->send(message);
+}
+
+void GameClient::notifyPlayerControlLaser(CW::PlayerControl laserDirection)
+{
+ NetworkMessage message(CW::PlayerControlMessageType, laserDirection);
+
+ m_networkClient->send(message);
+}
+
+void GameClient::handleCharacterMessage(const NetworkMessage &message)
+{
+ if (!m_characterListModel) {
+ // XXX: Properly thrown an exception for the Game class
+ qCritical("Error: CharacterListModel not initialized.");
+ return;
+ }
+
+ switch (message.content()) {
+ case CW::CharacterSelected: {
+ QString characterName(message.data());
+
+ CharacterModel *model;
+ for (int i = 0; i < m_characterListModel->rowCount(); i++) {
+ model = m_characterListModel->get(i);
+ if (model->name() == characterName)
+ model->setAvailable(false);
+ }
+
+ break;
+ }
+ case CW::CharacterAvailableList: {
+ QStringList availableCharacters(QString(message.data()).split("|"));
+
+ CharacterModel *model;
+ for (int i = 0; i < m_characterListModel->rowCount(); i++) {
+ model = m_characterListModel->get(i);
+ if (!availableCharacters.contains(model->name()))
+ model->setAvailable(false);
+ }
+
+ break;
+ }
+ case CW::CharacterIsAvailable: {
+ QStringList messageDataList(QString(message.data()).split("|"));
+ QString characterName = messageDataList.at(0);
+
+ bool characterIsAvailable(true);
+ if (messageDataList.at(1) == "0")
+ characterIsAvailable = false;
+
+ CharacterModel *model;
+ for (int i = 0; i < m_characterListModel->rowCount(); i++) {
+ model = m_characterListModel->get(i);
+
+ if (model->name() == characterName)
+ model->setAvailable(characterIsAvailable);
+ }
+
+ break;
+ }
+ }
+}
+
+void GameClient::handleMatchMessage(const NetworkMessage &message)
+{
+ switch (message.content()) {
+ case CW::MatchReady:
+ setStatus(Ready);
+ m_control->start();
+ forceBackLightOn();
+ m_backlightTimer.start();
+ break;
+ case CW::MatchFinished:
+ setStatus(LeftMatch);
+ m_control->stop();
+ m_backlightTimer.stop();
+ break;
+ default:
+ qWarning("Invalid match message");
+ }
+}
+
+void GameClient::handlePlayerInfoMessage(const NetworkMessage &message)
+{
+ switch (message.content()) {
+ case CW::PlayerInfoLeader: {
+ bool isLeader(false);
+ if (message.data() == "1")
+ isLeader = true;
+
+ setLeader(isLeader);
+
+ break;
+ }
+ default:
+ qWarning("Invalid player info message");
+ }
+}
+
+// FIXME: Move this function to a better place
+static CW::PlayerControl directionToPlayerControl(Global::Direction direction)
+{
+ QMap<Global::Direction, CW::PlayerControl> playerControl;
+
+ playerControl[Global::DirectionUp] = CW::PlayerControlUp;
+ playerControl[Global::DirectionDown] = CW::PlayerControlDown;
+ playerControl[Global::DirectionRight] = CW::PlayerControlRight;
+ playerControl[Global::DirectionLeft] = CW::PlayerControlLeft;
+ playerControl[Global::DirectionStop] = CW::PlayerControlStop;
+
+ return playerControl[direction];
+}
+
+void GameClient::onControlDirectionChanged(Global::Direction direction)
+{
+ NetworkMessage message(CW::PlayerControlMessageType, directionToPlayerControl(direction));
+
+ m_networkClient->send(message);
+}
+
+void GameClient::forceBackLightOn()
+{
+ /* TODO: Provide specific implementations for Maemo6 and Symbian
+
+ if (!QDBusConnection::systemBus().isConnected()) {
+ qWarning("Error connecting to session bus");
+ return;
+ }
+
+ QDBusInterface iface("com.nokia.mce", "/com/nokia/mce/request", "com.nokia.mce.request",
+ QDBusConnection::systemBus());
+
+ if (iface.isValid())
+ iface.call("req_tklock_mode_change", QString("unlocked"));
+ else
+ qWarning("Error calling com.nokia.mce.request.req_tklock_mode_change");
+ */
+}
+
+void GameClient::scanCanceled()
+{
+ m_networkClient->stopDiscovery();
+
+ // scan is assynchronous, so wait a little bit before cleaning the model
+ QTimer::singleShot(300, m_connectivityListModel, SLOT(clear()));
+}
diff --git a/chicken-wranglers/src/main/gameclient.h b/chicken-wranglers/src/main/gameclient.h
new file mode 100644
index 0000000..7e9e7ad
--- /dev/null
+++ b/chicken-wranglers/src/main/gameclient.h
@@ -0,0 +1,156 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+#ifndef GAMECLIENT_H
+#define GAMECLIENT_H
+
+#include <QtCore/QObject>
+#include <QtCore/QTimer>
+#include <QtNetwork/QHostAddress>
+
+#include "global.h"
+#include "networkmessage.h"
+
+class CharacterListModel;
+class ConnectivityListModel;
+class Control;
+class NetworkClient;
+class QDeclarativeContext;
+
+class GameClient : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(Status status READ status WRITE setStatus NOTIFY statusChanged)
+ Q_PROPERTY(bool isLeader READ isLeader WRITE setLeader NOTIFY isLeaderChanged)
+ Q_PROPERTY(ErrorType error READ error NOTIFY errorChanged)
+ Q_ENUMS(Status ErrorType)
+
+public:
+ GameClient(QObject *parent = 0);
+ GameClient(QDeclarativeContext *context, const QString &connectivity = "lan",
+ QObject *parent = 0);
+
+ enum Status {
+ NoStatus,
+ Joined,
+ LeftMatch,
+ Ready,
+ Playing,
+ Error
+ };
+
+ enum ErrorType {
+ NoError,
+ ServerDiscoveryTimeoutError,
+ SocketError,
+ UnknownError
+ };
+
+ Status status() { return m_status; }
+ void setStatus(Status status);
+
+ void setLeader(bool isLeader);
+ bool isLeader() const { return m_isLeader; }
+
+ ErrorType error() { return m_error; }
+
+public slots:
+ void startConnection();
+
+ void scanCanceled();
+
+ // TODO: Use a single toggle laser method with direction parameter
+ void toggleLaserUp();
+ void toggleLaserDown();
+ void toggleLaserLeft();
+ void toggleLaserRight();
+
+ // TODO: Use a single move method with direction parameter
+ void moveUp();
+ void moveDown();
+ void moveLeft();
+ void moveRight();
+ void moveStop();
+
+ void quit();
+
+signals:
+ void statusChanged();
+ void errorChanged();
+ void isLeaderChanged();
+ void ended();
+
+private slots:
+ void onServerDiscoveryTimeout();
+ void onConnected();
+ void onDisconnected();
+ void onMessageReceived(const NetworkMessage &message);
+ void onSocketError(QAbstractSocket::SocketError error);
+ void onModelSelectedIndexChanged();
+ void onControlDirectionChanged(Global::Direction direction);
+ void forceBackLightOn();
+
+private:
+ void loadCharacters();
+
+ void handleCharacterMessage(const NetworkMessage &message);
+ void handleMatchMessage(const NetworkMessage &message);
+ void handlePlayerInfoMessage(const NetworkMessage &message);
+
+ void notifyCharacterSelected(const QString &characterName);
+ void notifyCharacterReleased();
+ void notifyDirectionChanged(Global::Direction);
+ void notifyPlayerControlLaser(CW::PlayerControl laserDirection);
+
+ QDeclarativeContext *m_declarativeContext;
+ NetworkClient *m_networkClient;
+ CharacterListModel *m_characterListModel;
+ ConnectivityListModel *m_connectivityListModel;
+ Control *m_control;
+ Status m_status;
+ ErrorType m_error;
+ bool m_isLeader;
+ QTimer m_backlightTimer;
+};
+
+#endif
diff --git a/chicken-wranglers/src/main/gamehost.cpp b/chicken-wranglers/src/main/gamehost.cpp
new file mode 100644
index 0000000..6948d65
--- /dev/null
+++ b/chicken-wranglers/src/main/gamehost.cpp
@@ -0,0 +1,199 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+#include <QtDeclarative>
+
+#include "global.h"
+#include "matchcontroller.h"
+#include "networkconnection.h"
+#include "playermodel.h"
+#include "settings.h"
+
+#include "gamehost.h"
+
+GameHost::GameHost(QDeclarativeContext *context, const QString &connectivity,
+ QObject *parent)
+ : QObject(parent), m_declarativeContext(context), m_networkServer(0),
+ m_playerListModel(new PlayerListModel(this)), m_matchController(0),
+ m_status(NoStatus), m_error(NoError)
+{
+ m_declarativeContext->setContextProperty("playerListModel", m_playerListModel);
+
+ qmlRegisterType<MatchController>("game.types", 1, 0, "Match");
+
+ m_networkServer = new NetworkServer(connectivity, Settings::lanUdpDiscoveryTimeout(),
+ Settings::lanUdpDiscoveryHostAttempts());
+ m_networkServer->setLanPorts(Settings::lanUdpPort(), Settings::lanTcpPort());
+
+ connect(m_networkServer, SIGNAL(error(NetworkServer::ServerError)),
+ this, SLOT(onServerError(NetworkServer::ServerError)));
+ connect(m_networkServer, SIGNAL(started()),
+ this, SLOT(onServerStarted()));
+ connect(m_networkServer, SIGNAL(peerConnected(NetworkConnection *)),
+ this, SLOT(onPeerConnected(NetworkConnection *)));
+ connect(m_networkServer, SIGNAL(peerDisconnected(NetworkConnection *)),
+ this, SLOT(onPeerDisconnected(NetworkConnection *)));
+}
+
+GameHost::GameHost(QObject *parent)
+ : QObject(parent)
+{
+}
+
+GameHost::~GameHost()
+{
+ delete m_networkServer;
+}
+
+void GameHost::setStatus(Status status)
+{
+ if (m_status == status)
+ return;
+
+ m_status = status;
+
+ if (m_status == Match)
+ newMatch();
+}
+
+void GameHost::newMatch()
+{
+ if (m_matchController) {
+ m_matchController->deleteLater();
+ m_matchController = 0;
+ }
+
+ m_matchController = new MatchController(m_playerListModel, Settings::matchChickenNumber(),
+ Settings::matchTime(), this);
+ m_declarativeContext->setContextProperty("matchController", m_matchController);
+
+ connect(m_matchController, SIGNAL(matchOver()),
+ this, SLOT(onMatchOver()));
+
+ m_playerListModel->notifyMatchReady();
+}
+
+void GameHost::startConnection()
+{
+ m_error = NoError;
+ m_status = NoStatus;
+
+ m_networkServer->start();
+}
+
+void GameHost::quit()
+{
+ m_error = NoError;
+ m_status = NoStatus;
+ m_networkServer->closeAll();
+
+ emit ended();
+}
+
+void GameHost::onPeerConnected(NetworkConnection *connection)
+{
+ qDebug("Peer connected: %d" , connection->id());
+
+ addPlayer(connection);
+}
+
+void GameHost::onPeerDisconnected(NetworkConnection *connection)
+{
+ qDebug("Peer disconnected: %d" , connection->id());
+
+ removePlayer(connection);
+}
+
+void GameHost::addPlayer(NetworkConnection *connection)
+{
+ if (m_playerListModel->rowCount() == Global::maximumPlayers) {
+ qWarning("Maximum number of players reached (%d)", Global::maximumPlayers);
+
+ // TODO: Notify client that host is full
+ return;
+ }
+
+ m_playerListModel->newPlayer(connection);
+}
+
+void GameHost::removePlayer(NetworkConnection *connection)
+{
+ m_playerListModel->removePlayer(connection);
+}
+
+void GameHost::onServerError(NetworkServer::ServerError error)
+{
+ if (error == NetworkServer::AnotherServerRunningError)
+ m_error = AnotherServerRunningError;
+ else
+ m_error = UnknownError;
+
+ if (m_status == Error)
+ return;
+
+ m_status = Error;
+ emit statusChanged();
+
+ quit();
+}
+
+void GameHost::onServerStarted()
+{
+ if (m_status == Start)
+ return;
+
+ m_status = Start;
+ emit statusChanged();
+}
+
+void GameHost::onMatchOver()
+{
+ m_status = WaitingRoom;
+
+ m_playerListModel->reset();
+ m_playerListModel->notifyMatchFinished();
+}
+
+void GameHost::setConnectivity(const QString &connectivity)
+{
+ m_networkServer->createConnectionHandler(connectivity);
+}
diff --git a/chicken-wranglers/src/main/gamehost.h b/chicken-wranglers/src/main/gamehost.h
new file mode 100644
index 0000000..795c954
--- /dev/null
+++ b/chicken-wranglers/src/main/gamehost.h
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+#ifndef GAMEHOST_H
+#define GAMEHOST_H
+
+#include <QtCore/QObject>
+
+#include "networkmessage.h"
+#include "networkserver.h"
+
+class MatchController;
+class PlayerListModel;
+class QDeclarativeContext;
+
+class GameHost : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(Status status READ status WRITE setStatus NOTIFY statusChanged)
+ Q_PROPERTY(ErrorType error READ error NOTIFY errorChanged)
+
+ Q_ENUMS(Status ErrorType GameState)
+
+public:
+ GameHost(QObject *parent = 0);
+ GameHost(QDeclarativeContext *context, const QString &connectivity,
+ QObject *parent = 0);
+ ~GameHost();
+
+ void setConnectivity(const QString &connectivity);
+
+ enum Status {
+ NoStatus,
+ Start,
+ WaitingRoom,
+ Match,
+ Error
+ };
+
+ enum ErrorType {
+ NoError,
+ AnotherServerRunningError,
+ UnknownError
+ };
+
+ Status status() { return m_status; }
+ void setStatus(Status status);
+
+ ErrorType error() { return m_error; }
+
+public slots:
+ void startConnection();
+ void quit();
+
+signals:
+ void statusChanged();
+ void errorChanged();
+ void ended();
+
+private slots:
+ void onServerError(NetworkServer::ServerError error);
+ void onServerStarted();
+
+ void onPeerConnected(NetworkConnection *connection);
+ void onPeerDisconnected(NetworkConnection *connection);
+
+ void onMatchOver();
+
+private:
+ void newMatch();
+ void addPlayer(NetworkConnection *connection);
+ void removePlayer(NetworkConnection *connection);
+
+ QDeclarativeContext *m_declarativeContext;
+ NetworkServer *m_networkServer;
+
+ PlayerListModel *m_playerListModel;
+ MatchController *m_matchController;
+ Status m_status;
+ ErrorType m_error;
+};
+
+#endif
diff --git a/chicken-wranglers/src/main/main.cpp b/chicken-wranglers/src/main/main.cpp
new file mode 100644
index 0000000..f98f4e6
--- /dev/null
+++ b/chicken-wranglers/src/main/main.cpp
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+#include <QtGui/QApplication>
+
+#include "argumentparser.h"
+#include "game.h"
+#include "global.h"
+#include "settings.h"
+
+int main(int argc, char *argv[])
+{
+ QCoreApplication::setOrganizationName(Settings::organizationName());
+ QCoreApplication::setOrganizationDomain(Settings::organizationDomain());
+ QCoreApplication::setApplicationName(Settings::applicationName());
+
+ if (!Settings::exists())
+ Settings::reset();
+
+ QApplication app(argc, argv);
+ ArgumentProcessor options(app.arguments());
+ QSize displaySize(options.display());
+
+ QString tcpPort = options.tcpPort();
+ QString udpPort = options.udpPort();
+
+ if (tcpPort != "-1")
+ Settings::setLanTcpPort(tcpPort);
+ if (udpPort != "-1")
+ Settings::setLanUdpPort(udpPort);
+
+ Settings::update();
+
+ Global::setScreenOrientation(Global::Landscape);
+ Game::GraphicsMode mode = options.graphicsMode() == "opengl" ?
+ Game::OpenGL : Game::Raster;
+
+ Game game(mode);
+ game.setConnectivity(options.connectivity());
+ if (options.connectivity() == "bluetooth") {
+ // FIXME: this function is not working in Symbian
+ // and is crashing in Meego 1.2 netbook. Need to discover
+ // why QBluetoothLocalDevice is misbehaving.
+ // Global::setPowerOn();
+ }
+
+ if (displaySize.isValid()) {
+ game.start(displaySize);
+ } else {
+ game.start();
+ }
+
+ return app.exec();
+}
diff --git a/chicken-wranglers/src/main/main.pri b/chicken-wranglers/src/main/main.pri
new file mode 100644
index 0000000..985062a
--- /dev/null
+++ b/chicken-wranglers/src/main/main.pri
@@ -0,0 +1,18 @@
+QT += declarative
+
+PATH = $$PWD
+
+HEADERS += \
+ $$PATH/game.h \
+ $$PATH/gameclient.h \
+ $$PATH/gamehost.h \
+ $$PATH/argumentparser.h \
+ $$PATH/settings.h
+
+SOURCES += \
+ $$PATH/main.cpp \
+ $$PATH/game.cpp \
+ $$PATH/gameclient.cpp \
+ $$PATH/gamehost.cpp \
+ $$PATH/argumentparser.cpp \
+ $$PATH/settings.cpp
diff --git a/chicken-wranglers/src/main/settings.cpp b/chicken-wranglers/src/main/settings.cpp
new file mode 100644
index 0000000..0d476ef
--- /dev/null
+++ b/chicken-wranglers/src/main/settings.cpp
@@ -0,0 +1,284 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+#include <QtCore/QFileInfo>
+#include <QtCore/QString>
+
+#include "settings.h"
+
+const QString Settings::m_organizationName = "Nokia";
+const QString Settings::m_organizationDomain = "nokia.com";
+const QString Settings::m_applicationName = "chicken-wranglers";
+
+// host
+static const QSize defaultHostDisplaySize = QSize(1280, 768);
+static const int defaultHostMaximumPlayers = 4;
+
+// match
+static const int defaultMatchChickenNumber = 40;
+static const int defaultMatchTime = 180;
+static const int defaultMatchChickenMoveInterval = 700;
+static const int defaultMatchChickenChangeStepsInterval = 260;
+static const int defaultMatchCharacterMoveInterval = 500;
+static const int defaultMatchCharacterChangeStepsInterval = 260;
+
+// battlefield
+static const QSize defaultBattlefieldSize = QSize(10, 10);
+static const int defaultBattlefieldCellSize = 70;
+static const QPoint defaultBattlefieldStartPoint = QPoint(290, 34);
+
+// local network
+static const int defaultLanTcpPort = 35000;
+static const int defaultLanUdpPort = 45000;
+static const int defaultLanUdpDiscoveryTimeout = 100;
+static const int defaultLanUdpDiscoveryClientAttempts = 50;
+static const int defaultLanUdpDiscoveryHostAttempts = 10;
+
+// bluetooth
+static const QString defaultBluetoothHostAddress = "00:00:00:00:00:00";
+static const QString defaultBluetoothHostName = "";
+
+Settings::Settings(QObject *parent)
+ : QSettings(QSettings::IniFormat, QSettings::UserScope,
+ m_organizationName, m_applicationName, parent)
+{
+}
+
+Settings *Settings::instance()
+{
+ static Settings settings;
+
+ return &settings;
+}
+
+void Settings::update()
+{
+ instance()->sync();
+}
+
+QString Settings::organizationName()
+{
+ return m_organizationName;
+}
+
+QString Settings::organizationDomain()
+{
+ return m_organizationDomain;
+}
+
+QString Settings::applicationName()
+{
+ return m_applicationName;
+}
+
+// host
+
+QSize Settings::hostDisplaySize()
+{
+ return instance()->value("host/displaySize", QSize()).toSize();
+}
+
+int Settings::hostMaximumPlayers()
+{
+ return instance()->value("host/maximumPlayers", defaultHostMaximumPlayers).toInt();
+}
+
+// match
+
+int Settings::matchTime()
+{
+ return instance()->value("match/time", defaultMatchTime).toInt();
+}
+
+int Settings::matchChickenNumber()
+{
+ return instance()->value("match/chickenNumber", defaultMatchChickenNumber).toInt();
+}
+
+int Settings::matchChickenMoveInterval()
+{
+ return instance()->value("match/chickenMoveInterval",
+ defaultMatchChickenMoveInterval).toInt();
+}
+
+int Settings::matchChickenChangeStepsInterval()
+{
+ return instance()->value("match/chickenChangeStepsInterval",
+ defaultMatchChickenChangeStepsInterval).toInt();
+}
+
+int Settings::matchCharacterMoveInterval()
+{
+ return instance()->value("match/chickenCharacterMoveInterval",
+ defaultMatchCharacterMoveInterval).toInt();
+}
+
+int Settings::matchCharacterChangeStepsInterval()
+{
+ return instance()->value("match/chickenCharacterStepsInterval",
+ defaultMatchCharacterChangeStepsInterval).toInt();
+}
+
+// battlefield
+
+QSize Settings::battlefieldSize()
+{
+ return instance()->value("battlefield/size", defaultBattlefieldSize).toSize();
+}
+
+int Settings::battlefieldCellSize()
+{
+ return instance()->value("battlefield/cellSize", defaultBattlefieldCellSize).toInt();
+}
+
+QPoint Settings::battlefieldStartPoint()
+{
+ return instance()->value("battlefield/startPoint", defaultBattlefieldStartPoint).toPoint();
+}
+
+// local network
+
+int Settings::lanTcpPort()
+{
+ return instance()->value("lan/tcpPort", defaultLanTcpPort).toInt();
+}
+
+void Settings::setLanTcpPort(const QString port)
+{
+ instance()->setValue("lan/tcpPort", port);
+}
+
+int Settings::lanUdpPort()
+{
+ return instance()->value("lan/udpPort", defaultLanUdpPort).toInt();
+}
+
+void Settings::setLanUdpPort(const QString port)
+{
+ instance()->setValue("lan/udpPort", port);
+}
+
+int Settings::lanUdpDiscoveryTimeout()
+{
+ return instance()->value("lan/UdpDiscoveryTimeout", defaultLanUdpDiscoveryTimeout).toInt();
+}
+
+int Settings::lanUdpDiscoveryClientAttempts()
+{
+ return instance()->value("lan/UdpDiscoveryClientAttempts",
+ defaultLanUdpDiscoveryClientAttempts).toInt();
+}
+
+int Settings::lanUdpDiscoveryHostAttempts()
+{
+ return instance()->value("lan/UdpDiscoveryHostAttempts",
+ defaultLanUdpDiscoveryHostAttempts).toInt();
+}
+
+// bluetooth
+
+QString Settings::bluetoothHostAddress()
+{
+ return instance()->value("bluetooth/hostAddress", QString()).toString();
+}
+
+void Settings::setBluetoothHostAddress(const QString &address)
+{
+ instance()->setValue("bluetooth/hostAddress", address);
+}
+
+QString Settings::bluetoothHostName()
+{
+ return instance()->value("bluetooth/hostName", QString()).toString();
+}
+
+void Settings::setBluetoothHostName(const QString &name)
+{
+ instance()->setValue("bluetooth/hostName", name);
+}
+
+bool Settings::exists()
+{
+ QFileInfo settingsFileInfo(instance()->fileName());
+
+ return settingsFileInfo.exists();
+}
+
+void Settings::reset()
+{
+ Settings *settings = instance();
+
+ settings->beginGroup("host");
+ settings->setValue("displaySize", defaultHostDisplaySize);
+ settings->setValue("hostMaximumPlayers", defaultHostMaximumPlayers);
+ settings->endGroup();
+
+ settings->beginGroup("match");
+ settings->setValue("time", defaultMatchTime);
+ settings->setValue("chickenNumber", defaultMatchChickenNumber);
+ settings->setValue("chickenMoveInterval", defaultMatchChickenMoveInterval);
+ settings->setValue("chickenChangeStepsInterval", defaultMatchChickenChangeStepsInterval);
+ settings->setValue("characterMoveInterval", defaultMatchCharacterMoveInterval);
+ settings->setValue("characterChangeStepsInterval", defaultMatchCharacterChangeStepsInterval);
+ settings->endGroup();
+
+ settings->beginGroup("battlefield");
+ settings->setValue("size", defaultBattlefieldSize);
+ settings->setValue("cellSize", defaultBattlefieldCellSize);
+ settings->setValue("startPoint", defaultBattlefieldStartPoint);
+ settings->endGroup();
+
+ settings->beginGroup("lan");
+ settings->setValue("tcpPort", defaultLanTcpPort);
+ settings->setValue("udpPort", defaultLanUdpPort);
+ settings->setValue("udpDiscoveryTimeout", defaultLanUdpDiscoveryTimeout);
+ settings->setValue("udpDiscoveryClientAttempts", defaultLanUdpDiscoveryClientAttempts);
+ settings->setValue("udpDiscoveryHostAttempts", defaultLanUdpDiscoveryHostAttempts);
+ settings->endGroup();
+
+ settings->beginGroup("bluetooth");
+ settings->setValue("hostAddress", defaultBluetoothHostAddress);
+ settings->setValue("hostName", defaultBluetoothHostName);
+ settings->endGroup();
+
+ update();
+}
diff --git a/chicken-wranglers/src/main/settings.h b/chicken-wranglers/src/main/settings.h
new file mode 100644
index 0000000..1c967f3
--- /dev/null
+++ b/chicken-wranglers/src/main/settings.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+#ifndef SETTINGS_H
+#define SETTINGS_H
+
+#include <QtCore/QObject>
+#include <QtCore/QSettings>
+#include <QtCore/QSize>
+#include <QtCore/QPoint>
+
+class Settings : public QSettings
+{
+ Q_OBJECT
+
+public:
+ static Settings *instance();
+
+ static void update();
+ static bool exists();
+ static void reset();
+
+ static QString organizationName();
+ static QString organizationDomain();
+ static QString applicationName();
+
+public slots:
+ // host
+ static QSize hostDisplaySize();
+ static int hostMaximumPlayers();
+
+ // match
+ static int matchTime();
+ static int matchChickenNumber();
+ static int matchChickenMoveInterval();
+ static int matchChickenChangeStepsInterval();
+ static int matchCharacterMoveInterval();
+ static int matchCharacterChangeStepsInterval();
+
+ // battlefield
+ static QSize battlefieldSize();
+ static int battlefieldCellSize();
+ static QPoint battlefieldStartPoint();
+
+ // local network
+ static int lanTcpPort();
+ static void setLanTcpPort(const QString port);
+ static int lanUdpPort();
+ static void setLanUdpPort(const QString port);
+ static int lanUdpDiscoveryTimeout();
+ static int lanUdpDiscoveryClientAttempts();
+ static int lanUdpDiscoveryHostAttempts();
+
+ // bluetooth
+ static QString bluetoothHostAddress();
+ static void setBluetoothHostAddress(const QString &address);
+
+ static QString bluetoothHostName();
+ static void setBluetoothHostName(const QString &name);
+
+private:
+ explicit Settings(QObject *parent = 0);
+
+ static const QString m_organizationName;
+ static const QString m_organizationDomain;
+ static const QString m_applicationName;
+};
+
+#endif
diff --git a/chicken-wranglers/src/models/bluetoothdevice.cpp b/chicken-wranglers/src/models/bluetoothdevice.cpp
new file mode 100644
index 0000000..2d72086
--- /dev/null
+++ b/chicken-wranglers/src/models/bluetoothdevice.cpp
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+#include "bluetoothdevice.h"
+
+BluetoothDevice::BluetoothDevice(QObject *parent)
+ : QObject(parent)
+{
+}
+
+BluetoothDevice::BluetoothDevice(const BluetoothDevice &device)
+ : QObject(device.parent())
+{
+ operator=(device);
+}
+
+bool BluetoothDevice::operator==(const BluetoothDevice &device) const
+{
+ return (m_address == device.address());
+}
+
+BluetoothDevice &BluetoothDevice::operator=(const BluetoothDevice &device)
+{
+ m_name = device.m_name;
+ m_address = device.m_address;
+ m_paired = device.m_paired;
+ m_category = device.m_category;
+
+ return *this;
+}
+
+void BluetoothDevice::setName(const QString &name)
+{
+ m_name = name;
+}
+
+QString BluetoothDevice::name() const
+{
+ return m_name;
+}
+
+void BluetoothDevice::setAddress(const QString &address)
+{
+ m_address = address;
+}
+
+QString BluetoothDevice::address() const
+{
+ return m_address;
+}
+
+void BluetoothDevice::setPaired(const bool paired)
+{
+ m_paired = paired;
+}
+
+bool BluetoothDevice::paired() const
+{
+ return m_paired;
+}
+
+void BluetoothDevice::setCategory(const quint8 category)
+{
+ m_category = category;
+}
+
+quint8 BluetoothDevice::category() const
+{
+ return m_category;
+}
+
diff --git a/chicken-wranglers/src/models/bluetoothdevice.h b/chicken-wranglers/src/models/bluetoothdevice.h
new file mode 100644
index 0000000..4bb7a36
--- /dev/null
+++ b/chicken-wranglers/src/models/bluetoothdevice.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+#ifndef BLUETOOTHDEVICE_H
+#define BLUETOOTHDEVICE_H
+
+#include <QtCore/QObject>
+#include <QtCore/QString>
+
+class BluetoothDevice : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QString name READ name WRITE setName)
+ Q_PROPERTY(QString address READ address WRITE setAddress)
+ Q_PROPERTY(bool paired READ paired WRITE setPaired)
+ Q_PROPERTY(quint8 category READ category WRITE setCategory)
+
+public:
+ BluetoothDevice(QObject *parent = 0);
+ BluetoothDevice(const BluetoothDevice &device);
+
+ bool operator==(const BluetoothDevice &device) const;
+ BluetoothDevice &operator=(const BluetoothDevice &device);
+
+ enum Category {
+ Other,
+ Computer,
+ Phone
+ };
+
+ void setName(const QString &name);
+ QString name() const;
+
+ void setAddress(const QString &address);
+ QString address() const;
+
+ void setPaired(const bool paired);
+ bool paired() const;
+
+ void setCategory(const quint8 category);
+ quint8 category() const;
+
+private:
+ QString m_name;
+ QString m_address;
+ bool m_paired;
+ quint8 m_category;
+};
+
+#endif
diff --git a/chicken-wranglers/src/models/charactermodel.cpp b/chicken-wranglers/src/models/charactermodel.cpp
new file mode 100644
index 0000000..c8f0f53
--- /dev/null
+++ b/chicken-wranglers/src/models/charactermodel.cpp
@@ -0,0 +1,217 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+#include "charactermodel.h"
+
+#include "global.h"
+
+#include <QtCore/QDir>
+#include <QtCore/QUrl>
+#include <QtDeclarative>
+#include <QtGui/QPixmap>
+
+CharacterModel::CharacterModel(QObject *parent)
+ : QObject(parent)
+{
+}
+
+CharacterModel::CharacterModel(const QFileInfo &characterPath, QObject *parent)
+ : QObject(parent), m_path(characterPath.absoluteFilePath()), m_available(true)
+{
+ // TODO: Maybe we need to check it for a valid directory path
+ m_characterName = characterPath.baseName();
+}
+
+CharacterModel::CharacterModel(const QString &characterName, QObject *parent)
+ : QObject(parent), m_characterName(characterName),
+ m_path(QFileInfo(basePath() + characterName).absoluteFilePath())
+{
+}
+
+QString CharacterModel::path() const
+{
+ return QUrl::fromLocalFile(m_path.toString()).toString();
+}
+
+QString CharacterModel::basePath()
+{
+ return Global::rootDirectory().absoluteFilePath() + "/characters/";
+}
+
+bool CharacterModel::isValid() const
+{
+ QString iconPath = m_path.toString(QUrl::RemoveScheme) + "/select_character.png";
+
+ if (QPixmap(iconPath).isNull())
+ return false;
+
+ return true;
+}
+
+void CharacterModel::setAvailable(bool available)
+{
+ if (m_available == available)
+ return;
+
+ m_available = available;
+
+ emit isAvailableChanged(available);
+}
+
+CharacterListModel::CharacterListModel(QObject *parent)
+ : QAbstractListModel(parent), m_selectedIndex(-1)
+{
+ QHash<int, QByteArray> roles;
+
+ roles[PathRole] = "path";
+ roles[IsAvailableRole] = "isAvailable";
+
+ setRoleNames(roles);
+
+ qmlRegisterType<CharacterModel>("game.types", 1, 0, "CharacterModel");
+}
+
+bool CharacterListModel::load()
+{
+ QDir characterDir = QDir(CharacterModel::basePath());
+ if (!characterDir.exists())
+ return false;
+
+ QFlags<QDir::Filter> flags = QDir::Dirs | QDir::NoDotAndDotDot;
+ QFileInfoList entries = characterDir.entryInfoList(flags, QDir::Time);
+
+ foreach(QFileInfo entry, entries) {
+ CharacterModel *character = new CharacterModel(entry);
+
+ if (character->isValid())
+ addCharacter(character);
+ else
+ delete character;
+ }
+
+ return true;
+}
+
+void CharacterListModel::addCharacter(CharacterModel *character)
+{
+ beginInsertRows(QModelIndex(), rowCount(), rowCount());
+ m_characters << character;
+ endInsertRows();
+
+ connect(character, SIGNAL(isAvailableChanged(bool)),
+ this, SLOT(onIsAvailableChanged(bool)));
+}
+
+int CharacterListModel::rowCount(const QModelIndex &parent) const
+{
+ Q_UNUSED(parent);
+
+ return m_characters.count();
+}
+
+QVariant CharacterListModel::data(const QModelIndex &index, int role) const
+{
+ if (index.row() < 0 || index.row() >= m_characters.count())
+ return QVariant();
+
+ CharacterModel *character = m_characters[index.row()];
+
+ if (role == PathRole)
+ return character->path();
+ if (role == IsAvailableRole)
+ return character->isAvailable();
+
+ return QVariant();
+}
+
+void CharacterListModel::setSelectedIndex(int selectedIndex)
+{
+ if (selectedIndex >= m_characters.count())
+ return;
+
+ m_selectedIndex = selectedIndex;
+
+ selectedIndexChanged();
+}
+
+CharacterModel *CharacterListModel::get(int index) const
+{
+ if (index < 0 || index >= m_characters.count())
+ return 0;
+
+ return m_characters.at(index);
+}
+
+CharacterModel *CharacterListModel::selected() const
+{
+ if (m_selectedIndex < 0 || m_selectedIndex >= m_characters.count())
+ return 0;
+
+ return m_characters.at(m_selectedIndex);
+}
+
+QStringList CharacterListModel::characterNameList()
+{
+ QDir characterDir = QDir(CharacterModel::basePath());
+ if (!characterDir.exists())
+ return QStringList();
+
+ QFlags<QDir::Filter> flags = QDir::Dirs | QDir::NoDotAndDotDot;
+ QFileInfoList entries = characterDir.entryInfoList(flags, QDir::Time);
+
+ QStringList nameList;
+
+ foreach(QFileInfo entry, entries)
+ nameList.append(entry.baseName());
+
+ return nameList;
+}
+
+void CharacterListModel::onIsAvailableChanged(bool available)
+{
+ Q_UNUSED(available)
+
+ CharacterModel *model = qobject_cast<CharacterModel *>(sender());
+
+ int characterIndex = m_characters.indexOf(model);
+
+ dataChanged(index(characterIndex), index(characterIndex));
+}
diff --git a/chicken-wranglers/src/models/charactermodel.h b/chicken-wranglers/src/models/charactermodel.h
new file mode 100644
index 0000000..b3e27f7
--- /dev/null
+++ b/chicken-wranglers/src/models/charactermodel.h
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+#ifndef CHARACTERMODEL_H
+#define CHARACTERMODEL_H
+
+#include <QtCore/QAbstractListModel>
+#include <QtCore/QFileInfo>
+#include <QtCore/QUrl>
+
+class CharacterModel : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QString path READ path NOTIFY pathChanged)
+ Q_PROPERTY(bool isAvailable READ isAvailable NOTIFY isAvailableChanged)
+
+public:
+ CharacterModel(QObject *parent = 0);
+ CharacterModel(const QFileInfo &characterPath, QObject *parent = 0);
+ CharacterModel(const QString &characterName, QObject *parent = 0);
+
+ bool isValid() const;
+
+ QString path() const;
+ QString name() const { return m_characterName; }
+
+ bool isAvailable() const { return m_available; }
+ void setAvailable(bool available);
+
+ static QString basePath();
+
+signals:
+ void pathChanged(const QString &path);
+ void isAvailableChanged(bool available);
+
+private:
+ QString m_characterName;
+ QUrl m_path;
+ bool m_available;
+};
+
+class CharacterListModel : public QAbstractListModel
+{
+ Q_OBJECT
+
+ Q_PROPERTY(int selectedIndex READ selectedIndex WRITE setSelectedIndex NOTIFY selectedIndexChanged)
+
+public:
+ enum CharacterRole {
+ PathRole = Qt::UserRole + 1,
+ IsAvailableRole
+ };
+
+ explicit CharacterListModel(QObject *parent = 0);
+
+ bool load();
+ void addCharacter(CharacterModel *character);
+
+ int rowCount(const QModelIndex &parent = QModelIndex()) const;
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+
+ int selectedIndex() const { return m_selectedIndex; }
+ void setSelectedIndex(int selectedIndex);
+
+ static QStringList characterNameList();
+
+ Q_INVOKABLE CharacterModel *get(int index) const;
+ Q_INVOKABLE CharacterModel *selected() const;
+
+signals:
+ void selectedIndexChanged();
+
+private slots:
+ void onIsAvailableChanged(bool available);
+
+private:
+ QList<CharacterModel *> m_characters;
+ int m_selectedIndex;
+};
+
+#endif
diff --git a/chicken-wranglers/src/models/connectivitylistmodel.cpp b/chicken-wranglers/src/models/connectivitylistmodel.cpp
new file mode 100644
index 0000000..46c4a19
--- /dev/null
+++ b/chicken-wranglers/src/models/connectivitylistmodel.cpp
@@ -0,0 +1,151 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+#include "connectivitylistmodel.h"
+
+#include "settings.h"
+
+ConnectivityListModel::ConnectivityListModel(QObject *parent)
+ : QAbstractListModel(parent), m_selectedIndex(-1)
+{
+ QHash<int, QByteArray> roles;
+
+ roles[NameRole] = "name";
+ roles[AddressRole] = "address";
+
+ setRoleNames(roles);
+}
+
+void ConnectivityListModel::addDevice(const BluetoothDevice &device)
+{
+ for (int i = 0; i < m_devices.count(); i++) {
+ if (m_devices[i] == device) {
+ if ((m_devices[i].name() == m_devices[i].address())
+ && device.name() != device.address()) {
+
+ m_devices[i].setName(device.name());
+ emit dataChanged(index(i), index(i));
+ }
+
+ return;
+ }
+ }
+
+ beginInsertRows(QModelIndex(), rowCount(), rowCount());
+ m_devices << device;
+ endInsertRows();
+}
+
+int ConnectivityListModel::rowCount(const QModelIndex &parent) const
+{
+ Q_UNUSED(parent);
+
+ return m_devices.count();
+}
+
+QVariant ConnectivityListModel::data(const QModelIndex &index, int role) const
+{
+ if (index.row() < 0 || index.row() > m_devices.count())
+ return QVariant();
+
+ const BluetoothDevice &device = m_devices[index.row()];
+
+ if (role == NameRole)
+ return device.name();
+ else if (role == AddressRole)
+ return device.address();
+
+ return QVariant();
+}
+
+void ConnectivityListModel::setSelectedIndex(int selectedIndex)
+{
+ if (selectedIndex >= m_devices.count())
+ return;
+
+ m_selectedIndex = selectedIndex;
+
+ emit selectedIndexChanged();
+
+ emit selectedDevice(m_devices[m_selectedIndex].address());
+}
+
+void ConnectivityListModel::clear()
+{
+ if (!rowCount())
+ return;
+
+ beginRemoveRows(QModelIndex(), 0, rowCount() - 1);
+ m_devices.clear();
+ endRemoveRows();
+}
+
+void ConnectivityListModel::storeLastHostDevice()
+{
+ if (m_selectedIndex == -1 || m_selectedIndex >= m_devices.count())
+ return;
+
+ BluetoothDevice device = m_devices[m_selectedIndex];
+ Settings::setBluetoothHostAddress(device.address());
+ Settings::setBluetoothHostName(device.name());
+}
+
+void ConnectivityListModel::loadLastHostDevice()
+{
+ BluetoothDevice device;
+
+ QString address = Settings::bluetoothHostAddress();
+ QString name = Settings::bluetoothHostName();
+
+ if (address == "00:00:00:00:00:00" || address.isEmpty())
+ return;
+
+ device.setAddress(address);
+ if (!name.isEmpty())
+ device.setName(name);
+ else
+ device.setName(address);
+
+ addDevice(device);
+
+ m_selectedIndex = m_devices.indexOf(device);
+ emit selectedIndexChanged();
+}
diff --git a/chicken-wranglers/src/models/connectivitylistmodel.h b/chicken-wranglers/src/models/connectivitylistmodel.h
new file mode 100644
index 0000000..a81d693
--- /dev/null
+++ b/chicken-wranglers/src/models/connectivitylistmodel.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+#ifndef CONNECTIVITYLISTMODEL_H
+#define CONNECTIVITYLISTMODEL_H
+
+#include "bluetoothdevice.h"
+
+#include <QtCore/QAbstractListModel>
+
+class ConnectivityListModel : public QAbstractListModel
+{
+ Q_OBJECT
+
+ Q_PROPERTY(int selectedIndex READ selectedIndex WRITE setSelectedIndex NOTIFY selectedIndexChanged)
+
+public:
+ enum DeviceRole {
+ NameRole = Qt::UserRole + 1,
+ AddressRole
+ };
+
+ ConnectivityListModel(QObject *parent = 0);
+
+ int rowCount(const QModelIndex &parent = QModelIndex()) const;
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+
+ int selectedIndex() const { return m_selectedIndex; }
+ void setSelectedIndex(int selectedIndex);
+
+ void storeLastHostDevice();
+ void loadLastHostDevice();
+
+public slots:
+ void addDevice(const BluetoothDevice &device);
+ void clear();
+
+signals:
+ void selectedDevice(const QString &deviceAddress);
+ void selectedIndexChanged();
+
+private:
+ QList<BluetoothDevice> m_devices;
+ int m_selectedIndex;
+};
+
+#endif
diff --git a/chicken-wranglers/src/models/models.pri b/chicken-wranglers/src/models/models.pri
new file mode 100644
index 0000000..9859eff
--- /dev/null
+++ b/chicken-wranglers/src/models/models.pri
@@ -0,0 +1,15 @@
+QT += declarative
+
+PATH = $$PWD
+
+HEADERS += \
+ $$PATH/charactermodel.h \
+ $$PATH/playermodel.h \
+ $$PATH/bluetoothdevice.h \
+ $$PATH/connectivitylistmodel.h
+
+SOURCES += \
+ $$PATH/charactermodel.cpp \
+ $$PATH/playermodel.cpp \
+ $$PATH/bluetoothdevice.cpp \
+ $$PATH/connectivitylistmodel.cpp
diff --git a/chicken-wranglers/src/models/playermodel.cpp b/chicken-wranglers/src/models/playermodel.cpp
new file mode 100644
index 0000000..f1ccab0
--- /dev/null
+++ b/chicken-wranglers/src/models/playermodel.cpp
@@ -0,0 +1,466 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+#include "playermodel.h"
+
+#include "charactermodel.h"
+#include "networkconnection.h"
+
+#include <QtDeclarative>
+
+PlayerModel::PlayerModel(QObject *parent)
+ : QObject(parent)
+{
+}
+
+PlayerModel::PlayerModel(NetworkConnection *connection, QObject *parent)
+ : QObject(parent), m_character(0), m_connection(connection),
+ m_status(NoCharacter), m_direction(Global::DirectionStop),
+ m_isLeader(false), m_score(0)
+{
+ connect(connection, SIGNAL(received(NetworkMessage)),
+ this, SLOT(onNetworkMessageReceived(NetworkMessage)));
+}
+
+PlayerModel::~PlayerModel()
+{
+ if (!characterName().isEmpty())
+ emit characterReleased(characterName());
+}
+
+QString PlayerModel::characterPath() const
+{
+ if (m_character)
+ return m_character->path();
+ else
+ return QString();
+}
+
+QString PlayerModel::characterName() const
+{
+ if (m_character)
+ return m_character->name();
+ else
+ return QString();
+}
+
+bool PlayerModel::setCharacter(const QString &characterName)
+{
+ PlayerListModel *listModel = qobject_cast<PlayerListModel *>(parent());
+ if (!listModel) {
+ qWarning() << "Invalid PlayerListModel";
+ return false;
+ }
+
+ if (!listModel->availableCharacters().contains(characterName))
+ return false;
+
+ // TODO: Check if it is safe to set a new character when
+ // the player has already selected one.
+ if (m_character && m_character->name() == characterName) {
+ qWarning() << "Player has already an associated character";
+ return false;
+ }
+
+ m_character = new CharacterModel(characterName, this);
+ m_status = Ready;
+
+ emit characterPathChanged();
+ emit characterSelected(characterName);
+
+ return true;
+}
+
+bool PlayerModel::unsetCharacter(const QString &characterName)
+{
+ if (!m_character) {
+ qWarning() << "Player has no associated character";
+ return false;
+ }
+
+ m_character->deleteLater();
+ m_character = 0;
+
+ m_status = NoCharacter;
+
+ emit characterPathChanged();
+ emit characterReleased(characterName);
+
+ return true;
+}
+
+void PlayerModel::setLeader(bool isLeader)
+{
+ if (m_isLeader == isLeader)
+ return;
+
+ m_isLeader = isLeader;
+
+ notifyPlayerLeader(m_isLeader);
+}
+
+void PlayerModel::setScore(int score)
+{
+ if (m_score == score)
+ return;
+
+ m_score = score;
+
+ emit scoreChanged();
+}
+
+void PlayerModel::reset()
+{
+ // TODO: Check what we need to cleanup at this point
+ m_score = 0;
+ m_direction = Global::DirectionStop;
+}
+
+void PlayerModel::setDirection(Global::Direction direction)
+{
+ if (m_direction == direction)
+ return;
+
+ m_direction = direction;
+
+ emit directionChanged();
+}
+
+void PlayerModel::notifyCharacterAvailableList(const QStringList &availableCharacters)
+{
+ QString availableCharactersString = availableCharacters.join("|");
+
+ NetworkMessage message(CW::CharacterMessageType, CW::CharacterAvailableList);
+ message.setData(availableCharactersString.toLatin1());
+
+ m_connection->send(message);
+}
+
+void PlayerModel::notifyCharacterIsAvailable(const QString &characterName, bool available)
+{
+ QByteArray data;
+ data.append(characterName);
+ data.append("|");
+
+ if (available)
+ data.append("1");
+ else
+ data.append("0");
+
+ NetworkMessage message(CW::CharacterMessageType, CW::CharacterIsAvailable);
+ message.setData(data);
+
+ m_connection->send(message);
+}
+
+void PlayerModel::notifyPlayerLeader(bool isLeader)
+{
+ QByteArray data;
+
+ if (isLeader)
+ data.append("1");
+ else
+ data.append("0");
+
+ NetworkMessage message(CW::PlayerInfoMessageType, CW::PlayerInfoLeader);
+ message.setData(data);
+
+ m_connection->send(message);
+}
+
+void PlayerModel::onNetworkMessageReceived(const NetworkMessage &message)
+{
+ switch (message.type()) {
+ case CW::CharacterMessageType:
+ handleCharacterMessage(message);
+ break;
+ case CW::PlayerControlMessageType:
+ handlePlayerControlMessage(message);
+ break;
+ default:
+ qWarning("Invalid network message type");
+ }
+}
+
+void PlayerModel::handleCharacterMessage(const NetworkMessage &message)
+{
+ switch (message.content()) {
+ case CW::CharacterSelected:
+ setCharacter(QString(message.data()));
+ break;
+
+ case CW::CharacterReleased:
+ unsetCharacter(characterName());
+ break;
+
+ default:
+ qWarning("Invalid character message");
+ }
+}
+
+// FIXME: Move the two static functions below to a better place
+static Global::Direction playerControlToDirection(CW::PlayerControl control)
+{
+ QMap<CW::PlayerControl, Global::Direction> direction;
+
+ direction[CW::PlayerControlUp] = Global::DirectionUp;
+ direction[CW::PlayerControlDown] = Global::DirectionDown;
+ direction[CW::PlayerControlRight] = Global::DirectionRight;
+ direction[CW::PlayerControlLeft] = Global::DirectionLeft;
+ direction[CW::PlayerControlStop] = Global::DirectionStop;
+
+ return direction[control];
+}
+
+static Global::LaserDirection playerControlToLaserDirection(CW::PlayerControl control)
+{
+ QMap<CW::PlayerControl, Global::LaserDirection> laserDirection;
+
+ laserDirection[CW::PlayerControlLaserUp] = Global::LaserUp;
+ laserDirection[CW::PlayerControlLaserDown] = Global::LaserDown;
+ laserDirection[CW::PlayerControlLaserRight] = Global::LaserRight;
+ laserDirection[CW::PlayerControlLaserLeft] = Global::LaserLeft;
+
+ return laserDirection[control];
+}
+
+void PlayerModel::handlePlayerControlMessage(const NetworkMessage &message)
+{
+ CW::PlayerControl control = static_cast<CW::PlayerControl>(message.content());
+
+ switch (control) {
+ case CW::PlayerControlLaserUp:
+ case CW::PlayerControlLaserDown:
+ case CW::PlayerControlLaserLeft:
+ case CW::PlayerControlLaserRight:
+ requestLaserToggle(playerControlToLaserDirection(control));
+ break;
+ case CW::PlayerControlUp:
+ case CW::PlayerControlDown:
+ case CW::PlayerControlLeft:
+ case CW::PlayerControlRight:
+ case CW::PlayerControlStop:
+ setDirection(playerControlToDirection(control));
+ break;
+ default:
+ qWarning("Invalid player control message");
+ }
+}
+
+void PlayerModel::requestLaserToggle(Global::LaserDirection laserDirection)
+{
+ emit laserToggleRequested(laserDirection);
+}
+
+PlayerListModel::PlayerListModel(QObject *parent)
+ : QAbstractListModel(parent), m_playersReady(false)
+{
+ QHash<int, QByteArray> roles;
+
+ roles[StatusRole] = "status";
+ roles[CharacterPathRole] = "characterPath";
+
+ setRoleNames(roles);
+
+ qmlRegisterType<PlayerModel>("game.types", 1, 0, "PlayerModel");
+
+ m_availableCharacters = CharacterListModel::characterNameList();
+}
+
+void PlayerListModel::newPlayer(NetworkConnection *connection)
+{
+ PlayerModel *player = new PlayerModel(connection, this);
+
+ beginInsertRows(QModelIndex(), rowCount(), rowCount());
+ m_players << player;
+ endInsertRows();
+
+ connect(player, SIGNAL(characterPathChanged()),
+ this, SLOT(onCharacterPathChanged()));
+ connect(player, SIGNAL(characterSelected(QString)),
+ this, SLOT(onCharacterSelected(QString)));
+ connect(player, SIGNAL(characterReleased(QString)),
+ this, SLOT(onCharacterReleased(QString)));
+
+ // A new player has joined, so he is not yet until he
+ // has chosen a character.
+ setPlayersReady(false);
+
+ // Check if player is the first one connected, which
+ // makes him the leader. This enables some special
+ // abilities for his client, such as start/end a match.
+ if (m_players.size() == 1)
+ player->setLeader(true);
+
+ player->notifyCharacterAvailableList(m_availableCharacters);
+}
+
+void PlayerListModel::removePlayer(NetworkConnection *connection)
+{
+ foreach (PlayerModel *model, m_players) {
+ if (connection == model->connection()) {
+ int index = m_players.indexOf(model);
+
+ beginRemoveRows(QModelIndex(), index, index);
+ m_players.removeAt(index);
+ endRemoveRows();
+
+ model->deleteLater();
+ break;
+ }
+ }
+
+ checkPlayersReady();
+}
+
+int PlayerListModel::rowCount(const QModelIndex &parent) const
+{
+ Q_UNUSED(parent);
+
+ return m_players.count();
+}
+
+QVariant PlayerListModel::data(const QModelIndex &index, int role) const
+{
+ if (index.row() < 0 || index.row() >= m_players.count())
+ return QVariant();
+
+ PlayerModel *player = m_players[index.row()];
+
+ if (role == StatusRole)
+ return player->status();
+ if (role == CharacterPathRole)
+ return player->characterPath();
+
+ return QVariant();
+}
+
+void PlayerListModel::reset()
+{
+ foreach (PlayerModel *player, m_players)
+ player->reset();
+}
+
+void PlayerListModel::setPlayersReady(bool playersReady)
+{
+ if (m_playersReady == playersReady)
+ return;
+
+ m_playersReady = playersReady;
+
+ emit playersReadyChanged();
+}
+
+void PlayerListModel::checkPlayersReady()
+{
+ if (m_players.size() == 0) {
+ setPlayersReady(false);
+ return;
+ }
+
+ foreach(PlayerModel *player, m_players) {
+ if (player->status() != PlayerModel::Ready) {
+ setPlayersReady(false);
+ return;
+ }
+ }
+
+ setPlayersReady(true);
+}
+
+PlayerModel *PlayerListModel::get(int index) const
+{
+ if (index < 0 || index >= m_players.count())
+ return 0;
+
+ return m_players.at(index);
+}
+
+void PlayerListModel::onCharacterPathChanged()
+{
+ PlayerModel *playerModel = qobject_cast<PlayerModel *>(sender());
+
+ int playerModelIndex = m_players.indexOf(playerModel);
+
+ emit dataChanged(index(playerModelIndex), index(playerModelIndex));
+}
+
+void PlayerListModel::onCharacterSelected(const QString &characterName)
+{
+ m_availableCharacters.removeAll(characterName);
+
+ PlayerModel *senderModel = qobject_cast<PlayerModel *>(sender());
+
+ foreach (PlayerModel *model, m_players)
+ if (senderModel != model)
+ model->notifyCharacterIsAvailable(characterName, false);
+
+ checkPlayersReady();
+}
+
+void PlayerListModel::onCharacterReleased(const QString &characterName)
+{
+ if (m_availableCharacters.contains(characterName))
+ return;
+
+ m_availableCharacters.append(characterName);
+
+ foreach (PlayerModel *model, m_players)
+ model->notifyCharacterIsAvailable(characterName, true);
+
+ checkPlayersReady();
+}
+
+void PlayerListModel::notifyMatchReady()
+{
+ NetworkMessage message(CW::MatchMessageType, CW::MatchReady);
+
+ foreach (PlayerModel *model, m_players)
+ model->connection()->send(message);
+}
+
+void PlayerListModel::notifyMatchFinished()
+{
+ NetworkMessage message(CW::MatchMessageType, CW::MatchFinished);
+
+ foreach (PlayerModel *model, m_players)
+ model->connection()->send(message);
+}
diff --git a/chicken-wranglers/src/models/playermodel.h b/chicken-wranglers/src/models/playermodel.h
new file mode 100644
index 0000000..2bd1d34
--- /dev/null
+++ b/chicken-wranglers/src/models/playermodel.h
@@ -0,0 +1,175 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+#ifndef PLAYERMODEL_H
+#define PLAYERMODEL_H
+
+#include "global.h"
+
+#include "networkmessage.h"
+
+#include <QtCore/QAbstractListModel>
+#include <QtCore/QStringList>
+#include <QtNetwork/QHostAddress>
+
+class CharacterModel;
+class NetworkConnection;
+
+class PlayerModel : public QObject
+{
+ Q_OBJECT
+ Q_ENUMS(Status)
+
+ Q_PROPERTY(QString characterPath READ characterPath NOTIFY characterPathChanged)
+ Q_PROPERTY(QString direction READ directionString NOTIFY directionChanged)
+ Q_PROPERTY(int score READ score NOTIFY scoreChanged)
+
+public:
+ PlayerModel(QObject *parent = 0);
+ PlayerModel(NetworkConnection *connection, QObject *parent = 0);
+ ~PlayerModel();
+
+ enum Status {
+ NoCharacter,
+ Ready,
+ Playing
+ };
+
+ QString characterPath() const;
+ Status status() const { return m_status; }
+ NetworkConnection *connection() const { return m_connection; }
+
+ bool setCharacter(const QString &characterName);
+ bool unsetCharacter(const QString &characterName);
+
+ void setLeader(bool isLeader);
+ bool isLeader() const { return m_isLeader; }
+
+ void setScore(int score);
+ int score() const { return m_score; }
+
+ void reset();
+
+ QString directionString() const { return Global::directionString(m_direction); }
+ Global::Direction direction() const { return m_direction; }
+ void setDirection(Global::Direction direction);
+
+ void notifyCharacterAvailableList(const QStringList &availableCharacters);
+ void notifyCharacterIsAvailable(const QString &characterName, bool available);
+ void notifyPlayerLeader(bool isLeader);
+
+ QString characterName() const;
+
+signals:
+ void characterPathChanged();
+ void directionChanged();
+ void scoreChanged();
+ void characterSelected(const QString &characterName);
+ void characterReleased(const QString &characterName);
+ void laserToggleRequested(Global::LaserDirection laserDirection);
+
+private slots:
+ void onNetworkMessageReceived(const NetworkMessage &message);
+
+private:
+ void handleCharacterMessage(const NetworkMessage &message);
+ void handlePlayerControlMessage(const NetworkMessage &message);
+
+ void requestLaserToggle(Global::LaserDirection laserDirection);
+
+ CharacterModel *m_character;
+ NetworkConnection *m_connection;
+ Status m_status;
+ Global::Direction m_direction;
+ bool m_isLeader;
+ int m_score;
+};
+
+class PlayerListModel : public QAbstractListModel
+{
+ Q_OBJECT
+
+ Q_PROPERTY(bool playersReady READ playersReady NOTIFY playersReadyChanged)
+
+public:
+ enum PlayerRole {
+ StatusRole = Qt::UserRole + 1,
+ CharacterPathRole
+ };
+
+ explicit PlayerListModel(QObject *parent = 0);
+
+ void newPlayer(NetworkConnection *connection);
+ void removePlayer(NetworkConnection *connection);
+
+ int rowCount(const QModelIndex &parent = QModelIndex()) const;
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+
+ QStringList availableCharacters() const { return m_availableCharacters; }
+ void reset();
+
+ void notifyMatchReady();
+ void notifyMatchFinished();
+
+ // Used by QML views
+ Q_INVOKABLE PlayerModel *get(int index) const;
+ Q_INVOKABLE int count() const { return rowCount(); }
+
+signals:
+ void playersReadyChanged();
+
+private slots:
+ void onCharacterPathChanged();
+ void onCharacterSelected(const QString &characterName);
+ void onCharacterReleased(const QString &characterName);
+
+private:
+ bool playersReady() const { return m_playersReady; }
+ void setPlayersReady(bool playersReady);
+ void checkPlayersReady();
+
+ QList<PlayerModel *> m_players;
+ QStringList m_availableCharacters;
+ bool m_playersReady;
+};
+
+#endif
diff --git a/chicken-wranglers/src/network/bluetoothconnection.cpp b/chicken-wranglers/src/network/bluetoothconnection.cpp
new file mode 100644
index 0000000..b315fbc
--- /dev/null
+++ b/chicken-wranglers/src/network/bluetoothconnection.cpp
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+#include <QBluetoothAddress>
+#include <QtCore/QByteArray>
+
+#include "bluetoothconnection.h"
+
+BluetoothConnection::BluetoothConnection(QObject *parent, QBluetoothSocket *socket)
+ : NetworkConnection(parent), m_socket(socket)
+{
+ if (m_socket == 0)
+ m_socket = new QBluetoothSocket(QBluetoothSocket::RfcommSocket, this);
+
+ connect(m_socket, SIGNAL(connected()),
+ this, SIGNAL(connected()));
+ connect(m_socket, SIGNAL(disconnected()),
+ this, SIGNAL(disconnected()));
+ connect(m_socket, SIGNAL(error(QBluetoothSocket::SocketError)),
+ this, SIGNAL(error(QBluetoothSocket::SocketError)));
+ connect(m_socket, SIGNAL(readyRead()),
+ this, SLOT(processReadyRead()));
+}
+
+BluetoothConnection::~BluetoothConnection()
+{
+ if (m_socket)
+ m_socket->abort();
+}
+
+void BluetoothConnection::setId(const quint16 &newId)
+{
+ m_id = newId;
+}
+
+quint16 BluetoothConnection::id() const
+{
+ return m_id;
+}
+
+void BluetoothConnection::send(NetworkMessage message)
+{
+ if (m_socket->write(message.byteArray()) == -1)
+ qWarning("Bluetooth Socket write error: %s", m_socket->errorString().toUtf8().constData());
+}
+
+void BluetoothConnection::connectToHost(const QString &address, const quint16 &port)
+{
+ m_socket->connectToService(QBluetoothAddress(address), port);
+}
+
+void BluetoothConnection::disconnectFromHost()
+{
+ m_socket->disconnectFromService();
+}
+
+QAbstractSocket::SocketState BluetoothConnection::state() const
+{
+ return static_cast<QAbstractSocket::SocketState>(m_socket->state());
+}
+
+QAbstractSocket::SocketError BluetoothConnection::error() const
+{
+ return static_cast<QAbstractSocket::SocketError>(m_socket->error());
+}
+
+QString BluetoothConnection::errorString() const
+{
+ return m_socket->errorString();
+}
+
+void BluetoothConnection::processReadyRead()
+{
+ processRead(m_socket);
+}
+
+void BluetoothConnection::close()
+{
+ m_socket.data()->close();
+}
diff --git a/chicken-wranglers/src/network/bluetoothconnection.h b/chicken-wranglers/src/network/bluetoothconnection.h
new file mode 100644
index 0000000..a37c5d8
--- /dev/null
+++ b/chicken-wranglers/src/network/bluetoothconnection.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+#ifndef BLUETOOTHCONNECTION_H
+#define BLUETOOTHCONNECTION_H
+
+#include "networkconnection.h"
+
+#include <QBluetoothSocket>
+#include <QtCore/QObject>
+#include <QtCore/QPointer>
+#include <QtNetwork/QHostAddress>
+
+QTM_USE_NAMESPACE
+
+class BluetoothConnection : public NetworkConnection
+{
+ Q_OBJECT
+
+public:
+ BluetoothConnection(QObject *parent = 0, QBluetoothSocket *socket = 0);
+ ~BluetoothConnection();
+
+ void setId(const quint16 &newId);
+ quint16 id() const;
+
+ void send(NetworkMessage message);
+
+ void connectToHost(const QString &address, const quint16 &port);
+ void disconnectFromHost();
+
+ QAbstractSocket::SocketState state() const;
+ QAbstractSocket::SocketError error() const;
+ QString errorString() const;
+
+ void close();
+
+signals:
+ void connected();
+ void disconnected();
+ void error(QBluetoothSocket::SocketError socketError);
+
+private slots:
+ void processReadyRead();
+
+private:
+ QPointer<QBluetoothSocket> m_socket;
+};
+
+#endif
diff --git a/chicken-wranglers/src/network/bluetoothhandler.cpp b/chicken-wranglers/src/network/bluetoothhandler.cpp
new file mode 100644
index 0000000..feb5244
--- /dev/null
+++ b/chicken-wranglers/src/network/bluetoothhandler.cpp
@@ -0,0 +1,198 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+#include "bluetoothhandler.h"
+
+#include "connectionfactory.h"
+#include "network.h"
+#include "networkconnection.h"
+
+BluetoothHandler::BluetoothHandler(QObject *parent, int maxConnections)
+ : QRfcommServer(parent), m_serviceInfo(QBluetoothServiceInfo())
+ , m_listenPort(14), m_maxConnections(maxConnections)
+{
+ connect(this, SIGNAL(newConnection()), this, SLOT(newClientConnection()));
+}
+
+BluetoothHandler::~BluetoothHandler()
+{
+ closeAll();
+ stop();
+}
+
+void BluetoothHandler::start()
+{
+ if (isListening()) {
+ emit started();
+ return;
+ }
+
+ QBluetoothAddress address;
+
+ if (listen(address, m_listenPort)) {
+ qWarning("Server started on port: %d", serverPort());
+ emit started();
+ registerService();
+ } else {
+ qWarning("Error: Unable to start server");
+ emit startError();
+ }
+}
+
+void BluetoothHandler::stop()
+{
+ if (isListening())
+ close();
+
+ m_serviceInfo.unregisterService();
+}
+
+void BluetoothHandler::setListenPort(const quint16 &port)
+{
+ if (m_listenPort != port) {
+ m_listenPort = port;
+
+ emit listenPortChanged();
+ }
+}
+
+quint16 BluetoothHandler::listenPort() const
+{
+ return m_listenPort;
+}
+
+void BluetoothHandler::newClientConnection()
+{
+ if (m_connections.size() == m_maxConnections)
+ return;
+
+ NetworkConnection *connection;
+ connection = ConnectionFactory::create(ConnectionFactory::Bluetooth,
+ this, nextPendingConnection());
+
+ for (quint16 id = 0; id < m_maxConnections; id++) {
+ // If the peer ID is NOT on the dictionary, insert it
+ if (!m_connections.contains(id)) {
+ connection->setId(id);
+
+ connect(connection, SIGNAL(disconnected()),
+ this, SLOT(peerDisconnected()));
+ connect(connection, SIGNAL(error(QBluetoothSocket::SocketError)),
+ this, SLOT(socketError(QBluetoothSocket::SocketError)));
+ connect(connection, SIGNAL(received(NetworkMessage)),
+ this, SIGNAL(received(NetworkMessage)));
+
+ m_connections[id] = connection;
+
+ // Signals that a new peer has connected
+ emit peerConnected(connection);
+
+ break;
+ }
+ }
+}
+
+void BluetoothHandler::closeAll()
+{
+ NetworkConnection *tmp;
+ int pos = 0;
+ while (m_connections.size()) {
+ tmp = m_connections[pos];
+ tmp->close();
+ delete tmp;
+ ++pos;
+ }
+
+ m_connections.clear();
+}
+
+void BluetoothHandler::send(const NetworkMessage &message)
+{
+ m_connections[message.id()]->send(message);
+}
+
+void BluetoothHandler::peerDisconnected()
+{
+ NetworkConnection *connection = qobject_cast<NetworkConnection *>(sender());
+ m_connections.remove(connection->id());
+
+ // Signals that a peer has disconnected
+ emit peerDisconnected(connection);
+}
+
+void BluetoothHandler::socketError(QBluetoothSocket::SocketError socketError)
+{
+ NetworkConnection *connection = qobject_cast<NetworkConnection *>(sender());
+ quint16 id = connection->id();
+
+ qWarning("Bluetooth Socket error [ %d ]: %s", socketError,
+ connection->errorString().toUtf8().constData());
+ emit peerError(static_cast<QAbstractSocket::SocketError>(socketError), id);
+}
+
+void BluetoothHandler::registerService()
+{
+ m_serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceRecordHandle, (uint) 0x00010010);
+
+ // TODO: Profile Descriptor List: "Serial Port" (0x1101)
+ QBluetoothServiceInfo::Sequence classId;
+ classId << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::SerialPort));
+ m_serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceClassIds, classId);
+
+ m_serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceName,
+ tr("ChickenWranglers"));
+ m_serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceDescription,
+ tr("Game bluetooth server"));
+ m_serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceProvider,
+ tr("Openbossa"));
+ m_serviceInfo.setAttribute(QBluetoothServiceInfo::BrowseGroupList,
+ QBluetoothUuid(QBluetoothUuid::PublicBrowseGroup));
+
+ QBluetoothServiceInfo::Sequence protocolDescriptorList;
+ QBluetoothServiceInfo::Sequence protocol;
+ protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::Rfcomm))
+ << QVariant::fromValue(quint8(serverPort()));
+ protocolDescriptorList.append(QVariant::fromValue(protocol));
+ m_serviceInfo.setAttribute(QBluetoothServiceInfo::ProtocolDescriptorList,
+ protocolDescriptorList);
+
+ m_serviceInfo.registerService();
+}
diff --git a/chicken-wranglers/src/network/bluetoothhandler.h b/chicken-wranglers/src/network/bluetoothhandler.h
new file mode 100644
index 0000000..5248fc3
--- /dev/null
+++ b/chicken-wranglers/src/network/bluetoothhandler.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+#ifndef BLUETOOTHHANDLER_H
+#define BLUETOOTHHANDLER_H
+
+#include "networkmessage.h"
+
+#include <QBluetoothServiceInfo>
+#include <QBluetoothSocket>
+#include <QRfcommServer>
+#include <QtCore/QHash>
+
+class NetworkConnection;
+
+QTM_USE_NAMESPACE
+
+class BluetoothHandler : public QRfcommServer
+{
+ Q_OBJECT
+
+ Q_PROPERTY(quint16 listenPort READ listenPort WRITE setListenPort NOTIFY listenPortChanged)
+
+public:
+ BluetoothHandler(QObject *parent = 0, int maxConnections = 4);
+ ~BluetoothHandler();
+
+ void start();
+ void stop();
+
+ void setListenPort(const quint16 &port);
+ quint16 listenPort() const;
+
+ void send(const NetworkMessage &message);
+ void closeAll();
+
+signals:
+ void peerConnected(NetworkConnection *connection);
+ void peerDisconnected(NetworkConnection *connection);
+ void peerError(QAbstractSocket::SocketError socketError, quint16 id);
+ void received(const NetworkMessage &message);
+ void started();
+ void listenPortChanged();
+ void startError();
+
+private slots:
+ void newClientConnection();
+ void peerDisconnected();
+ void socketError(QBluetoothSocket::SocketError socketError);
+
+protected:
+ void registerService();
+
+private:
+ QHash<quint16, NetworkConnection *> m_connections;
+ QBluetoothServiceInfo m_serviceInfo;
+ quint16 m_listenPort;
+ int m_maxConnections;
+};
+
+#endif
diff --git a/chicken-wranglers/src/network/bthandler.cpp b/chicken-wranglers/src/network/bthandler.cpp
new file mode 100644
index 0000000..60d8e08
--- /dev/null
+++ b/chicken-wranglers/src/network/bthandler.cpp
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+#include <QBluetoothAddress>
+#include <QBluetoothDeviceDiscoveryAgent>
+#include <QBluetoothLocalDevice>
+
+#include "bthandler.h"
+
+BtHandler::BtHandler(QObject *parent)
+ : QObject(parent), m_discoveryAgent(new QBluetoothDeviceDiscoveryAgent(this)),
+ m_localDevice(new QBluetoothLocalDevice(this)), m_devices(new QList<BluetoothDevice>)
+{
+ connect(m_discoveryAgent, SIGNAL(deviceDiscovered(const QBluetoothDeviceInfo &)),
+ this, SLOT(deviceDiscovered(const QBluetoothDeviceInfo &)));
+}
+
+BtHandler::~BtHandler()
+{
+ delete m_devices;
+}
+
+void BtHandler::enable()
+{
+ m_discoveryAgent->start();
+}
+
+void BtHandler::disable()
+{
+ m_discoveryAgent->stop();
+}
+
+void BtHandler::deviceDiscovered(const QBluetoothDeviceInfo &deviceInfo)
+{
+ BluetoothDevice device;
+
+ device.setAddress(deviceInfo.address().toString());
+ if (deviceInfo.name().isEmpty())
+ device.setName(device.address());
+ else
+ device.setName(deviceInfo.name());
+
+ device.setPaired(m_localDevice->pairingStatus(deviceInfo.address()));
+ device.setCategory(quint8(deviceInfo.majorDeviceClass()));
+
+ m_devices->append(device);
+
+ emit discovered(device);
+}
diff --git a/chicken-wranglers/src/network/bthandler.h b/chicken-wranglers/src/network/bthandler.h
new file mode 100644
index 0000000..243bca5
--- /dev/null
+++ b/chicken-wranglers/src/network/bthandler.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+#ifndef BTHANDLER_H
+#define BTHANDLER_H
+
+#include "bluetoothdevice.h"
+
+#include <QtCore/QList>
+#include <QtCore/QObject>
+#include <qmobilityglobal.h>
+
+QTM_BEGIN_NAMESPACE
+
+class QBluetoothDeviceDiscoveryAgent;
+class QBluetoothDeviceInfo;
+class QBluetoothLocalDevice;
+
+QTM_END_NAMESPACE
+
+QTM_USE_NAMESPACE
+
+class BtHandler : public QObject
+{
+ Q_OBJECT
+
+public:
+ BtHandler(QObject *parent = 0);
+ ~BtHandler();
+
+ void enable();
+ void disable();
+
+signals:
+ void finished();
+ void discovered(const BluetoothDevice &device);
+
+private slots:
+ void deviceDiscovered(const QBluetoothDeviceInfo &deviceInfo);
+
+private:
+ QBluetoothDeviceDiscoveryAgent *m_discoveryAgent;
+ QBluetoothLocalDevice *m_localDevice;
+ QList<BluetoothDevice> *m_devices;
+};
+
+#endif
diff --git a/chicken-wranglers/src/network/connectionfactory.cpp b/chicken-wranglers/src/network/connectionfactory.cpp
new file mode 100644
index 0000000..6926bcb
--- /dev/null
+++ b/chicken-wranglers/src/network/connectionfactory.cpp
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+#include "connectionfactory.h"
+
+#include "bluetoothconnection.h"
+#include "tcpconnection.h"
+
+#include <QtCore/QIODevice>
+#include <QtCore/QObject>
+
+ConnectionFactory::ConnectionFactory()
+{
+}
+
+NetworkConnection *ConnectionFactory::create(ConnectionType connection, QObject *parent,
+ QIODevice *socket)
+{
+ NetworkConnection *result = 0;
+
+ switch (connection) {
+ case Lan:
+ result = new TcpConnection(parent, dynamic_cast<QTcpSocket *>(socket));
+ break;
+ case Bluetooth:
+ result = new BluetoothConnection(parent, dynamic_cast<QBluetoothSocket *>(socket));
+ break;
+ }
+
+ return result;
+}
diff --git a/chicken-wranglers/src/network/connectionfactory.h b/chicken-wranglers/src/network/connectionfactory.h
new file mode 100644
index 0000000..06333f0
--- /dev/null
+++ b/chicken-wranglers/src/network/connectionfactory.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+#ifndef CONNECTIONFACTORY_H
+#define CONNECTIONFACTORY_H
+
+class QIODevice;
+class QObject;
+class NetworkConnection;
+
+class ConnectionFactory
+{
+public:
+ enum ConnectionType {
+ Lan,
+ Bluetooth
+ };
+
+ static NetworkConnection *create(ConnectionType connection, QObject *parent = 0,
+ QIODevice *socket = 0);
+
+private:
+ ConnectionFactory();
+};
+
+#endif
diff --git a/chicken-wranglers/src/network/lanhandler.cpp b/chicken-wranglers/src/network/lanhandler.cpp
new file mode 100644
index 0000000..ec1c12c
--- /dev/null
+++ b/chicken-wranglers/src/network/lanhandler.cpp
@@ -0,0 +1,133 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+#include "lanhandler.h"
+
+#include "connectionfactory.h"
+#include "network.h"
+#include "networkconnection.h"
+
+LanHandler::LanHandler(QObject *parent, int maxConnections)
+ : QTcpServer(parent), m_maxConnections(maxConnections)
+{
+ connect(this, SIGNAL(newConnection()), this, SLOT(newClientConnection()));
+}
+LanHandler::~LanHandler()
+{
+ closeAll();
+ stop();
+}
+
+void LanHandler::newClientConnection()
+{
+ if (m_connections.size() == m_maxConnections)
+ return;
+
+ NetworkConnection *connection;
+ connection = ConnectionFactory::create(ConnectionFactory::Lan,
+ this, nextPendingConnection());
+
+ for (quint16 id = 0; id < m_maxConnections; id++) {
+ // If the peer ID is NOT on the dictionary, insert it
+ if (!m_connections.contains(id)) {
+ connection->setId(id);
+
+ connect(connection, SIGNAL(disconnected()),
+ this, SLOT(peerDisconnected()));
+ connect(connection, SIGNAL(error(QAbstractSocket::SocketError)),
+ this, SLOT(socketError(QAbstractSocket::SocketError)));
+ connect(connection, SIGNAL(received(NetworkMessage)),
+ this, SIGNAL(received(NetworkMessage)));
+
+ m_connections[id] = connection;
+
+ // Signals that a new peer has connected
+ emit peerConnected(connection);
+
+ break;
+ }
+ }
+}
+
+void LanHandler::closeAll()
+{
+ NetworkConnection *tmp;
+ int pos = 0;
+ while (m_connections.size()) {
+ tmp = m_connections[pos];
+ tmp->close();
+ delete tmp;
+ ++pos;
+ }
+
+ m_connections.clear();
+}
+
+void LanHandler::send(const NetworkMessage &message)
+{
+ m_connections[message.id()]->send(message);
+}
+
+void LanHandler::peerDisconnected()
+{
+ NetworkConnection *connection = qobject_cast<NetworkConnection *>(sender());
+ m_connections.remove(connection->id());
+
+ // Signals that a peer has disconnected
+ emit peerDisconnected(connection);
+}
+
+void LanHandler::socketError(QAbstractSocket::SocketError socketError)
+{
+ NetworkConnection *connection = qobject_cast<NetworkConnection *>(sender());
+ quint16 id = connection->id();
+
+ qWarning("TCP Socket error [ %d ]: %s", socketError,
+ connection->errorString().toUtf8().constData());
+
+ emit peerError(socketError, id);
+}
+
+void LanHandler::stop()
+{
+ if (isListening())
+ close();
+}
diff --git a/chicken-wranglers/src/network/lanhandler.h b/chicken-wranglers/src/network/lanhandler.h
new file mode 100644
index 0000000..457b474
--- /dev/null
+++ b/chicken-wranglers/src/network/lanhandler.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+#ifndef LANHANDLER_H
+#define LANHANDLER_H
+
+#include "networkmessage.h"
+
+#include <QtCore/QHash>
+#include <QtNetwork/QTcpServer>
+
+class NetworkConnection;
+
+class LanHandler : public QTcpServer
+{
+ Q_OBJECT
+
+public:
+ LanHandler(QObject *parent = 0, int maxConnections = 4);
+ ~LanHandler();
+
+ void stop();
+ void send(const NetworkMessage &message);
+ void closeAll();
+
+signals:
+ void peerConnected(NetworkConnection *connection);
+ void peerDisconnected(NetworkConnection *connection);
+ void peerError(QAbstractSocket::SocketError socketError, quint16 id);
+ void received(const NetworkMessage &message);
+ void startError();
+
+private slots:
+ void newClientConnection();
+ void peerDisconnected();
+ void socketError(QAbstractSocket::SocketError socketError);
+
+private:
+ QHash<quint16, NetworkConnection *> m_connections;
+ int m_maxConnections;
+};
+
+#endif
diff --git a/chicken-wranglers/src/network/network.h b/chicken-wranglers/src/network/network.h
new file mode 100644
index 0000000..2b86ded
--- /dev/null
+++ b/chicken-wranglers/src/network/network.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+#ifndef NETWORK_H
+#define NETWORK_H
+
+#include <QtCore/QByteArray>
+#include <QtGlobal>
+
+namespace CW
+{
+ enum UdpSenderType {
+ UdpSenderNoType = 0,
+ UdpSenderClient = 1,
+ UdpSenderServer = 2,
+ UdpSenderAny = UdpSenderClient | UdpSenderServer
+ };
+
+ enum UdpContentType {
+ UdpNoContent = 200,
+ UdpContentDiscovery,
+ UdpContentAckDiscovery,
+ };
+
+ static const char udpMessageSeparator = '/';
+}
+
+#endif
diff --git a/chicken-wranglers/src/network/network.pri b/chicken-wranglers/src/network/network.pri
new file mode 100644
index 0000000..81f9d36
--- /dev/null
+++ b/chicken-wranglers/src/network/network.pri
@@ -0,0 +1,37 @@
+QT += network
+
+maemo5 {
+ CONFIG += mobility12
+} else {
+ CONFIG += mobility
+}
+MOBILITY += connectivity
+
+PATH = $$PWD
+
+HEADERS += \
+ $$PATH/network.h \
+ $$PATH/networkclient.h \
+ $$PATH/networkserver.h \
+ $$PATH/udphandler.h \
+ $$PATH/networkmessage.h \
+ $$PATH/networkconnection.h \
+ $$PATH/bluetoothconnection.h \
+ $$PATH/tcpconnection.h \
+ $$PATH/connectionfactory.h \
+ $$PATH/lanhandler.h \
+ $$PATH/bluetoothhandler.h \
+ $$PATH/bthandler.h
+
+SOURCES += \
+ $$PATH/networkclient.cpp \
+ $$PATH/networkserver.cpp \
+ $$PATH/udphandler.cpp \
+ $$PATH/networkmessage.cpp \
+ $$PATH/networkconnection.cpp \
+ $$PATH/bluetoothconnection.cpp \
+ $$PATH/tcpconnection.cpp \
+ $$PATH/connectionfactory.cpp \
+ $$PATH/lanhandler.cpp \
+ $$PATH/bluetoothhandler.cpp \
+ $$PATH/bthandler.cpp
diff --git a/chicken-wranglers/src/network/networkclient.cpp b/chicken-wranglers/src/network/networkclient.cpp
new file mode 100644
index 0000000..58dba98
--- /dev/null
+++ b/chicken-wranglers/src/network/networkclient.cpp
@@ -0,0 +1,196 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+#include "networkclient.h"
+
+#include "bthandler.h"
+#include "connectionfactory.h"
+#include "network.h"
+#include "networkconnection.h"
+#include "udphandler.h"
+
+#include <QtCore/QList>
+#include <QtCore/QTimer>
+
+
+NetworkClient::NetworkClient(const QString &connectivity, int discoveryTimeout,
+ int clientAttempts, QObject *parent)
+ : QObject(parent), m_udpHandler(0), m_btHandler(0), m_connection(0),
+ m_discoveryTimer(0), m_discoveryAttempts(0),
+ m_discoveryTimeout(discoveryTimeout), m_discoveryClientAttempts(clientAttempts)
+{
+ if (connectivity == "lan") {
+ m_udpHandler = new UdpHandler(this);
+ m_udpHandler->setListenPort(m_lanUdpPort);
+
+ connect(m_udpHandler, SIGNAL(received(QHostAddress, QByteArray, quint16, QByteArray)),
+ this, SLOT(processUdp(QHostAddress, QByteArray, quint16, QByteArray)));
+
+ m_connection = ConnectionFactory::create(ConnectionFactory::Lan, this);
+ connect(m_connection, SIGNAL(error(QAbstractSocket::SocketError)),
+ this, SLOT(tcpSocketError(QAbstractSocket::SocketError)));
+
+ } else if (connectivity == "bluetooth") {
+ m_btHandler = new BtHandler(this);
+ connect(m_btHandler, SIGNAL(discovered(const BluetoothDevice &)),
+ this, SIGNAL(bluetoothDeviceDiscovered(const BluetoothDevice &)));
+
+ m_connection = ConnectionFactory::create(ConnectionFactory::Bluetooth, this);
+ connect(m_connection, SIGNAL(error(QBluetoothSocket::SocketError)),
+ this, SLOT(bluetoothSocketError(QBluetoothSocket::SocketError)));
+ }
+
+ // Timer for broadcasting the message
+ m_discoveryTimer = new QTimer(this);
+ // TODO: rename this settings name to DiscoveryTimeout
+ m_discoveryTimer->setInterval(m_discoveryTimeout);
+ connect(m_discoveryTimer, SIGNAL(timeout()),
+ this, SLOT(sendDiscovery()));
+
+ connect(m_connection, SIGNAL(connected()),
+ this, SIGNAL(connected()));
+ connect(m_connection, SIGNAL(disconnected()),
+ this, SIGNAL(disconnected()));
+ connect(m_connection, SIGNAL(received(const NetworkMessage &)),
+ this, SIGNAL(messageReceived(const NetworkMessage &)));
+}
+
+void NetworkClient::setLanPorts(int udpPort, int tcpPort)
+{
+ m_lanUdpPort = udpPort;
+ m_lanTcpPort = tcpPort;
+}
+
+void NetworkClient::send(const NetworkMessage &message)
+{
+ m_connection->send(message);
+}
+
+void NetworkClient::startDiscovery()
+{
+ if (m_udpHandler) {
+ // FIXME: Do not enable UdpHandler if it's already enabled
+ m_udpHandler->setListenPort(m_lanUdpPort + 1);
+ m_udpHandler->enable();
+
+ m_discoveryAttempts = 0;
+ m_discoveryTimer->start();
+ } else {
+ m_btHandler->enable();
+ }
+}
+
+void NetworkClient::stopDiscovery()
+{
+ if (m_udpHandler)
+ m_discoveryTimer->stop();
+
+ if (m_btHandler)
+ m_btHandler->disable();
+}
+
+void NetworkClient::connectToBluetoothServer(const QString &address)
+{
+ m_connection->connectToHost(address, 14);
+}
+
+void NetworkClient::processUdp(QHostAddress senderAddress, QByteArray content,
+ quint16 senderListenPort, QByteArray timestamp)
+{
+ Q_UNUSED(timestamp)
+
+ quint16 contentData = content.toUShort();
+
+ if (contentData == CW::UdpContentAckDiscovery)
+ processAckDiscovery(senderAddress, senderListenPort);
+}
+
+void NetworkClient::processAckDiscovery(QHostAddress senderAddress, quint16 senderListenPort)
+{
+ Q_UNUSED(senderListenPort)
+
+ stopDiscovery();
+
+ if (m_connection->state() == QAbstractSocket::UnconnectedState) {
+ // Estabilish a connection to the server
+ m_connection->connectToHost(senderAddress.toString(), m_lanTcpPort);
+ } else {
+ qWarning("TCP Connection already open");
+ }
+}
+
+void NetworkClient::sendDiscovery()
+{
+ if (m_discoveryAttempts < m_discoveryClientAttempts) {
+ m_discoveryAttempts++;
+
+ if (m_udpHandler) {
+ m_udpHandler->sendDatagram(QHostAddress::Broadcast, m_lanUdpPort,
+ CW::UdpSenderClient, CW::UdpContentDiscovery,
+ m_udpHandler->listenPort());
+ } else {
+ // TODO: Notify upper layers about discovered bt
+ }
+ } else {
+ stopDiscovery();
+
+ if (m_udpHandler) {
+ m_udpHandler->disable();
+ } else {
+ // TODO: Bluetooth stuff
+ }
+
+ emit serverDiscoveryTimeout();
+ }
+}
+
+void NetworkClient::tcpSocketError(QAbstractSocket::SocketError error)
+{
+ qWarning("TCP Socket error [ %d ]: %s", error,
+ m_connection->errorString().toUtf8().constData());
+
+ emit socketError(error);
+}
+
+void NetworkClient::bluetoothSocketError(QBluetoothSocket::SocketError error)
+{
+ emit socketError(static_cast<QAbstractSocket::SocketError>(error));
+}
diff --git a/chicken-wranglers/src/network/networkclient.h b/chicken-wranglers/src/network/networkclient.h
new file mode 100644
index 0000000..621fc2c
--- /dev/null
+++ b/chicken-wranglers/src/network/networkclient.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+#ifndef NETWORKCLIENT_H
+#define NETWORKCLIENT_H
+
+#include "bluetoothdevice.h"
+#include "networkmessage.h"
+
+#include <QBluetoothSocket>
+#include <QtNetwork/QAbstractSocket>
+#include <QtNetwork/QHostAddress>
+#include <QtCore/QByteArray>
+#include <QtCore/QObject>
+
+class BtHandler;
+class NetworkConnection;
+class QTimer;
+class UdpHandler;
+
+QTM_USE_NAMESPACE
+
+class NetworkClient : public QObject
+{
+ Q_OBJECT
+
+public:
+ NetworkClient(const QString &connectivity = "lan", int discoveryTimeout = 0,
+ int clientAttempts = 0, QObject *parent = 0);
+
+ void send(const NetworkMessage &message);
+ void setLanPorts(int udpPort, int tcpPort);
+
+public slots:
+ void startDiscovery();
+ void stopDiscovery();
+ void connectToBluetoothServer(const QString &address);
+
+signals:
+ void connected();
+ void disconnected();
+ void socketError(QAbstractSocket::SocketError socketError);
+ void messageReceived(const NetworkMessage &message);
+ void serverDiscoveryTimeout();
+ void bluetoothDeviceDiscovered(const BluetoothDevice &device);
+
+private slots:
+ void processUdp(QHostAddress senderAddress, QByteArray content,
+ quint16 senderListenPort, QByteArray timestamp);
+ void sendDiscovery();
+ void tcpSocketError(QAbstractSocket::SocketError error);
+ void bluetoothSocketError(QBluetoothSocket::SocketError error);
+
+private:
+ void processAckDiscovery(QHostAddress senderAddress, quint16 senderListenPort);
+
+ UdpHandler *m_udpHandler;
+ BtHandler *m_btHandler;
+ NetworkConnection *m_connection;
+ QTimer *m_discoveryTimer;
+ quint16 m_discoveryAttempts;
+ int m_discoveryTimeout;
+ int m_lanUdpPort;
+ int m_lanTcpPort;
+ int m_discoveryClientAttempts;
+};
+
+#endif
diff --git a/chicken-wranglers/src/network/networkconnection.cpp b/chicken-wranglers/src/network/networkconnection.cpp
new file mode 100644
index 0000000..6bebe58
--- /dev/null
+++ b/chicken-wranglers/src/network/networkconnection.cpp
@@ -0,0 +1,144 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+#include "networkconnection.h"
+
+#include <QtCore/QByteArray>
+
+NetworkConnection::NetworkConnection(QObject *parent)
+ : QObject(parent), m_id(0), m_message(NetworkMessage())
+{
+}
+
+NetworkConnection::~NetworkConnection()
+{
+}
+
+void NetworkConnection::setId(const quint16 &newId)
+{
+ m_id = newId;
+}
+
+quint16 NetworkConnection::id() const
+{
+ return m_id;
+}
+
+void NetworkConnection::processRead(QIODevice *m_socket)
+{
+ QByteArray buffer(m_socket->readAll());
+ int counter = buffer.length();
+
+ QDataStream dataStream(&buffer, QIODevice::ReadOnly);
+ dataStream.setVersion(QDataStream::Qt_4_7);
+
+ while (counter) {
+ // Type
+ if (m_message.type() == CW::NoMessageType) {
+ if (counter < ((int) sizeof(quint16)))
+ return;
+
+ // Read the Message Type
+ quint16 type;
+ dataStream >> type;
+ counter -= sizeof(quint16);
+
+ m_message.setType((CW::MessageType) type);
+ }
+
+ // Content
+ if (m_message.content() == 0) {
+ if (counter < ((int) sizeof(quint16)))
+ return;
+
+ // Read the Message Content
+ quint16 content;
+ dataStream >> content;
+ counter -= sizeof(quint16);
+
+ m_message.setContent(content);
+ }
+
+ if (m_message.data().size() == 0) {
+ if (counter < ((int) sizeof(quint32)))
+ return;
+
+ quint32 dataSize;
+ dataStream >> dataSize;
+ counter -= sizeof(quint32);
+
+ if (dataSize == 0xFFFFFFFF) {
+ m_message.setId(m_id);
+
+ emit received(m_message);
+
+ m_message = NetworkMessage();
+
+ continue;
+ } else {
+ QByteArray data;
+ data.resize(dataSize);
+ m_message.setData(data);
+ }
+ }
+
+ if (m_message.data().size() > 0) {
+ if (counter < m_message.data().size())
+ return;
+
+ int dataSize = m_message.data().size();
+ char *charData = new char[dataSize + 1];
+
+ dataStream.readRawData(charData, dataSize);
+ counter -= dataSize;
+ charData[dataSize] = '\0';
+ QByteArray data(charData);
+ delete charData;
+
+ m_message.setData(data);
+
+ emit received(m_message);
+
+ m_message = NetworkMessage();
+ }
+ }
+}
diff --git a/chicken-wranglers/src/network/networkconnection.h b/chicken-wranglers/src/network/networkconnection.h
new file mode 100644
index 0000000..5167804
--- /dev/null
+++ b/chicken-wranglers/src/network/networkconnection.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+#ifndef NETWORKCONNECTION_H
+#define NETWORKCONNECTION_H
+
+#include "networkmessage.h"
+
+#include <QtCore/QObject>
+#include <QtCore/QPointer>
+#include <QtNetwork/QTcpSocket>
+
+class NetworkConnection : public QObject
+{
+ Q_OBJECT
+
+public:
+ NetworkConnection(QObject *parent = 0);
+ virtual ~NetworkConnection();
+
+ virtual void setId(const quint16 &newId);
+ virtual quint16 id() const;
+
+ virtual void send(NetworkMessage message) = 0;
+
+ virtual void connectToHost(const QString &address, const quint16 &port) = 0;
+
+ virtual QAbstractSocket::SocketState state() const = 0;
+
+ virtual QAbstractSocket::SocketError error() const = 0;
+
+ virtual QString errorString() const = 0;
+
+ virtual void close() = 0;
+
+signals:
+ void received(const NetworkMessage &message);
+
+protected:
+ void processRead(QIODevice *m_socket);
+
+ quint16 m_id;
+ NetworkMessage m_message;
+};
+
+#endif
diff --git a/chicken-wranglers/src/network/networkmessage.cpp b/chicken-wranglers/src/network/networkmessage.cpp
new file mode 100644
index 0000000..55e31f9
--- /dev/null
+++ b/chicken-wranglers/src/network/networkmessage.cpp
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+#include <QtCore/QDataStream>
+
+#include "networkmessage.h"
+
+NetworkMessage::NetworkMessage()
+ : m_id(0), m_type(CW::NoMessageType),
+ m_content(0), m_data(QByteArray())
+{
+}
+
+NetworkMessage::NetworkMessage(CW::MessageType type, quint16 content)
+ : m_id(0), m_type(type),
+ m_content(content), m_data(QByteArray())
+{
+}
+
+void NetworkMessage::setId(const quint16 &newId)
+{
+ m_id = newId;
+}
+
+quint16 NetworkMessage::id() const
+{
+ return m_id;
+}
+
+void NetworkMessage::setType(const CW::MessageType &newType)
+{
+ m_type = newType;
+}
+
+CW::MessageType NetworkMessage::type() const
+{
+ return m_type;
+}
+
+void NetworkMessage::setContent(const quint16 &newContent)
+{
+ m_content = newContent;
+}
+
+quint16 NetworkMessage::content() const
+{
+ return m_content;
+}
+
+void NetworkMessage::setData(const QByteArray &newData)
+{
+ m_data = newData;
+}
+
+QByteArray NetworkMessage::data() const
+{
+ return m_data;
+}
+
+QByteArray NetworkMessage::byteArray() const
+{
+ quint16 field;
+ QByteArray byteArray;
+
+ QDataStream stream(&byteArray, QIODevice::WriteOnly);
+ stream.setVersion(QDataStream::Qt_4_0);
+
+ // Type
+ field = m_type;
+ stream << field;
+
+ // Content
+ stream << m_content;
+
+ // Data (optional)
+ stream << m_data;
+
+ return byteArray;
+}
diff --git a/chicken-wranglers/src/network/networkmessage.h b/chicken-wranglers/src/network/networkmessage.h
new file mode 100644
index 0000000..da650be
--- /dev/null
+++ b/chicken-wranglers/src/network/networkmessage.h
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+#ifndef NETWORKMESSAGE_H
+#define NETWORKMESSAGE_H
+
+#include <QtCore/QByteArray>
+
+namespace CW
+{
+ enum MessageType {
+ NoMessageType = 1000,
+ PlayerControlMessageType,
+ PlayerInfoMessageType,
+ CharacterMessageType,
+ MatchMessageType
+ };
+
+ enum PlayerControl {
+ PlayerControlStop = 2000,
+ PlayerControlUp,
+ PlayerControlDown,
+ PlayerControlLeft,
+ PlayerControlRight,
+ PlayerControlLaserUp,
+ PlayerControlLaserDown,
+ PlayerControlLaserLeft,
+ PlayerControlLaserRight
+ };
+
+ enum PlayerInfo {
+ PlayerInfoScore = 3000,
+ PlayerInfoLeader
+ };
+
+ enum Character {
+ CharacterSelected = 4000,
+ CharacterReleased,
+ CharacterAvailableList,
+ CharacterIsAvailable
+ };
+
+ enum Match {
+ MatchReady = 5000,
+ MatchFinished
+ };
+}
+
+class NetworkMessage
+{
+public:
+ NetworkMessage();
+ NetworkMessage(CW::MessageType type, quint16 content);
+
+ void setId(const quint16 &newId);
+ quint16 id() const;
+
+ void setType(const CW::MessageType &newType);
+ CW::MessageType type() const;
+
+ void setContent(const quint16 &newContent);
+ quint16 content() const;
+
+ void setData(const QByteArray &newData);
+ QByteArray data() const;
+
+ QByteArray byteArray() const;
+
+private:
+ quint16 m_id;
+ CW::MessageType m_type;
+ quint16 m_content;
+ QByteArray m_data;
+};
+
+#endif
diff --git a/chicken-wranglers/src/network/networkserver.cpp b/chicken-wranglers/src/network/networkserver.cpp
new file mode 100644
index 0000000..8f13259
--- /dev/null
+++ b/chicken-wranglers/src/network/networkserver.cpp
@@ -0,0 +1,255 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+#include "networkserver.h"
+
+#include "bluetoothhandler.h"
+#include "lanhandler.h"
+#include "network.h"
+#include "udphandler.h"
+
+#include <QtCore/QList>
+#include <QtCore/QTimer>
+
+NetworkServer::NetworkServer(const QString &connectivity, int discoveryTimeout, int hostAttempts, QObject *parent)
+ : QObject(parent), m_udpHandler(0), m_lanHandler(0) , m_blueHandler(0)
+ , m_discoveryAttempts(0), m_lookingForServers(true)
+ , m_discoveryTimeout(discoveryTimeout), m_discoveryHostAttempts(hostAttempts)
+ , m_serverBluetooth(true)
+{
+ createConnectionHandler(connectivity);
+}
+
+void NetworkServer::createConnectionHandler(const QString &connectivity)
+{
+ if (connectivity == "lan") {
+ m_serverBluetooth = false;
+ if (m_udpHandler)
+ return;
+
+ m_udpHandler = new UdpHandler(this);
+ m_udpHandler->setListenPort(m_lanUdpPort);
+
+ connect(m_udpHandler, SIGNAL(received(QHostAddress, QByteArray, quint16, QByteArray)),
+ this, SLOT(processUdp(QHostAddress, QByteArray, quint16, QByteArray)));
+
+ m_lanHandler = new LanHandler(this);
+ connect(m_lanHandler, SIGNAL(peerConnected(NetworkConnection *)),
+ this, SIGNAL(peerConnected(NetworkConnection *)));
+ connect(m_lanHandler, SIGNAL(peerDisconnected(NetworkConnection *)),
+ this, SIGNAL(peerDisconnected(NetworkConnection *)));
+ connect(m_lanHandler, SIGNAL(peerError(QAbstractSocket::SocketError, quint16)),
+ this, SIGNAL(peerError(QAbstractSocket::SocketError, quint16)));
+ connect(m_lanHandler, SIGNAL(received(NetworkMessage)),
+ this, SIGNAL(messageReceived(NetworkMessage)));
+
+ m_discoveryTimer = new QTimer(this);
+ m_discoveryTimer->setInterval(m_discoveryTimeout);
+ connect(m_discoveryTimer, SIGNAL(timeout()),
+ this, SLOT(sendDiscovery()));
+
+ } else if (connectivity == "bluetooth") {
+ m_serverBluetooth = true;
+ if (m_blueHandler)
+ return;
+
+ m_blueHandler = new BluetoothHandler(this);
+
+ connect(m_blueHandler, SIGNAL(started()),
+ this, SIGNAL(started()));
+ connect(m_blueHandler, SIGNAL(peerConnected(NetworkConnection *)),
+ this, SIGNAL(peerConnected(NetworkConnection *)));
+ connect(m_blueHandler, SIGNAL(peerDisconnected(NetworkConnection *)),
+ this, SIGNAL(peerDisconnected(NetworkConnection *)));
+ connect(m_blueHandler, SIGNAL(peerError(QAbstractSocket::SocketError, quint16)),
+ this, SIGNAL(peerError(QAbstractSocket::SocketError, quint16)));
+ connect(m_blueHandler, SIGNAL(received(NetworkMessage)),
+ this, SIGNAL(messageReceived(NetworkMessage)));
+ connect(m_blueHandler, SIGNAL(startError()), this, SLOT(startError()));
+ }
+}
+
+NetworkServer::~NetworkServer()
+{
+}
+
+void NetworkServer::send(const NetworkMessage &message)
+{
+ if (m_lanHandler)
+ m_lanHandler->send(message);
+ else if (m_blueHandler)
+ m_blueHandler->send(message);
+}
+
+void NetworkServer::setLanPorts(int udpPort, int tcpPort)
+{
+ m_lanUdpPort = udpPort;
+ m_lanTcpPort = tcpPort;
+}
+
+void NetworkServer::start()
+{
+ if (!m_serverBluetooth && m_lanHandler) {
+ m_udpHandler->setListenSenderType(CW::UdpSenderAny);
+ m_udpHandler->setListenPort(m_lanUdpPort + 1);
+ m_udpHandler->enable();
+ // Server tries to find if there are other
+ // running servers in the same network
+ startDiscovery();
+ } else if ((m_serverBluetooth == true) && m_blueHandler) {
+ m_blueHandler->start();
+ }
+}
+
+void NetworkServer::stop()
+{
+ if (!m_serverBluetooth && m_lanHandler) {
+ stopDiscovery();
+
+ if (m_lanHandler->isListening())
+ m_lanHandler->close();
+
+ m_udpHandler->setListenSenderType(CW::UdpSenderNoType);
+ m_udpHandler->disable();
+ } else if ((m_serverBluetooth == true) && m_blueHandler) {
+ m_blueHandler->stop();
+ }
+}
+
+void NetworkServer::closeAll()
+{
+ if (!m_serverBluetooth && m_lanHandler) {
+ stopDiscovery();
+
+ if (m_lanHandler->isListening())
+ m_lanHandler->closeAll();
+
+ m_udpHandler->setListenSenderType(CW::UdpSenderNoType);
+ m_udpHandler->disable();
+ } else if ((m_serverBluetooth == true) && m_blueHandler) {
+ m_blueHandler->closeAll();
+ }
+
+}
+
+
+void NetworkServer::startDiscovery()
+{
+ m_lookingForServers = true;
+ m_discoveryAttempts = 0;
+ m_discoveryTimer->start();
+}
+
+void NetworkServer::stopDiscovery()
+{
+ m_lookingForServers = false;
+ m_discoveryTimer->stop();
+}
+
+void NetworkServer::processUdp(QHostAddress senderAddress, QByteArray content,
+ quint16 senderListenPort, QByteArray timestamp)
+{
+ Q_UNUSED(timestamp)
+
+ quint16 contentData = content.toUShort();
+
+ if (contentData == CW::UdpContentDiscovery)
+ processDiscovery(senderAddress, senderListenPort);
+ else if (contentData == CW::UdpContentAckDiscovery)
+ processAckDiscovery(senderAddress, senderListenPort);
+}
+
+void NetworkServer::processDiscovery(QHostAddress senderAddress, quint16 senderListenPort)
+{
+ // While looking for other active servers, do not respond
+ // to Discovery messages.
+ if (m_lookingForServers)
+ return;
+
+ // Received: "Discovery" --> Send: "AckDiscovery"
+ m_udpHandler->sendDatagram(senderAddress, senderListenPort, CW::UdpSenderServer,
+ CW::UdpContentAckDiscovery, m_udpHandler->listenPort());
+}
+
+void NetworkServer::processAckDiscovery(QHostAddress senderAddress, quint16 senderListenPort)
+{
+ Q_UNUSED(senderAddress)
+ Q_UNUSED(senderListenPort)
+
+ stop();
+
+ emit error(AnotherServerRunningError);
+}
+
+void NetworkServer::sendDiscovery()
+{
+ if (m_discoveryAttempts == m_discoveryHostAttempts) {
+ stopDiscovery();
+
+ m_udpHandler->disable();
+ m_udpHandler->setListenSenderType(CW::UdpSenderAny);
+ m_udpHandler->setListenPort(m_lanUdpPort);
+ m_udpHandler->enable();
+
+ if (!m_lanHandler->isListening()) {
+ if (!m_lanHandler->listen(QHostAddress::Any, m_lanTcpPort)) {
+ startError();
+ }
+ }
+ // TODO: Return the server to the stopped state in case of port binding error.
+ if (m_udpHandler->listenPort() != m_lanUdpPort)
+ qWarning("UDP Socket error: Unable to bind to port %d", m_lanUdpPort);
+
+ started();
+ return;
+ }
+
+ m_discoveryAttempts++;
+ m_udpHandler->sendDatagram(QHostAddress::Broadcast, m_lanUdpPort,
+ CW::UdpSenderServer, CW::UdpContentDiscovery,
+ m_udpHandler->listenPort());
+}
+
+void NetworkServer::startError()
+{
+ emit error(AnotherServerRunningError);
+}
diff --git a/chicken-wranglers/src/network/networkserver.h b/chicken-wranglers/src/network/networkserver.h
new file mode 100644
index 0000000..637a38f
--- /dev/null
+++ b/chicken-wranglers/src/network/networkserver.h
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+#ifndef NETWORKSERVER_H
+#define NETWORKSERVER_H
+
+#include "networkmessage.h"
+
+#include <QtCore/QByteArray>
+#include <QtCore/QList>
+#include <QtCore/QObject>
+#include <QtNetwork/QHostAddress>
+
+class BluetoothHandler;
+class LanHandler;
+class NetworkConnection;
+class QTimer;
+class UdpHandler;
+
+class NetworkServer : public QObject
+{
+ Q_OBJECT
+
+ Q_ENUMS(ServerError)
+
+public:
+ NetworkServer(const QString &connectivity = "lan", int hostAttempts = 0, int discoveryTimeout = 0, QObject *parent = 0);
+ ~NetworkServer();
+
+ void send(const NetworkMessage &message);
+ void setLanPorts(int udpPort, int tcpPort);
+
+ enum ServerError {
+ AnotherServerRunningError,
+ UnknownError
+ };
+
+ void createConnectionHandler(const QString &connectivity);
+
+ void closeAll();
+
+public slots:
+ void start();
+ void stop();
+
+signals:
+ void peerConnected(NetworkConnection *connection);
+ void peerDisconnected(NetworkConnection *connection);
+ void peerError(QAbstractSocket::SocketError socketError, quint16 id);
+ void messageReceived(const NetworkMessage &message);
+ void error(NetworkServer::ServerError error);
+ void started();
+
+private slots:
+ void processUdp(QHostAddress senderAddress, QByteArray content,
+ quint16 senderListenPort, QByteArray timestamp);
+ void sendDiscovery();
+
+ void startError();
+
+private:
+ void startDiscovery();
+ void stopDiscovery();
+ void processDiscovery(QHostAddress senderAddress, quint16 senderListenPort);
+ void processAckDiscovery(QHostAddress senderAddress, quint16 senderListenPort);
+
+ UdpHandler *m_udpHandler;
+ LanHandler *m_lanHandler;
+ BluetoothHandler *m_blueHandler;
+ QTimer *m_discoveryTimer;
+ quint16 m_discoveryAttempts;
+ bool m_lookingForServers;
+ int m_discoveryTimeout;
+ int m_lanUdpPort;
+ int m_lanTcpPort;
+ int m_discoveryHostAttempts;
+ bool m_serverBluetooth;
+
+};
+
+#endif
diff --git a/chicken-wranglers/src/network/tcpconnection.cpp b/chicken-wranglers/src/network/tcpconnection.cpp
new file mode 100644
index 0000000..502962e
--- /dev/null
+++ b/chicken-wranglers/src/network/tcpconnection.cpp
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+#include <QtCore/QByteArray>
+#include <QtNetwork/QHostAddress>
+
+#include "tcpconnection.h"
+
+TcpConnection::TcpConnection(QObject *parent, QTcpSocket *socket)
+ : NetworkConnection(parent), m_socket(socket)
+{
+ if (m_socket == 0)
+ m_socket = new QTcpSocket(this);
+
+ connect(m_socket, SIGNAL(connected()),
+ this, SIGNAL(connected()));
+ connect(m_socket, SIGNAL(disconnected()),
+ this, SIGNAL(disconnected()));
+ connect(m_socket, SIGNAL(error(QAbstractSocket::SocketError)),
+ this, SIGNAL(error(QAbstractSocket::SocketError)));
+ connect(m_socket, SIGNAL(readyRead()),
+ this, SLOT(processReadyRead()));
+}
+
+TcpConnection::~TcpConnection()
+{
+ if (m_socket)
+ m_socket->close();
+}
+
+void TcpConnection::setId(const quint16 &newId)
+{
+ m_id = newId;
+}
+
+quint16 TcpConnection::id() const
+{
+ return m_id;
+}
+
+void TcpConnection::send(NetworkMessage message)
+{
+ if (m_socket->write(message.byteArray()) == -1)
+ qWarning("TCP Socket write error: %s", m_socket->errorString().toUtf8().constData());
+}
+
+void TcpConnection::connectToHost(const QString &address, const quint16 &port)
+{
+ m_socket->connectToHost(QHostAddress(address), port);
+}
+
+QAbstractSocket::SocketState TcpConnection::state() const
+{
+ return m_socket->state();
+}
+
+QAbstractSocket::SocketError TcpConnection::error() const
+{
+ return m_socket->error();
+}
+
+QString TcpConnection::errorString() const
+{
+ return m_socket->errorString();
+}
+
+void TcpConnection::processReadyRead()
+{
+ processRead(m_socket);
+}
+
+void TcpConnection::close()
+{
+ m_socket.data()->close();
+}
diff --git a/chicken-wranglers/src/network/tcpconnection.h b/chicken-wranglers/src/network/tcpconnection.h
new file mode 100644
index 0000000..464d276
--- /dev/null
+++ b/chicken-wranglers/src/network/tcpconnection.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+#ifndef TCPCONNECTION_H
+#define TCPCONNECTION_H
+
+#include "networkconnection.h"
+
+#include <QtCore/QObject>
+#include <QtCore/QPointer>
+#include <QtNetwork/QTcpSocket>
+
+class TcpConnection : public NetworkConnection
+{
+ Q_OBJECT
+
+public:
+ TcpConnection(QObject *parent = 0, QTcpSocket *socket = 0);
+ ~TcpConnection();
+
+ void setId(const quint16 &newId);
+ quint16 id() const;
+
+ void send(NetworkMessage message);
+
+ void connectToHost(const QString &address, const quint16 &port);
+
+ QAbstractSocket::SocketState state() const;
+
+ QAbstractSocket::SocketError error() const;
+
+ QString errorString() const;
+
+ void close();
+
+signals:
+ void connected();
+ void disconnected();
+ void error(QAbstractSocket::SocketError socketError);
+
+private slots:
+ void processReadyRead();
+
+private:
+ QPointer<QTcpSocket> m_socket;
+};
+
+#endif
diff --git a/chicken-wranglers/src/network/udphandler.cpp b/chicken-wranglers/src/network/udphandler.cpp
new file mode 100644
index 0000000..2aa2635
--- /dev/null
+++ b/chicken-wranglers/src/network/udphandler.cpp
@@ -0,0 +1,169 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+#include <QtCore/QTime>
+#include <QtNetwork/QUdpSocket>
+
+#include "network.h"
+#include "settings.h"
+
+#include "udphandler.h"
+
+UdpHandler::UdpHandler(QObject *parent)
+ : QObject(parent), m_listenSenderType(CW::UdpSenderServer), m_listenPort(0)
+{
+ m_socket = new QUdpSocket(this);
+
+ connect(m_socket, SIGNAL(readyRead()), this, SLOT(processIncomingDatagrams()));
+}
+
+UdpHandler::~UdpHandler()
+{
+ disable();
+}
+
+void UdpHandler::enable()
+{
+ for (quint16 i = 0; i < 100; i++) {
+ m_listenPort += i;
+
+ if (m_socket->bind(QHostAddress::Any, m_listenPort,
+ QUdpSocket::DontShareAddress)) {
+ qWarning("UDP Socket bound to port %d", m_listenPort);
+
+ break;
+ }
+ }
+}
+
+void UdpHandler::disable()
+{
+ m_socket->close();
+}
+
+void UdpHandler::setListenSenderType(const CW::UdpSenderType &type)
+{
+ m_listenSenderType = type;
+}
+
+CW::UdpSenderType UdpHandler::listenSenderType() const
+{
+ return m_listenSenderType;
+}
+
+void UdpHandler::setListenPort(const quint16 &port)
+{
+ if (m_listenPort != port)
+ m_listenPort = port;
+}
+
+quint16 UdpHandler::listenPort() const
+{
+ return m_listenPort;
+}
+
+void UdpHandler::processIncomingDatagrams()
+{
+ QByteArray datagram;
+ QHostAddress senderAddress;
+ quint16 senderPort;
+
+ while (m_socket->hasPendingDatagrams()) {
+ datagram.resize(m_socket->pendingDatagramSize());
+
+ if (m_socket->readDatagram(datagram.data(), datagram.size(),
+ &senderAddress, &senderPort) == -1) {
+ qWarning("UDP Error: Unable to read datagram.");
+ } else {
+ parseDatagram(senderAddress, senderPort, datagram);
+ }
+
+ datagram.clear();
+ }
+}
+
+void UdpHandler::parseDatagram(QHostAddress address, quint16 port, QByteArray datagram)
+{
+ QList<QByteArray> fields = datagram.split(CW::udpMessageSeparator);
+ QTime time = QTime::currentTime();
+
+ // Message size correct (=4)
+ if (fields.size() == 4) {
+ // Message type received (='type specified')
+ if (fields.at(0).toUShort() & m_listenSenderType) {
+ qWarning("UDP Received:\t\"%s\"", datagram.constData());
+
+ emit received(address, fields.at(1), port, fields.at(2));
+ } else {
+ qWarning("UDP Invalid sender type:\"%s\"", datagram.constData());
+ }
+ } else {
+ qWarning("UDP Invalid message size:\"%s\"", datagram.constData());
+ }
+}
+
+void UdpHandler::sendDatagram(QHostAddress address, quint16 port, CW::UdpSenderType senderType,
+ CW::UdpContentType content, quint16 senderListenPort)
+{
+ QTime time;
+ QByteArray datagram;
+
+ // Message format:
+ // "client/content/senderListenPort/11:22:33.444"
+
+ // Timestamp
+ time = QTime::currentTime();
+
+ // Message type: Client or Server
+ datagram = QByteArray::number(senderType);
+
+ // Message content: content
+ datagram += CW::udpMessageSeparator + QByteArray::number((quint16) content);
+
+ // Message content: sender listen port
+ datagram += CW::udpMessageSeparator + QByteArray::number((quint16) senderListenPort);
+
+ // Message timestamp: hours:minutes:seconds.miliseconds
+ datagram += CW::udpMessageSeparator + time.toString("hh:mm:ss.zzz").toUtf8();
+
+ m_socket->writeDatagram(datagram.data(), datagram.size(), address, port);
+}
diff --git a/chicken-wranglers/src/network/udphandler.h b/chicken-wranglers/src/network/udphandler.h
new file mode 100644
index 0000000..6c26965
--- /dev/null
+++ b/chicken-wranglers/src/network/udphandler.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+#ifndef UDPHANDLER_H
+#define UDPHANDLER_H
+
+#include "network.h"
+
+#include <QtCore/QByteArray>
+#include <QtCore/QList>
+#include <QtCore/QObject>
+#include <QtNetwork/QHostAddress>
+
+class QUdpSocket;
+
+class UdpHandler : public QObject
+{
+ Q_OBJECT
+
+public:
+ UdpHandler(QObject *parent = 0);
+ ~UdpHandler();
+
+ void enable();
+ void disable();
+
+ void setListenSenderType(const CW::UdpSenderType &type);
+ CW::UdpSenderType listenSenderType() const;
+
+ void setListenPort(const quint16 &port);
+ quint16 listenPort() const;
+
+ void sendDatagram(QHostAddress toAddress, quint16 toPort, CW::UdpSenderType senderType,
+ CW::UdpContentType content, quint16 senderListenPort);
+
+signals:
+ void received(QHostAddress senderAddress, QByteArray content,
+ quint16 senderListenPort, QByteArray timestamp);
+
+private slots:
+ void processIncomingDatagrams();
+
+private:
+ void parseDatagram(QHostAddress address, quint16 port, QByteArray datagram);
+
+ QUdpSocket *m_socket;
+ CW::UdpSenderType m_listenSenderType;
+ quint16 m_listenPort;
+};
+
+#endif
diff --git a/chicken-wranglers/src/qml/Being.qml b/chicken-wranglers/src/qml/Being.qml
new file mode 100644
index 0000000..984ee9b
--- /dev/null
+++ b/chicken-wranglers/src/qml/Being.qml
@@ -0,0 +1,150 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+import Qt 4.7
+
+import "match.js" as MatchLogic
+import game.types 1.0
+
+Image {
+ id: being
+
+ property string path: ""
+ property int currentRow: 0
+ property int currentColumn: 0
+ property int walkingStep: 1
+ property string orientation: "side_"
+ property string movement: "stopped_"
+
+ // Default values
+ property int moveInterval: 500
+ property int changeStepsInterval: 260
+
+ scale: matchScreen.displayScale
+ smooth: true
+
+ source: {
+ if (path == "")
+ return ""
+
+ path + "/" + orientation + movement + walkingStep + ".png"
+ }
+
+ state: "stopped"
+
+ Timer {
+ id: changeSteps;
+ interval: changeStepsInterval
+ running: (opacity == 1) && (matchController.status != Match.Paused)
+ repeat: true
+ onTriggered: {
+ if (walkingStep == 1)
+ walkingStep = 2
+ else
+ walkingStep = 1
+ }
+ }
+
+ states {
+ State {
+ name: "Up"
+ PropertyChanges {
+ target: being
+ orientation: "back_"
+ movement: "walking_"
+ }
+ }
+
+ State {
+ name: "Down"
+ PropertyChanges {
+ target: being
+ orientation: "front_"
+ movement: "walking_"
+ }
+ }
+
+ State {
+ name: "Left"
+ PropertyChanges {
+ target: being
+ orientation: "side_"
+ movement: "walking_"
+ }
+ }
+
+ State {
+ name: "Right"
+ PropertyChanges {
+ target: being
+ orientation: "side_"
+ movement: "walking_"
+ }
+ PropertyChanges {
+ target: rotation
+ angle: 180
+ }
+ }
+
+ State {
+ name: "Stop"
+ PropertyChanges {
+ target: being
+ movement: "stopped_"
+ orientation: orientation
+ }
+ PropertyChanges {
+ target: rotation
+ angle: angle
+ }
+ }
+ }
+
+ transform {
+ Rotation {
+ id: rotation
+ origin.x: being.width/2; origin.y: being.height/2
+ axis.x: 0; axis.y: 1; axis.z: 0
+ angle: 0
+ }
+ }
+}
diff --git a/chicken-wranglers/src/qml/Character.qml b/chicken-wranglers/src/qml/Character.qml
new file mode 100644
index 0000000..46ab988
--- /dev/null
+++ b/chicken-wranglers/src/qml/Character.qml
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+import Qt 4.7
+
+import "match.js" as MatchLogic
+import game.types 1.0
+
+Being {
+ id: character
+
+ property int playerNumber: 0
+ property PlayerModel model
+ property PlayerController controller
+
+ path: {
+ if (model)
+ return model.characterPath
+ else
+ return ""
+ }
+
+ moveInterval: MatchLogic.characterMoveInterval
+ changeStepsInterval: MatchLogic.characterChangeStepsInterval
+
+ function onLaserToggleRequested(laserDirection) {
+ var column = Math.round((x - matchScreen.fieldStartX - (matchScreen.cellSize - width) / 2) / matchScreen.cellSize)
+ var row = Math.round((y - matchScreen.fieldStartY - (matchScreen.cellSize - height) / 2) / matchScreen.cellSize)
+ matchController.toggleLaser(column, row, laserDirection)
+ }
+
+ x: matchScreen.fieldStartX + (currentColumn * matchScreen.cellSize) + (matchScreen.cellSize - width) / 2
+ y: matchScreen.fieldStartY + (currentRow * matchScreen.cellSize) + (matchScreen.cellSize - height) / 2
+
+ Behavior on x {
+ NumberAnimation {
+ duration: moveInterval;
+ easing.type: Easing.Linear
+ }
+ }
+
+ Behavior on y {
+ NumberAnimation {
+ duration: moveInterval;
+ easing.type: Easing.Linear
+ }
+ }
+
+ Behavior on opacity {
+ NumberAnimation { duration: 200 }
+ }
+
+ currentRow: {
+ if (controller)
+ return controller.position.y
+ else
+ return 4
+ }
+
+ currentColumn: {
+ if (controller)
+ return controller.position.x
+ else
+ return 4
+ }
+
+ opacity: 0
+
+ Timer {
+ id: moveTimer
+
+ triggeredOnStart: true
+ interval: moveInterval;
+ running: model != null && matchController.status != Match.Paused
+ repeat: true
+ onTriggered: {
+ state = model.direction
+ if (controller)
+ controller.move()
+ }
+ }
+}
diff --git a/chicken-wranglers/src/qml/CharacterSelectionView.qml b/chicken-wranglers/src/qml/CharacterSelectionView.qml
new file mode 100644
index 0000000..e28b6f9
--- /dev/null
+++ b/chicken-wranglers/src/qml/CharacterSelectionView.qml
@@ -0,0 +1,235 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+import Qt 4.7
+
+import game.types 1.0
+import "common.js" as Common
+import "widgets"
+
+Screen {
+ id: screen
+
+ signal back
+ signal characterSelected(int index)
+
+ Image {
+ id: background
+
+ anchors.fill: parent
+ source: {
+ if (game.environment() == Global.Symbian)
+ "qrc:/images/general/symbian/bg_selectcharacter.png"
+ else
+ "qrc:/images/general/bg_selectcharacter.png"
+ }
+ }
+
+ Component {
+ id: characterDelegate
+
+ Item {
+ width: 191
+ height: 220
+
+ scale: PathView.iconScale
+
+ Image {
+ id: characterIcon
+
+ y: 0
+ anchors.fill: parent
+ anchors.horizontalCenter: parent.horizontalCenter
+ smooth: true
+ source: {
+ if (isAvailable)
+ Common.getImagePath(path, "select_character.png")
+ else
+ Common.getImagePath(path, "unavailable.png")
+ }
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ view.currentIndex = index
+ }
+ }
+ }
+ }
+
+ Item {
+ id: characterHighlight
+
+ anchors {
+ horizontalCenter: parent.horizontalCenter
+ top: parent.top
+ bottom: view.bottom
+ }
+
+ Image {
+ id: name
+
+ anchors {
+ horizontalCenter: parent.horizontalCenter
+ top: parent.top
+ topMargin: 60
+ }
+
+ smooth: true
+ source: Common.getImagePath(characterListModel.get(view.currentIndex).path, "name.png")
+
+ // XXX: When changing source property, the sourceSize.width
+ // is not updating accordingly. So we are forcing a hardcoded
+ // value for now.
+ onSourceChanged: sourceSize.width = 200
+
+ Behavior on opacity {
+ NumberAnimation { duration: 100 }
+ }
+ }
+
+ ImageButton {
+ source: "qrc:/images/general/bt_previous.png"
+
+ anchors.right: parent.horizontalCenter
+ anchors.rightMargin: 80
+ anchors.verticalCenter: name.verticalCenter
+
+ onClicked: view.decrementCurrentIndex()
+ }
+
+ ImageButton {
+ source: "qrc:/images/general/bt_next.png"
+
+ anchors.left: parent.horizontalCenter
+ anchors.leftMargin: 80
+ anchors.verticalCenter: name.verticalCenter
+
+ onClicked: view.incrementCurrentIndex()
+ }
+ }
+
+ PathView {
+ id: view
+
+ anchors {
+ right: parent.right
+ left: parent.left
+ verticalCenter: parent.verticalCenter
+ verticalCenterOffset: 20
+ }
+
+ height: 220
+ model: characterListModel
+ delegate: characterDelegate
+ preferredHighlightBegin: 0.5
+ preferredHighlightEnd: 0.5
+ pathItemCount: 5
+ highlightMoveDuration: 200
+ dragMargin: 500
+
+ onCurrentIndexChanged: {
+ name.source = Common.getImagePath(characterListModel.get(currentIndex).path, "name.png")
+ }
+
+ onMovementStarted: {
+ name.opacity = 0
+ }
+
+ onMovementEnded: {
+ name.source = Common.getImagePath(characterListModel.get(currentIndex).path, "name.png")
+ name.opacity = 1
+ }
+
+ path: Path {
+ startX: -40
+ startY: 100
+
+ PathAttribute { name: "iconScale"; value: 0.3 }
+
+ PathLine {
+ x: screen.width * 0.5
+ y: 100
+ }
+
+ PathAttribute { name: "iconScale"; value: 1.0 }
+
+ // 4
+ PathLine {
+ x: screen.width + 40
+ y: 100
+ }
+
+ PathAttribute { name: "iconScale"; value: 0.3 }
+ }
+ }
+
+ Button {
+ id: buttonJoin
+
+ text: "Join"
+ width: 200
+ enabled: characterListModel.get(view.currentIndex).isAvailable
+
+ anchors {
+ horizontalCenter: parent.horizontalCenter
+ bottom: parent.bottom
+ margins: 20
+ }
+
+ onClicked: characterSelected(view.currentIndex)
+ }
+
+ ImageButton {
+ id: buttonBack
+
+ anchors {
+ top: parent.top
+ right: parent.right
+ margins: 15
+ }
+
+ name: "back"
+ onClicked: back();
+ }
+}
diff --git a/chicken-wranglers/src/qml/Chicken.qml b/chicken-wranglers/src/qml/Chicken.qml
new file mode 100644
index 0000000..a09e9c1
--- /dev/null
+++ b/chicken-wranglers/src/qml/Chicken.qml
@@ -0,0 +1,159 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+import Qt 4.7
+import "match.js" as MatchLogic
+import game.types 1.0
+
+Being {
+ id: chicken
+
+ property ChickenController controller
+
+ path: "qrc:/images/chicken"
+
+ function kill() {
+ chicken.opacity = 0
+ }
+
+ function onPositionChanged() {
+ currentRow = controller.position.y
+ currentColumn = controller.position.x
+
+ var newX = matchScreen.fieldStartX + (currentColumn * matchScreen.cellSize) + (matchScreen.cellSize - width) / 2
+ var newY = matchScreen.fieldStartY + (currentRow * matchScreen.cellSize) + (matchScreen.cellSize - height) / 2
+
+ moveInterval = chickenMoveInterval
+
+ if (x != newX && !xAnimation.running) {
+ xAnimation.to = newX
+ xAnimation.start()
+ }
+
+ if (y != newY && !yAnimation.running) {
+ yAnimation.to = newY
+ yAnimation.start()
+ }
+ }
+
+ function move() {
+ controller.move()
+ chicken.state = controller.direction
+ }
+
+ opacity: 1
+
+ currentRow: MatchLogic.defaultRows / 2
+ currentColumn: MatchLogic.defaultColumns / 2
+
+ PropertyAnimation {
+ id: xAnimation
+
+ target: chicken
+ property: "x"
+ duration: moveInterval
+ alwaysRunToEnd: true
+
+ onRunningChanged: {
+ if (!running)
+ chicken.move()
+ }
+ }
+
+ PropertyAnimation {
+ id: yAnimation
+
+ target: chicken
+ property: "y"
+ duration: moveInterval
+ alwaysRunToEnd: true
+
+ onRunningChanged: {
+ if (!running)
+ chicken.move()
+ }
+ }
+
+ property int chickenMoveInterval
+
+ chickenMoveInterval: {
+ if (!controller)
+ return MatchLogic.chickenMoveIntervalNormal
+
+ if (controller.isSafe)
+ return MatchLogic.chickenMoveIntervalNormal
+ else
+ return MatchLogic.chickenMoveIntervalRunning
+ }
+
+ changeStepsInterval: MatchLogic.chickenChangeStepsIntervalNormal
+ moveInterval: MatchLogic.chickenMoveIntervalNormal
+
+ onOpacityChanged: {
+ if (opacity == 0)
+ chicken.destroy()
+ }
+
+ Behavior on opacity {
+ NumberAnimation { duration: 500 }
+ }
+
+ Timer {
+ id: move;
+ interval: chickenMoveInterval
+ running: state == "Stop" && matchController.status != Match.Paused
+ repeat: true
+ onTriggered: {
+ chicken.move()
+
+ if (currentRow < 0 || currentColumn < 0
+ || currentRow >= MatchLogic.defaultRows
+ || currentColumn >= MatchLogic.defaultColumns) {
+ chicken.kill()
+ }
+ }
+ }
+
+ Component.onCompleted: {
+ chicken.state = "Stop"
+ }
+}
diff --git a/chicken-wranglers/src/qml/ClientView.qml b/chicken-wranglers/src/qml/ClientView.qml
new file mode 100644
index 0000000..0bb06af
--- /dev/null
+++ b/chicken-wranglers/src/qml/ClientView.qml
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+import Qt 4.7
+import game.types 1.0
+
+import "widgets"
+import "common.js" as Common
+
+Screen {
+ id: clientView
+
+ focus: true
+
+ function showControlView() {
+ var character = characterListModel.get(characterListModel.selectedIndex)
+
+ playerControlView.characterPath = character.path
+ Common.switchScreens(playerReadyView, playerControlView)
+ playerControlView.focus = true
+ }
+
+ function showPlayerReadyView() {
+ Common.switchScreens(playerControlView, playerReadyView)
+ }
+
+
+ CharacterSelectionView {
+ id: characterSelectionView
+
+ anchors.fill: parent
+
+ onBack: {
+ closeRequested()
+ focus = false
+ }
+
+ onCharacterSelected: {
+ characterListModel.selectedIndex = index
+ var character = characterListModel.get(index)
+
+ if (character.isAvailable) {
+ playerReadyView.characterPath = character.path
+ Common.switchScreens(characterSelectionView, playerReadyView)
+ } else {
+ console.log("Character is not available.");
+ }
+ }
+ }
+
+ PlayerReadyView {
+ id: playerReadyView
+
+ anchors.fill: parent
+ onBack: {
+ characterListModel.selectedIndex = -1
+ Common.switchScreens(playerReadyView, characterSelectionView)
+ focus = false
+ }
+ }
+
+ PlayerControlView {
+ id: playerControlView
+
+ anchors.fill: parent
+ onBack: {
+ characterListModel.selectedIndex = -1
+ Common.switchScreens(playerControlView, characterSelectionView)
+ focus = false
+ }
+ }
+
+ onTransitionFinished: {
+ if (!visible)
+ closeFinished()
+ }
+
+ Component.onCompleted: {
+ characterSelectionView.show()
+ characterSelectionView.focus = true
+ }
+}
diff --git a/chicken-wranglers/src/qml/HenCoop.qml b/chicken-wranglers/src/qml/HenCoop.qml
new file mode 100644
index 0000000..ad5db74
--- /dev/null
+++ b/chicken-wranglers/src/qml/HenCoop.qml
@@ -0,0 +1,149 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+import Qt 4.7
+import game.types 1.0
+
+Item {
+ id: henCoop
+
+ property int playerNumber: 1
+ property PlayerModel player: playerListModel.get(playerNumber - 1)
+ property string side: getSide()
+
+ scale: matchScreen.displayScale
+
+ function getSide () {
+ if ((playerNumber % 2) == 0)
+ return "right"
+
+ return "left"
+ }
+
+ opacity: {
+ if (henCoop.player == null || henCoop.player.characterPath == "")
+ return 0
+ return 1
+ }
+
+ Image {
+ id: plate
+ source: {
+ if (henCoop.player == null || henCoop.player.characterPath == "")
+ return ""
+ "qrc:/images/battlefield/hencoop_plate.png"
+ }
+
+ smooth: true
+ anchors {
+ top: parent.top
+ left: {
+ if (henCoop.side == "left")
+ return parent.left
+ else
+ return undefined
+ }
+ right: {
+ if (henCoop.side == "right")
+ return parent.right
+ else
+ return undefined
+ }
+ }
+ }
+
+ Image {
+ id: house
+
+ smooth: true
+ source: {
+ if (henCoop.player == null || henCoop.player.characterPath == "")
+ return ""
+ return henCoop.player.characterPath + "/hencoop.png"
+ }
+
+ anchors {
+ top: parent.top
+ left: {
+ if (henCoop.side == "left")
+ return parent.left
+ else
+ return undefined
+ }
+ right: {
+ if (henCoop.side == "right")
+ return parent.right
+ else
+ return undefined
+ }
+ leftMargin: 12
+ }
+
+ Text {
+ id: score
+
+ text: {
+ if (player != null)
+ return player.score
+ else
+ return "0"
+ }
+
+ color: "white"
+ style: Text.Outline
+ styleColor: "black"
+ smooth: true
+
+ font {
+ family: "Nokia Sans"
+ pointSize: 30
+ bold: true
+ }
+
+ anchors {
+ horizontalCenter: parent.horizontalCenter
+ top: parent.top
+ topMargin: 20
+ }
+ }
+ }
+}
diff --git a/chicken-wranglers/src/qml/HostView.qml b/chicken-wranglers/src/qml/HostView.qml
new file mode 100644
index 0000000..fd37ab2
--- /dev/null
+++ b/chicken-wranglers/src/qml/HostView.qml
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+import Qt 4.7
+
+import "widgets"
+import "common.js" as Common
+
+Screen {
+ id: hostView
+
+ anchors.fill: parent
+ focus: true
+
+ WaitingRoomView {
+ id: waitingRoomView
+
+ anchors.fill: parent
+
+ onBack: closeRequested()
+
+ onMatchStarted: {
+ matchViewLoader.source = "MatchView.qml"
+ }
+ }
+
+ Loader {
+ id: matchViewLoader
+
+ signal closeRequested
+ signal closeFinished
+
+ anchors.fill: parent
+
+ onLoaded: {
+ Common.switchScreens(waitingRoomView, matchViewLoader.item)
+ focus = true
+ }
+
+ onCloseRequested: Common.switchScreens(matchViewLoader.item, waitingRoomView)
+ onCloseFinished: {
+ matchViewLoader.source = ""
+ }
+ }
+
+ onTransitionFinished: {
+ if (!visible)
+ closeFinished()
+ }
+
+ Component.onCompleted: {
+ waitingRoomView.show()
+ waitingRoomView.focus = true
+ }
+}
diff --git a/chicken-wranglers/src/qml/Laser.qml b/chicken-wranglers/src/qml/Laser.qml
new file mode 100644
index 0000000..2444d0f
--- /dev/null
+++ b/chicken-wranglers/src/qml/Laser.qml
@@ -0,0 +1,147 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+import Qt 4.7
+
+import game.types 1.0
+
+Image {
+ id: laser
+
+ property int step: 1
+ property int maxSteps: 5
+ property string orientation: ""
+ property bool turnedOn: false
+
+ property string path: "qrc:/images/laser/laser_" + orientation + "_" + step + ".png"
+ source: ""
+
+ onSourceChanged: {
+ // FIXME: Laser image's width and height should not
+ // be hardcoded. We are forcing this due to a bug in
+ // Image element after we change source property.
+ if (orientation == "vertical") {
+ laser.width = 27 * matchScreen.displayScale
+ laser.height = 83 * matchScreen.displayScale
+ } else {
+ laser.width = 83 * matchScreen.displayScale
+ laser.height = 27 * matchScreen.displayScale
+ }
+ }
+
+ function turnOn(cellX, cellY, cellSize, direction) {
+ if (direction == Global.LaserLeft || direction == Global.LaserRight)
+ orientation = "vertical"
+ else
+ orientation = "horizontal"
+
+ // FIXME: Same as above.
+ var diffWidth = ((83 * matchScreen.displayScale) - cellSize) / 2
+ var diffHeight = (27 * matchScreen.displayScale) / 2
+
+ if (direction == Global.LaserUp) {
+ laser.x = cellX - diffWidth
+ laser.y = cellY - diffHeight
+ } else if (direction == Global.LaserDown) {
+ laser.x = cellX - diffWidth
+ laser.y = cellY + cellSize - diffHeight
+ } else if (direction == Global.LaserRight) {
+ laser.x = cellX + cellSize - diffHeight
+ laser.y = cellY - diffWidth
+ } else if (direction == Global.LaserLeft) {
+ laser.x = cellX - diffHeight
+ laser.y = cellY - diffWidth
+ }
+
+ step = 0
+ laserOnTimer.start()
+ }
+
+ function turnOff(cell, direction) {
+ step = 4
+ laserOffTimer.start();
+ }
+
+ Timer {
+ id: laserOnTimer
+
+ repeat: true
+ interval: 50
+
+ onTriggered: {
+ if (step == maxSteps - 1) {
+ running = false
+ turnedOn = true
+ return
+ }
+
+ step = step + 1
+ laser.source = path
+ }
+ }
+
+ Timer {
+ id: laserOffTimer
+
+ repeat: true
+ interval: 50
+
+ onTriggered: {
+
+ // FIXME: Check if laser wasn't turned on before
+ // destroying the previous one
+ if (step === 0) {
+ running = false
+ turnedOn = false
+ laser.destroy()
+ return
+ }
+
+ step = step - 1
+
+ if (step == 0)
+ laser.source = ""
+ else
+ laser.source = path
+ }
+ }
+}
diff --git a/chicken-wranglers/src/qml/MatchView.qml b/chicken-wranglers/src/qml/MatchView.qml
new file mode 100644
index 0000000..9f26cb1
--- /dev/null
+++ b/chicken-wranglers/src/qml/MatchView.qml
@@ -0,0 +1,345 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+import Qt 4.7
+
+import game.types 1.0
+import "common.js" as Common
+import "match.js" as MatchLogic
+import "widgets"
+
+Screen {
+ id: matchScreen
+
+ anchors.fill: parent
+ color: "black"
+ smooth: true
+ focus: true
+
+ property real displayScale: MatchLogic.getDisplayScale()
+ property real cellSize: MatchLogic.defaultCellSize * displayScale
+ property real fieldStartX: (MatchLogic.defaultFieldStartX * displayScale) + MatchLogic.deltaX
+ property real fieldStartY: (MatchLogic.defaultFieldStartY * displayScale) + MatchLogic.deltaY
+
+ function showQuitDialog() {
+ quitDialog.show()
+ }
+
+ function closeQuitDialog() {
+ quitDialog.hide()
+ }
+
+ function showScore() {
+ score.show()
+ }
+
+ function hideScore() {
+ score.hide()
+ }
+
+ Image {
+ id: fieldBg
+ source: {
+ if (game.environment() == Global.Symbian)
+ "qrc:/images/battlefield/bg_fence_stones_mobile.png"
+ else
+ "qrc:/images/battlefield/bg_fence_stones.png"
+ }
+ scale : {
+ if (game.environment() == Global.Symbian)
+ 1.0
+ else
+ battleField.scale
+ }
+ smooth: true
+ anchors.centerIn: battleField
+ }
+
+ Item {
+ id: battleField
+ anchors.fill: parent
+ scale: displayScale
+
+ Image {
+ id: topLeftCorner
+
+ property PlayerModel player: playerListModel.get(0)
+
+ opacity: {
+ if (player == null || player.characterPath == "")
+ return 1
+ return 0
+ }
+
+ source: "qrc:/images/battlefield/fence_corner_top_left.png"
+ smooth: true
+ anchors {
+ left: fenceLayer.left
+ top: fenceLayer.top
+ }
+ }
+
+ Image {
+ id: bottomRightCorner
+
+ property PlayerModel player: playerListModel.get(1)
+
+ opacity: {
+ if (player == null || player.characterPath == "")
+ return 1
+ return 0
+ }
+
+ source: "qrc:/images/battlefield/fence_corner_bottom_right.png"
+ smooth: true
+ anchors {
+ right: fenceLayer.right
+ bottom: fenceLayer.bottom
+ }
+ }
+
+ Image {
+ id: bottomLeftCorner
+
+ property PlayerModel player: playerListModel.get(2)
+
+ opacity: {
+ if (player == null || player.characterPath == "")
+ return 1
+ return 0
+ }
+
+ source: "qrc:/images/battlefield/fence_corner_bottom_left.png"
+ smooth: true
+ anchors {
+ left: fenceLayer.left
+ bottom: fenceLayer.bottom
+ }
+ }
+
+ Image {
+ id: topRightCorner
+
+ property PlayerModel player: playerListModel.get(3)
+
+ opacity: {
+ if (player == null || player.characterPath == "")
+ return 1
+ return 0
+ }
+
+ source: "qrc:/images/battlefield/fence_corner_top_right.png"
+ smooth: true
+ anchors {
+ right: fenceLayer.right
+ top: fenceLayer.top
+ }
+ }
+
+ Image {
+ id: fenceLayer
+ source: "qrc:/images/battlefield/fence_layer_over.png"
+ smooth: true
+ anchors.centerIn: parent
+ focus: true
+ }
+
+ Image {
+ id: clockContainer
+ source: "qrc:/images/battlefield/clock.png"
+ smooth: true
+ anchors {
+ top: fenceLayer.top
+ horizontalCenter: parent.horizontalCenter
+ }
+
+ Text {
+ id: clock
+
+ text: matchController.elapsedTime
+ color: "white"
+ style: Text.Outline
+ smooth: true
+
+ font {
+ bold: true
+ family: "Nokia Sans"
+ pointSize: 20
+ }
+
+ anchors.centerIn: parent
+ anchors.verticalCenterOffset: -6
+ }
+ }
+
+ ImageButton {
+ id: quitButton
+ name: "quit"
+ path: "qrc:/images/battlefield"
+ smooth: true
+ anchors {
+ bottom: fenceLayer.bottom
+ horizontalCenter: parent.horizontalCenter
+ }
+
+ onClicked: MatchLogic.askQuitMatch()
+ }
+ }
+
+ HenCoop {
+ playerNumber: 1
+
+ anchors {
+ top: parent.top
+ topMargin: 35
+ left: parent.left
+ leftMargin: 29
+ }
+ }
+
+ HenCoop {
+ playerNumber: 2
+
+ anchors {
+ top: parent.verticalCenter
+ topMargin: 36
+ right: parent.right
+ rightMargin: 29
+ }
+ }
+
+ HenCoop {
+ playerNumber: 3
+
+ anchors {
+ top: parent.verticalCenter
+ topMargin: 36
+ left: parent.left
+ leftMargin: 29
+ }
+ }
+
+ HenCoop {
+ playerNumber: 4
+
+ anchors {
+ top: parent.top
+ topMargin: 35
+ right: parent.right
+ rightMargin: 29
+ }
+ }
+
+ ConfirmationDialog {
+ id: quitDialog
+
+ text: "Do you want to leave this match?"
+ opacity: 0
+
+ onRejected: {
+ closeQuitDialog()
+ MatchLogic.resumeMatch()
+ }
+
+ onAccepted: {
+ closeQuitDialog()
+ MatchLogic.leaveMatch()
+
+ closeRequested()
+ }
+
+ z: 10
+ }
+
+ Score {
+ id: score
+
+ opacity: 0
+
+ onClose: {
+ MatchLogic.leaveMatch()
+ hideScore()
+
+ closeRequested()
+ }
+ }
+
+ Rectangle {
+ id: background
+
+ anchors.fill: parent
+ color: "black"
+ opacity: 0.7
+ z: 49
+
+ MouseArea {
+ anchors.fill: parent
+ }
+
+ Behavior on opacity {
+ PropertyAnimation { duration: 200 }
+ }
+ }
+
+ Countdown {
+ id: countdown
+
+ z: 50
+
+ anchors.fill: parent
+ onTimeout: {
+ background.opacity = 0
+ MatchLogic.startMatch()
+ }
+ }
+
+ onTransitionFinished: {
+ if (visible)
+ countdown.start()
+ else
+ closeFinished()
+ }
+
+ Component.onCompleted: MatchLogic.newMatch()
+
+ Keys.onEscapePressed: MatchLogic.askQuitMatch()
+}
diff --git a/chicken-wranglers/src/qml/PlayerControlView.qml b/chicken-wranglers/src/qml/PlayerControlView.qml
new file mode 100644
index 0000000..b520587
--- /dev/null
+++ b/chicken-wranglers/src/qml/PlayerControlView.qml
@@ -0,0 +1,147 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+import Qt 4.7
+
+import "widgets"
+import "common.js" as Common
+
+Screen {
+ id: screen
+
+ property string characterPath: ""
+ property int margins: -60
+
+ signal back
+
+ focus: true
+
+ Keys.onUpPressed: gameClient.moveUp()
+ Keys.onDownPressed: gameClient.moveDown()
+ Keys.onLeftPressed: gameClient.moveLeft()
+ Keys.onRightPressed: gameClient.moveRight()
+ Keys.onSpacePressed: gameClient.moveStop()
+
+ Keys.onPressed: {
+ switch (event.key) {
+
+ // Quit the game
+ case Qt.Key_Q:
+ back()
+ break
+
+ // Laser shots
+ case Qt.Key_W:
+ gameClient.toggleLaserUp()
+ break
+
+ case Qt.Key_S:
+ gameClient.toggleLaserDown()
+ break
+
+ case Qt.Key_A:
+ gameClient.toggleLaserLeft()
+ break
+
+ case Qt.Key_D:
+ gameClient.toggleLaserRight()
+ break
+ }
+
+ event.accepted = true
+ }
+
+ Image {
+ anchors.fill: parent
+
+ source: Common.getImagePath(characterPath, "control.png")
+ }
+
+ Row {
+ anchors.fill: parent
+
+ Item {
+ width: parent.width / 4
+ height: parent.height
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: gameClient.toggleLaserLeft()
+ }
+ }
+
+ Column {
+ width: parent.width / 2
+ height: parent.height
+
+ Item {
+ width: parent.width
+ height: parent.height / 3 * 2
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: gameClient.toggleLaserUp()
+ }
+ }
+
+ Item {
+ width: parent.width
+ height: parent.height / 3
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: gameClient.toggleLaserDown()
+ }
+ }
+ }
+
+ Item {
+ width: parent.width / 4
+ height: parent.height
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: gameClient.toggleLaserRight()
+ }
+ }
+ }
+}
diff --git a/chicken-wranglers/src/qml/PlayerReadyView.qml b/chicken-wranglers/src/qml/PlayerReadyView.qml
new file mode 100644
index 0000000..41e8c5a
--- /dev/null
+++ b/chicken-wranglers/src/qml/PlayerReadyView.qml
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+import Qt 4.7
+
+import game.types 1.0
+import "widgets"
+import "common.js" as Common
+
+Screen {
+ property string characterPath: ""
+
+ signal back
+
+ anchors.fill: parent
+
+ Image {
+ id: background
+
+ source: {
+ if (game.environment() == Global.Symbian)
+ "qrc:/images/general/symbian/bg_selectcharacter.png"
+ else
+ "qrc:/images/general/bg_selectcharacter.png"
+ }
+ anchors.fill: parent
+ }
+
+
+ Image {
+ id: title
+
+ anchors {
+ top: parent.top
+ horizontalCenter: parent.horizontalCenter
+ margins: 40
+ }
+
+ source: "qrc:/images/general/you_are_ready.png"
+ smooth: true
+ }
+
+ Image {
+ anchors.centerIn: parent
+
+ smooth: true
+ source: Common.getImagePath(characterPath, "select_character.png")
+ }
+
+ Button {
+ text: "Start"
+ width: 200
+
+ // TODO: Enable this button if this client is P1
+ opacity: 0
+
+ anchors {
+ horizontalCenter: parent.horizontalCenter
+ bottom: parent.bottom
+ margins: 20
+ }
+
+ onClicked: console.log("Start game via P1 client")
+ }
+
+ ImageButton {
+ name: "back"
+ onClicked: back()
+
+ anchors {
+ top: parent.top
+ right: parent.right
+ margins: 15
+ }
+ }
+}
diff --git a/chicken-wranglers/src/qml/Score.qml b/chicken-wranglers/src/qml/Score.qml
new file mode 100644
index 0000000..1776386
--- /dev/null
+++ b/chicken-wranglers/src/qml/Score.qml
@@ -0,0 +1,128 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+import Qt 4.7
+import "widgets"
+
+import "match.js" as MatchLogic
+import "common.js" as Common
+
+Item {
+ id: score
+
+ property int numberOfPlayers: playerListModel.count()
+ property int scoreBoxTick: width / (numberOfPlayers + 1)
+
+ signal close
+
+ anchors.fill: parent
+ z: 10
+
+ function sortScore(scoreBox1, scoreBox2) {
+ return (scoreBox2.score - scoreBox1.score)
+ }
+
+ function createScore() {
+ var scoreBoxList = []
+
+ for (var i = 0; i < numberOfPlayers; i++) {
+ var scoreBox
+ scoreBox = MatchLogic.createScoreBox()
+ if (scoreBox == undefined)
+ continue
+
+ var player = playerListModel.get(i)
+ if (player == null)
+ continue
+
+ scoreBox.source = Common.getImagePath(player.characterPath, "score.png")
+ scoreBox.score = player.score
+ scoreBox.z = 15
+ scoreBox.y = 0
+
+ scoreBoxList.push(scoreBox)
+ }
+
+ scoreBoxList.sort(sortScore)
+
+ for (var i = 0; i < scoreBoxList.length; i++)
+ scoreBoxList[i].x = (scoreBoxTick * (i + 1)) - (scoreBoxList[i].width / 2)
+
+ closeTimer.start()
+ }
+
+ function show() {
+ opacity = 1
+ }
+
+ function hide() {
+ opacity = 0
+ }
+
+ Behavior on opacity {
+ NumberAnimation { duration: 500 }
+ }
+
+ Rectangle {
+ anchors.fill: parent
+ color: "black"
+ opacity: 0.8
+
+ MouseArea {
+ anchors.fill: parent
+ }
+ }
+
+ Timer {
+ id: closeTimer
+
+ interval: 5000
+
+ onTriggered: close()
+ }
+
+ onOpacityChanged: {
+ if (opacity == 1) {
+ createScore()
+ }
+ }
+}
diff --git a/chicken-wranglers/src/qml/ScoreBox.qml b/chicken-wranglers/src/qml/ScoreBox.qml
new file mode 100644
index 0000000..ef2f19d
--- /dev/null
+++ b/chicken-wranglers/src/qml/ScoreBox.qml
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+import Qt 4.7
+
+Image {
+ id: scoreBox
+
+ property int score: 0
+
+ y: -593 * matchScreen.displayScale // FIXME: Use image height instead
+ smooth: true
+ width: scoreBox.sourceSize.width * matchScreen.displayScale
+ height: scoreBox.sourceSize.height * matchScreen.displayScale
+
+ Text {
+ text: score
+ style: Text.Outline
+ color: "white"
+ smooth: true
+
+ font {
+ family: "Nokia Sans"
+ pointSize: 60 * matchScreen.displayScale
+ bold: true
+ }
+
+ anchors {
+ horizontalCenter: parent.horizontalCenter
+ bottom: parent.bottom
+ bottomMargin: 30 * matchScreen.displayScale
+ }
+ }
+
+ Behavior on y {
+ PropertyAnimation {
+ duration: 1000
+ easing.type: Easing.OutBounce
+ }
+ }
+}
+
diff --git a/chicken-wranglers/src/qml/Splash.qml b/chicken-wranglers/src/qml/Splash.qml
new file mode 100644
index 0000000..5a1aa38
--- /dev/null
+++ b/chicken-wranglers/src/qml/Splash.qml
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+import Qt 4.7
+
+import game.types 1.0
+import "widgets"
+
+Screen {
+ id: screen
+
+ property int time: 1500
+
+ Image {
+ id: background
+
+ smooth: true
+
+ anchors.fill: parent
+ source: {
+ if (game.environment() == Global.Symbian)
+ "qrc:/images/general/symbian/bg_splash.png"
+ else
+ "qrc:/images/general/bg_splash.png"
+ }
+ }
+
+ Timer {
+ running: true
+ interval: time
+ repeat: false
+
+ onTriggered: timeout()
+ }
+
+ onTransitionFinished: {
+ if (!visible)
+ closeFinished()
+ }
+}
diff --git a/chicken-wranglers/src/qml/StartView.qml b/chicken-wranglers/src/qml/StartView.qml
new file mode 100644
index 0000000..fd2905d
--- /dev/null
+++ b/chicken-wranglers/src/qml/StartView.qml
@@ -0,0 +1,246 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+import Qt 4.7
+import game.types 1.0
+
+import "client.js" as Client
+import "host.js" as Host
+import "widgets"
+
+Screen {
+ id: screen
+
+ signal hostSelected
+ signal clientSelected
+ signal clientDiscoveryCanceled
+
+ function showStartServerDialog() {
+ startServerDialog.show()
+ }
+
+ function hideStartServerDialog() {
+ startServerDialog.hide()
+ }
+
+ function showStartClientDialog() {
+ if (game.connectivity == "bluetooth") {
+ connectivityDialog.model = connectivityListModel
+ connectivityDialog.show()
+ } else {
+ startClientDialog.show()
+ }
+ }
+
+ function hideStartClientDialog() {
+ if (game.connectivity == "bluetooth") {
+ gameClient.scanCanceled()
+ connectivityDialog.hide()
+ } else
+ startClientDialog.hide()
+ }
+
+ function showErrorDialog(msg) {
+ errorDialog.text = msg
+ errorDialog.show()
+ }
+
+ function hideErrorDialog() {
+ errorDialog.hide()
+ }
+
+ onHostSelected: Host.start()
+ onClientSelected: Client.start()
+
+ Image {
+ id: background
+
+ smooth: true
+ anchors.fill: parent
+
+ source: {
+ if (game.environment() == Global.Symbian)
+ "qrc:/images/general/symbian/bg_640x360.png"
+ else if (game.environment() == Global.Maemo)
+ "qrc:/images/general/bg_800x480.png"
+ else
+ "qrc:/images/general/bg_1280x768.png"
+ }
+ }
+
+ FeatherFall {
+ id: featherFall
+ number: {
+ if (game.environment() == Global.Symbian)
+ 2
+ else if (game.environment() == Global.Maemo)
+ 3
+ else
+ 5
+ }
+ fallWidth:{
+ if (game.environment() == Global.Symbian)
+ 640
+ else
+ 800
+ }
+ fallHeight:{
+ if (game.environment() == Global.Symbian)
+ 360
+ else
+ 768
+ }
+
+ anchors.fill: parent
+ }
+
+ Item {
+ anchors {
+ centerIn: parent
+ horizontalCenterOffset: 90
+ verticalCenterOffset: 120
+ margins: 100
+ }
+
+ Button {
+ id: hostGameButton
+
+ anchors {
+ right: parent.right
+ bottom: parent.bottom
+ }
+
+ text: "Host game"
+ width: 200
+ onClicked: hostSelected()
+ }
+
+ Button {
+ id: joinGameButton
+
+ anchors {
+ left: parent.left
+ leftMargin: 10
+ bottom: parent.bottom
+ }
+
+ text: "Join game"
+ width: 200
+ onClicked: clientSelected()
+ }
+ }
+
+ ImageButton {
+ anchors {
+ top: parent.top
+ left: parent.left
+ margins: 15
+ }
+
+ name: "close"
+ onClicked: Qt.quit()
+ }
+
+ ToggleButton {
+ anchors {
+ top: parent.top
+ right: parent.right
+ margins: 15
+ }
+ }
+
+ MessageDialog {
+ id: startClientDialog
+
+ text: "Searching for server"
+ buttonText: "Cancel"
+ opacity: 0
+
+ Loading {
+ anchors.horizontalCenter: startClientDialog.box.horizontalCenter
+ anchors.bottom: startClientDialog.box.bottom
+ anchors.bottomMargin: 100
+ }
+
+ onButtonClicked: clientDiscoveryCanceled()
+ }
+
+ ConnectivityDialog {
+ id: connectivityDialog
+
+ opacity: 0
+ onCancel: {
+ connectivityDialog.hide()
+ gameClient.scanCanceled()
+ }
+ }
+
+ MessageDialog {
+ id: startServerDialog
+
+ text: "Creating server"
+ opacity: 0
+
+ Loading {
+ anchors.horizontalCenter: startServerDialog.box.horizontalCenter
+ anchors.bottom: startServerDialog.box.bottom
+ anchors.bottomMargin: 100
+ }
+ }
+
+ MessageDialog {
+ id: errorDialog
+
+ text: "error"
+ buttonText: "Close"
+ opacity: 0
+
+ onButtonClicked: hideErrorDialog()
+ }
+
+ onOpacityChanged: {
+ if (opacity == 1)
+ featherFall.start()
+ else if (opacity == 0)
+ featherFall.stop()
+ }
+}
diff --git a/chicken-wranglers/src/qml/WaitingRoomView.qml b/chicken-wranglers/src/qml/WaitingRoomView.qml
new file mode 100644
index 0000000..64b0bea
--- /dev/null
+++ b/chicken-wranglers/src/qml/WaitingRoomView.qml
@@ -0,0 +1,288 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+import Qt 4.7
+
+import game.types 1.0
+import "common.js" as Common
+import "widgets"
+
+Screen {
+ id: screen
+
+ signal back
+ signal matchStarted
+
+ Keys.onReturnPressed: {
+ if (buttonStart.enabled)
+ matchStarted()
+ }
+
+ Image {
+ id: background
+ smooth: true
+ anchors.fill: parent
+ source: {
+ if (game.environment() == Global.Symbian)
+ "qrc:/images/general/symbian/bg_640x360.png"
+ else if (game.environment() == Global.Maemo)
+ "qrc:/images/general/bg_800x480.png"
+ else
+ "qrc:/images/general/bg_1280x768.png"
+ }
+ }
+
+ ImageButton {
+ anchors {
+ left: screen.left
+ top: screen.top
+ margins: 15
+ }
+
+ name: "back"
+ onClicked: back()
+ }
+
+
+ Button {
+ id: buttonStart
+
+ anchors {
+ top: screen.top
+ right: screen.right
+ margins: 15
+ }
+
+ width: 160
+ text: "Start"
+ sourceName: "bt_start"
+ rightBorder: 35
+ horizontalCenterOffset: -6
+ italic: true
+
+ enabled: playerListModel.playersReady;
+
+ onClicked: matchStarted()
+ }
+
+ ListView {
+ id: playerListView
+ anchors {
+ centerIn: parent
+ horizontalCenterOffset: 30
+ verticalCenterOffset: 130
+ }
+
+ height: 400
+ width: 400
+ model: playerListModel
+ delegate: playerListDelegate
+ interactive: false
+ }
+
+ Component {
+ id: playerListDelegate
+
+ Item {
+ id: delegatePlayer
+
+ scale: {
+ if (game.environment() == Global.Symbian)
+ 0.7
+ else
+ 1
+ }
+
+ width: 400
+ height: 80
+
+ property bool isReady: status == PlayerModel.Ready
+
+ states {
+ State {
+ name: "playerReady"; when: isReady
+ PropertyChanges { target: playerInfo; opacity: 1 }
+ PropertyChanges { target: playerInfoUnknown; opacity: 0 }
+ }
+ }
+
+ Image {
+ id: listItemBg
+
+ anchors {
+ top: playerInfoUnknown.top
+ topMargin: 32
+ }
+
+ source: "qrc:/images/general/list_name_bg.png"
+ }
+
+ Item {
+ id: playerInfoUnknown
+
+ Image {
+ id: listItemIconUnknown
+
+ smooth: true
+
+ anchors {
+ top: parent.top
+ left: parent.left
+ leftMargin: 25
+ }
+
+ source: "qrc:/images/general/list_unknown_character.png"
+ fillMode: Image.PreserveAspectFit
+ }
+
+ Loading {
+ id: listItemLoading
+
+ anchors {
+ left: listItemIconUnknown.right
+ leftMargin: 40
+ bottom: listItemIconUnknown.bottom
+ bottomMargin: 20
+ }
+ }
+
+ }
+
+ Item {
+ id: playerInfo
+
+ opacity: 0
+
+ Image {
+ id: listItemIcon
+
+ smooth: true
+
+ anchors {
+ top: parent.top
+ left: parent.left
+ leftMargin: 25
+ }
+
+ source: Common.getImagePath(characterPath, "waitinglist.png")
+ fillMode: Image.PreserveAspectFit
+ }
+
+
+ Item {
+ id: listItemNameOk
+
+ anchors {
+ left: listItemIcon.right
+ leftMargin: 15
+ bottom: listItemIcon.bottom
+ bottomMargin: 12
+ }
+
+ Image {
+ id: listItemName
+
+ smooth: true
+
+ anchors {
+ left: listItemNameOk.left
+ bottom: listItemNameOk.bottom
+ }
+
+ source: Common.getImagePath(characterPath, "name.png")
+ fillMode: Image.PreserveAspectFit
+ }
+
+ Image {
+ id: listItemOk
+
+ smooth: true
+
+ anchors {
+ left: listItemName.right
+ leftMargin: 30
+ verticalCenter: listItemName.verticalCenter
+ }
+
+ source: "qrc:/images/general/list_status_ok.png"
+ fillMode: Image.PreserveAspectFit
+ }
+ }
+
+ ParallelAnimation {
+ id: anim
+
+ SequentialAnimation {
+ PropertyAnimation {
+ target: listItemIcon
+ property: "scale"
+ duration: 300
+ easing.type: Easing.InOutBack
+ to: 2
+ }
+ PropertyAnimation {
+ target: listItemIcon
+ property: "scale"
+ duration: 200
+ to: 1
+ }
+ }
+ }
+
+ onOpacityChanged: {
+ anim.running = true
+ }
+ }
+
+ ListView.onAdd: SequentialAnimation {
+ PropertyAction { target: delegatePlayer; property: "scale"; value: 0 }
+ NumberAnimation { target: delegatePlayer; property: "scale"; to: 1; duration: 250; easing.type: Easing.InOutQuad }
+ }
+
+ ListView.onRemove: SequentialAnimation {
+ PropertyAction { target: delegatePlayer; property: "ListView.delayRemove"; value: true }
+ NumberAnimation { target: delegatePlayer; property: "scale"; to: 0; duration: 250; easing.type: Easing.InOutQuad }
+ PropertyAction { target: delegatePlayer; property: "ListView.delayRemove"; value: false }
+ }
+ }
+ }
+}
diff --git a/chicken-wranglers/src/qml/client.js b/chicken-wranglers/src/qml/client.js
new file mode 100644
index 0000000..16eb9f8
--- /dev/null
+++ b/chicken-wranglers/src/qml/client.js
@@ -0,0 +1,72 @@
+function start() {
+ game.mode = Game.ClientMode
+
+ startViewLoader.item.showStartClientDialog("Looking for server")
+ startViewLoader.item.clientDiscoveryCanceled.connect(cancelDiscovery)
+
+ // gameClient only exists after game.mode is set to Game.ClientMode
+ gameClient.statusChanged.connect(onStatusChanged)
+ gameClient.startConnection()
+}
+
+function cancelDiscovery() {
+ if (gameClient.status == GameClient.Joined) {
+ gameClient.statusChanged.disconnect(onStatusChanged)
+ startViewLoader.item.clientDiscoveryCanceled.disconnect(cancelDiscovery)
+ startViewLoader.item.hideStartClientDialog()
+ return
+ }
+
+ quit()
+}
+
+function quit() {
+ gameClient.statusChanged.disconnect(onStatusChanged)
+ startViewLoader.item.clientDiscoveryCanceled.disconnect(cancelDiscovery)
+ startViewLoader.item.hideStartClientDialog()
+
+ gameClient.quit()
+}
+
+function onStatusChanged() {
+ switch (gameClient.status) {
+
+ case GameClient.Joined:
+ startViewLoader.item.hideStartClientDialog()
+ clientViewLoader.source = "ClientView.qml"
+ break
+
+ case GameClient.LeftMatch:
+ clientViewLoader.item.showPlayerReadyView()
+ break
+
+ case GameClient.Ready:
+ clientViewLoader.item.showControlView()
+ break
+
+ case GameClient.Error:
+ startViewLoader.item.hideStartClientDialog()
+ handleError(gameClient.error)
+ break
+
+ default:
+ console.log("Unknown client status")
+ }
+}
+
+function handleError(error) {
+ switch (error) {
+
+ case GameClient.ServerDiscoveryTimeoutError:
+ startViewLoader.item.showErrorDialog("Host not found")
+ break
+
+ case GameClient.SocketError:
+ clientViewLoader.closeRequested()
+ startViewLoader.item.showErrorDialog("Disconnected from host")
+ break
+
+ default:
+ console.log("Unknown client error")
+ }
+}
diff --git a/chicken-wranglers/src/qml/common.js b/chicken-wranglers/src/qml/common.js
new file mode 100644
index 0000000..2ce1585
--- /dev/null
+++ b/chicken-wranglers/src/qml/common.js
@@ -0,0 +1,26 @@
+var tempFrom
+var tempTo
+
+function switchScreens(from, to) {
+ if (!from || !to)
+ return
+
+ tempFrom = from
+ tempTo = to
+
+ from.hide()
+ from.opacityChanged.connect(showNextScreen)
+}
+
+function showNextScreen() {
+ if (tempFrom.opacity == 0) {
+ tempTo.show()
+ }
+}
+
+function getImagePath(basePath, fileName) {
+ if (basePath == "")
+ return ""
+
+ return basePath + "/" + fileName
+}
diff --git a/chicken-wranglers/src/qml/host.js b/chicken-wranglers/src/qml/host.js
new file mode 100644
index 0000000..d545c31
--- /dev/null
+++ b/chicken-wranglers/src/qml/host.js
@@ -0,0 +1,46 @@
+function start() {
+ game.mode = Game.HostMode
+
+ startViewLoader.item.showStartServerDialog("Creating server")
+
+ // gameHosts only exists after game.mode is set to Game.HostMode
+ gameHost.statusChanged.connect(onStatusChanged)
+ gameHost.startConnection()
+}
+
+function quit() {
+ gameHost.statusChanged.disconnect(onStatusChanged)
+ startViewLoader.item.hideStartServerDialog()
+
+ gameHost.quit();
+}
+
+function onStatusChanged() {
+ switch (gameHost.status) {
+
+ case GameHost.Start:
+ startViewLoader.item.hideStartServerDialog()
+ hostViewLoader.source = "HostView.qml"
+ break
+
+ case GameHost.Error:
+ startViewLoader.item.hideStartServerDialog()
+ handleError(gameHost.error)
+ break
+
+ default:
+ console.log("Unknown server status")
+ }
+}
+
+function handleError(error) {
+ switch (error) {
+
+ case GameHost.AnotherServerRunningError:
+ startViewLoader.item.showErrorDialog("Server is already running")
+ break
+
+ default:
+ console.log("Unknown server error")
+ }
+}
diff --git a/chicken-wranglers/src/qml/main.qml b/chicken-wranglers/src/qml/main.qml
new file mode 100644
index 0000000..32ac3f3
--- /dev/null
+++ b/chicken-wranglers/src/qml/main.qml
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+import Qt 4.7
+import game.types 1.0
+
+import "common.js" as Common
+import "host.js" as Host
+import "client.js" as Client
+import "widgets"
+
+Rectangle {
+ id: main
+
+ width: 800
+ height: 480
+
+ focus: true
+
+ SystemPalette { id: activePalette }
+
+ Loader {
+ id: splashScreenLoader
+
+ signal closeFinished
+ signal timeout
+
+ anchors.fill: parent
+
+ onLoaded: splashScreenLoader.item.show()
+ onTimeout: startViewLoader.source = "StartView.qml"
+ onCloseFinished: {
+ splashScreenLoader.source = ""
+ game.startBackgroundSound()
+ }
+ }
+
+ Loader {
+ id: startViewLoader
+
+ anchors.fill: parent
+
+ onLoaded: Common.switchScreens(splashScreenLoader.item, startViewLoader.item)
+ }
+
+ Loader {
+ id: hostViewLoader
+
+ signal closeRequested
+ signal closeFinished
+
+ anchors.fill: parent
+
+ onLoaded: {
+ focus = true
+ Common.switchScreens(startViewLoader.item, hostViewLoader.item)
+ }
+
+ onCloseRequested: Common.switchScreens(hostViewLoader.item, startViewLoader.item)
+ onCloseFinished: {
+ Host.quit()
+ hostViewLoader.source = ""
+ }
+ }
+
+ Loader {
+ id: clientViewLoader
+
+ signal closeRequested
+ signal closeFinished
+
+ anchors.fill: parent
+
+ onLoaded: {
+ focus = true
+ Common.switchScreens(startViewLoader.item, clientViewLoader.item)
+ }
+
+ onCloseRequested: Common.switchScreens(clientViewLoader.item, startViewLoader.item)
+ onCloseFinished: {
+ Client.quit()
+ clientViewLoader.source = ""
+ }
+ }
+
+ Component.onCompleted: splashScreenLoader.source = "Splash.qml"
+}
diff --git a/chicken-wranglers/src/qml/match.js b/chicken-wranglers/src/qml/match.js
new file mode 100644
index 0000000..be9628e
--- /dev/null
+++ b/chicken-wranglers/src/qml/match.js
@@ -0,0 +1,310 @@
+var defaultRows = settings.battlefieldSize().height
+var defaultColumns = settings.battlefieldSize().width
+var defaultFieldStartX = settings.battlefieldStartPoint().x
+var defaultFieldStartY = settings.battlefieldStartPoint().y
+var defaultCellSize = settings.battlefieldCellSize()
+var defaultHostWidth = settings.hostDisplaySize().width
+var defaultHostHeight = settings.hostDisplaySize().height
+
+// FIXME: Find better naming and place for these variables
+var deltaX = 0
+var deltaY = 0
+
+// Chicken values
+var chickenMoveIntervalNormal = settings.matchChickenMoveInterval()
+var chickenMoveIntervalRunning = chickenMoveIntervalNormal * 0.7
+var chickenChangeStepsIntervalNormal = settings.matchChickenChangeStepsInterval()
+var chickenChangeStepsIntervalRunning = chickenChangeStepsIntervalNormal * 0.7
+
+// Character values
+var characterMoveInterval = settings.matchCharacterMoveInterval()
+var characterChangeStepsInterval = settings.matchChickenChangeStepsInterval()
+
+var chickenComponent = null
+var playerComponent = null
+var playerScoreComponent = null
+var henCoopComponent = null
+var laserComponent = null
+
+var verticalLaserArray = null
+var horizontalLaserArray = null
+var chickenArray = new Array()
+var playerArray = new Array()
+
+function initLaserArrays()
+{
+ verticalLaserArray = new Array(defaultRows)
+ for (var y = 0; y < defaultRows; y++)
+ verticalLaserArray[y] = new Array(defaultColumns - 1)
+
+ horizontalLaserArray = new Array(defaultRows - 1)
+ for (var y = 0; y < defaultRows - 1; y++)
+ horizontalLaserArray[y] = new Array(defaultColumns)
+
+ for (var y = 0; y < defaultRows; y++)
+ for (var x = 0; x < defaultColumns - 1; x++)
+ verticalLaserArray[y][x] = null
+
+ for (var y = 0; y < defaultRows - 1; y++)
+ for (var x = 0; x < defaultColumns; x++)
+ horizontalLaserArray[y][x] = null
+}
+
+function destroyLasers()
+{
+ for (var y = 0; y < defaultRows; y++)
+ for (var x = 0; x < defaultColumns - 1; x++) {
+ if (verticalLaserArray[y][x] != null && verticalLaserArray[y][x] != undefined) {
+ verticalLaserArray[y][x].destroy()
+ verticalLaserArray[y][x] = null
+ }
+ }
+
+ for (var y = 0; y < defaultRows - 1; y++)
+ for (var x = 0; x < defaultColumns; x++) {
+ if (horizontalLaserArray[y][x] != null && horizontalLaserArray[y][x] != undefined) {
+ horizontalLaserArray[y][x].destroy()
+ horizontalLaserArray[y][x] = null
+ }
+ }
+}
+
+function getDisplayScale() {
+ var scaleX = game.displaySize.width / defaultHostWidth
+ var scaleY = game.displaySize.height / defaultHostHeight
+
+ var max = Math.max(scaleX, scaleY)
+ deltaX = ((max - scaleY) * defaultHostWidth) / 2
+ deltaY = ((max - scaleX) * defaultHostHeight) / 2
+
+ return Math.min(scaleX, scaleY)
+}
+
+function newMatch() {
+ gameHost.status = GameHost.Match
+
+ initLaserArrays();
+
+ matchController.chickenCreated.connect(onChickenCreated);
+ matchController.playerCreated.connect(onPlayerCreated);
+ matchController.laserUpdated.connect(onLaserUpdated);
+ matchController.matchFinished.connect(onMatchFinished);
+
+ matchController.setupMatch()
+ matchController.status = Match.Paused
+}
+
+function startMatch() {
+ matchController.status = Match.Started
+
+ for (var i = 0; i < playerArray.length; i++)
+ playerArray[i].opacity = 1
+}
+
+function askQuitMatch() {
+ if (matchController.status == Match.Running)
+ matchController.status = Match.Paused
+
+ matchScreen.showQuitDialog()
+}
+
+function resumeMatch() {
+ matchController.status = Match.Running
+}
+
+function leaveMatch() {
+ destroyChickens()
+ destroyPlayers()
+ destroyLasers()
+
+ matchController.status = Match.Over
+}
+
+function onMatchFinished() {
+ matchController.status = Match.Paused
+
+ matchScreen.showScore()
+}
+
+function destroyChickens()
+{
+ for (var i = 0; i < chickenArray.length; i++)
+ if (chickenArray[i] != undefined && chickenArray[i] != null) {
+ chickenArray[i].destroy()
+ chickenArray[i] = null
+ }
+}
+
+function destroyPlayers()
+{
+ for (var i = 0; i < playerArray.length; i++)
+ if (playerArray[i] != undefined && playerArray[i] != null) {
+ playerArray[i].destroy()
+ playerArray[i] = null
+ }
+}
+
+function onChickenCreated(id)
+{
+ if (chickenComponent == null)
+ chickenComponent = Qt.createComponent("Chicken.qml");
+
+ if (chickenComponent.status == Component.Ready) {
+ var dynamicObject = chickenComponent.createObject(matchScreen);
+ if (dynamicObject == null) {
+ console.log("error creating chicken");
+ console.log(chickenComponent.errorString());
+ return false;
+ }
+
+ chickenArray[id] = dynamicObject
+
+ var chickenController = matchController.getChicken(id)
+ chickenController.positionChanged.connect(dynamicObject.onPositionChanged)
+ dynamicObject.controller = chickenController
+ dynamicObject.x = matchScreen.fieldStartX + (chickenController.position.x * matchScreen.cellSize) + (matchScreen.cellSize - dynamicObject.width) / 2
+ dynamicObject.y = matchScreen.fieldStartY + (chickenController.position.y * matchScreen.cellSize) + (matchScreen.cellSize - dynamicObject.height) / 2
+ } else {
+ console.log("error loading block chickenComponent");
+ console.log(chickenComponent.errorString());
+ return false;
+ }
+
+ return true;
+}
+
+function onPlayerCreated(id)
+{
+ if (playerComponent == null)
+ playerComponent = Qt.createComponent("Character.qml");
+
+ if (playerComponent.status == Component.Ready) {
+ // TODO: Only players with status Ready should be added
+ var dynamicObject = playerComponent.createObject(matchScreen);
+ if (dynamicObject == null) {
+ console.log("error creating character");
+ console.log(playerComponent.errorString());
+ return false;
+ }
+
+ dynamicObject.playerNumber = id
+ playerArray[id] = dynamicObject
+
+ var playerController = matchController.getPlayer(id)
+ dynamicObject.controller = playerController
+ playerController.laserToggleRequested.connect(dynamicObject.onLaserToggleRequested)
+
+ dynamicObject.model = playerListModel.get(id)
+ } else {
+ console.log("error loading block playerComponent");
+ console.log(playerComponent.errorString());
+ return false;
+ }
+
+ return true;
+}
+
+function createScoreBox()
+{
+ if (playerScoreComponent == null)
+ playerScoreComponent = Qt.createComponent("ScoreBox.qml");
+
+ var dynamicObject = null;
+
+ if (playerScoreComponent.status == Component.Ready) {
+ dynamicObject = playerScoreComponent.createObject(score);
+ if (dynamicObject == null) {
+ console.log("error creating laser");
+ console.log(playerScoreComponent.errorString());
+ return null;
+ }
+ } else {
+ console.log("error loading block playerScoreComponent");
+ console.log(playerScoreComponent.errorString());
+ return null;
+ }
+
+ return dynamicObject
+
+}
+
+function createLaser()
+{
+ if (laserComponent == null)
+ laserComponent = Qt.createComponent("Laser.qml");
+
+ var dynamicObject = null;
+
+ if (laserComponent.status == Component.Ready) {
+ dynamicObject = laserComponent.createObject(matchScreen);
+ if (dynamicObject == null) {
+ console.log("error creating laser");
+ console.log(laserComponent.errorString());
+ return null;
+ }
+ } else {
+ console.log("error loading block laserComponent");
+ console.log(laserComponent.errorString());
+ return null;
+ }
+
+ return dynamicObject
+}
+
+function removeLaser(x, y, direction)
+{
+ var laserObj = null
+
+ if (direction == Global.LaserRight && x < defaultColumns - 1) {
+ laserObj = verticalLaserArray[y][x]
+ verticalLaserArray[y][x] = null
+ } else if (direction == Global.LaserLeft && x >= 0) {
+ laserObj = verticalLaserArray[y][x - 1]
+ verticalLaserArray[y][x - 1] = null
+ } else if (direction == Global.LaserUp && y > 0) {
+ laserObj = horizontalLaserArray[y - 1][x]
+ horizontalLaserArray[y - 1][x] = null
+ } else if (direction == Global.LaserDown && y < defaultRows - 1) {
+ laserObj = horizontalLaserArray[y][x]
+ horizontalLaserArray[y][x] = null
+ }
+
+ if (laserObj == null)
+ return
+
+ var cellX = matchScreen.fieldStartX + x * (defaultCellSize * matchScreen.displayScale)
+ var cellY = matchScreen.fieldStartY + y * (defaultCellSize * matchScreen.displayScale)
+
+ laserObj.turnOff(cellX, cellY, defaultCellSize * matchScreen.displayScale, direction)
+}
+
+function addLaser(x, y, direction)
+{
+ var laserObj = createLaser();
+
+ if (direction == Global.LaserRight && verticalLaserArray[y][x] == null)
+ verticalLaserArray[y][x] = laserObj
+ else if (direction == Global.LaserLeft && verticalLaserArray[y][x - 1] == null)
+ verticalLaserArray[y][x - 1] = laserObj
+ else if (direction == Global.LaserUp && horizontalLaserArray[y - 1][x] == null)
+ horizontalLaserArray[y - 1][x] = laserObj
+ else if (direction == Global.LaserDown && horizontalLaserArray[y][x] == null)
+ horizontalLaserArray[y][x] = laserObj
+ else {
+ laserObj.destroy()
+ return
+ }
+
+ var cellX = matchScreen.fieldStartX + x * (defaultCellSize * matchScreen.displayScale)
+ var cellY = matchScreen.fieldStartY + y * (defaultCellSize * matchScreen.displayScale)
+
+ laserObj.turnOn(cellX, cellY, defaultCellSize * matchScreen.displayScale, direction)
+}
+
+function onLaserUpdated(posX, posY, laserDirection, isOn)
+{
+ if (isOn)
+ addLaser(posX, posY, laserDirection)
+ else
+ removeLaser(posX, posY, laserDirection)
+}
diff --git a/chicken-wranglers/src/qml/qml.qrc b/chicken-wranglers/src/qml/qml.qrc
new file mode 100644
index 0000000..615d922
--- /dev/null
+++ b/chicken-wranglers/src/qml/qml.qrc
@@ -0,0 +1,43 @@
+ <!DOCTYPE RCC><RCC version="1.0">
+ <qresource prefix="/">
+ <file>main.qml</file>
+ <file>common.js</file>
+ <file>client.js</file>
+ <file>host.js</file>
+ <file>Splash.qml</file>
+ <file>StartView.qml</file>
+ <file>widgets/Screen.qml</file>
+ <file>widgets/Button.qml</file>
+ <file>widgets/ImageButton.qml</file>
+ <file>widgets/Loading.qml</file>
+ <file>widgets/BaseDialog.qml</file>
+ <file>widgets/MessageDialog.qml</file>
+ <file>widgets/ConfirmationDialog.qml</file>
+ <file>widgets/Feather.qml</file>
+ <file>widgets/FeatherFall.qml</file>
+ <file>widgets/featherfall.js</file>
+ <file>widgets/Countdown.qml</file>
+ <file>widgets/OptionSlider.qml</file>
+ <file>widgets/Scrollbar.qml</file>
+ <file>widgets/ConnectivityDialog.qml</file>
+ <file>widgets/ConnectivityListView.qml</file>
+ <file>widgets/ToggleButton.qml</file>
+
+ <file>ClientView.qml</file>
+ <file>CharacterSelectionView.qml</file>
+ <file>PlayerReadyView.qml</file>
+ <file>PlayerControlView.qml</file>
+
+ <file>HostView.qml</file>
+ <file>WaitingRoomView.qml</file>
+ <file>MatchView.qml</file>
+ <file>Laser.qml</file>
+ <file>Score.qml</file>
+ <file>ScoreBox.qml</file>
+ <file>HenCoop.qml</file>
+ <file>Being.qml</file>
+ <file>Character.qml</file>
+ <file>Chicken.qml</file>
+ <file>match.js</file>
+ </qresource>
+ </RCC>
diff --git a/chicken-wranglers/src/qml/widgets/BaseDialog.qml b/chicken-wranglers/src/qml/widgets/BaseDialog.qml
new file mode 100644
index 0000000..e1cea04
--- /dev/null
+++ b/chicken-wranglers/src/qml/widgets/BaseDialog.qml
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+import Qt 4.7
+
+import game.types 1.0
+
+Item {
+ id: dialog
+
+ property alias box: box
+
+ signal showFinished
+ signal hideFinished
+
+ anchors.fill: parent
+
+ function show() {
+ dialog.opacity = 1
+ }
+
+ function hide() {
+ dialog.opacity = 0
+ }
+
+ onOpacityChanged: {
+ if (dialog.opacity == 1)
+ showFinished()
+ else if (dialog.opacity == 0)
+ hideFinished()
+ }
+
+ Rectangle {
+ id: background
+
+ anchors.fill: parent
+ color: "black"
+ opacity: 0.7
+
+ MouseArea {
+ anchors.fill: parent
+ }
+ }
+
+ function backgroundSize() {
+ var res = {};
+ res["height"] = 376
+ res["width"] = 622
+
+ // XXX: if in symbian, make the dialog smaller
+ if (game.environment() == Global.Symbian) {
+ res.height = 0.9 * dialog.height
+ res.width = 0.9 * dialog.width
+ }
+ return res;
+ }
+
+ Image {
+ id: box
+
+ source: {
+ if (game.environment() == Global.Symbian)
+ "qrc:/images/general/symbian/bg_dialog.png"
+ else
+ "qrc:/images/general/bg_dialog.png"
+ }
+ anchors.centerIn: parent
+ }
+
+ Behavior on opacity {
+ NumberAnimation { duration: 200 }
+ }
+}
diff --git a/chicken-wranglers/src/qml/widgets/Button.qml b/chicken-wranglers/src/qml/widgets/Button.qml
new file mode 100644
index 0000000..6ccd512
--- /dev/null
+++ b/chicken-wranglers/src/qml/widgets/Button.qml
@@ -0,0 +1,133 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+import Qt 4.7
+
+BorderImage {
+ id: button
+
+ property int leftBorder: 18
+ property int rightBorder: 18
+ property int horizontalCenterOffset: 0
+ property string sourceName: "bt"
+ property string text: ""
+ property bool blink: false
+ property bool enabled: true
+ property bool italic: false
+
+ signal clicked
+
+ source: {
+ if (!enabled)
+ return "qrc:/images/general/" + sourceName + "_disabled.png"
+
+ if (mouseArea.pressed)
+ return "qrc:/images/general/" + sourceName + "_pressed.png"
+ else
+ return "qrc:/images/general/" + sourceName + ".png"
+ }
+
+ smooth: true
+
+ border {
+ left: leftBorder
+ right: rightBorder
+ }
+
+ width: buttonText.width + 40
+
+ PropertyAnimation {
+ id: blinkAnimation
+
+ target: button
+ properties: "opacity"
+ loops: 2
+ from: 0
+ to: 1
+ duration: 200
+
+ onRunningChanged: {
+ if (!running)
+ button.clicked()
+ }
+ }
+
+ Text {
+ id: buttonText
+
+ text: button.text
+ smooth: true
+
+ color: {
+ if (button.enabled)
+ "#77262d"
+ else
+ "#666666"
+ }
+
+ anchors {
+ centerIn: parent
+ verticalCenterOffset: -3
+ horizontalCenterOffset: button.horizontalCenterOffset
+ }
+
+ font {
+ family: "Nokia Sans"
+ pixelSize: 26
+ bold: true
+ italic: button.italic
+ }
+ }
+
+ MouseArea {
+ id: mouseArea
+
+ enabled: button.enabled
+ anchors.fill: parent
+ onClicked: {
+ if (blink)
+ blinkAnimation.running = true
+ else
+ button.clicked()
+ }
+ }
+}
diff --git a/chicken-wranglers/src/qml/widgets/ConfirmationDialog.qml b/chicken-wranglers/src/qml/widgets/ConfirmationDialog.qml
new file mode 100644
index 0000000..90e922d
--- /dev/null
+++ b/chicken-wranglers/src/qml/widgets/ConfirmationDialog.qml
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+import Qt 4.7
+
+BaseDialog {
+ id: dialog
+
+ property string text: "Confirmation Dialog"
+ property string rejectText: "No"
+ property string acceptText: "Yes"
+ property int buttonWidth: 160
+
+ signal rejected()
+ signal accepted()
+
+ Text {
+ color: "#4d908f"
+ text: dialog.text
+ style: Text.Raised
+ styleColor: "white"
+
+ anchors.fill: box
+ anchors.margins: 60
+
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ wrapMode: Text.WordWrap
+
+ font {
+ family: "Nokia Sans"
+ pixelSize: 34
+ }
+ }
+
+ Button {
+ id: rejectButton
+
+ width: buttonWidth
+ text: dialog.rejectText
+ source: "qrc:/images/general/bt.png"
+ anchors {
+ verticalCenter: box.bottom
+ verticalCenterOffset: -25
+ right: box.horizontalCenter
+ rightMargin: 20
+ }
+
+ onClicked: rejected()
+ }
+
+ Button {
+ id: acceptButton
+
+ width: buttonWidth
+ text: dialog.acceptText
+ source: "qrc:/images/general/bt.png"
+ anchors {
+ verticalCenter: box.bottom
+ verticalCenterOffset: -25
+ left: box.horizontalCenter
+ leftMargin: 20
+ }
+
+ onClicked: accepted()
+ }
+}
diff --git a/chicken-wranglers/src/qml/widgets/ConnectivityDialog.qml b/chicken-wranglers/src/qml/widgets/ConnectivityDialog.qml
new file mode 100644
index 0000000..c7a4f99
--- /dev/null
+++ b/chicken-wranglers/src/qml/widgets/ConnectivityDialog.qml
@@ -0,0 +1,185 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+import Qt 4.7
+import game.types 1.0
+
+BaseDialog {
+ id: dialog
+
+ property string buttonText: "Use it"
+ property string cancelText: "Cancel"
+ property ConnectivityListModel model: ConnectivityListModel {}
+ signal cancel()
+
+ Connections {
+ target: dialog
+ onHideFinished: {
+ title.text = "Scanning..."
+ button.enabled = true
+ quitButton.enabled = true
+ }
+ }
+
+ ConfirmationDialog {
+ id: quitDialog
+
+ text: "Do you want to cancel scanning?"
+ opacity: 0
+
+ onRejected: {
+ quitDialog.hide()
+ }
+
+ onAccepted: {
+ quitDialog.hide()
+ dialog.cancel()
+ }
+
+ z: 10
+ }
+
+ Text {
+ id: title
+
+ text: "Scanning..."
+ style: Text.Raised
+ styleColor: "white"
+ color: "#4d908f"
+
+ font {
+ family: "Nokia Sans"
+ bold: true
+ pixelSize: 34
+ }
+
+ anchors.top: box.top
+ anchors.topMargin: 60
+ anchors.left: parent.left
+ anchors.right: parent.right
+
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ }
+
+ ConnectivityListView {
+ id: listView
+
+ property real scrollSize: 200
+
+ width: 400
+ height: 200
+ model: dialog.model
+ anchors.top: title.bottom
+ anchors.topMargin: 15
+ anchors.bottom: box.bottom
+ anchors.bottomMargin: 80
+ anchors.horizontalCenter: parent.horizontalCenter
+
+ onContentYChanged: {
+ scrollbar.setValue((contentY / scrollSize) * 100)
+ }
+
+ onMovingChanged: {
+ if (moving)
+ scrollbar.opacity = 1;
+ else
+ scrollbar.opacity = 0;
+ }
+ }
+
+ Scrollbar {
+ id: scrollbar
+
+ opacity: 0
+ anchors.top: title.bottom
+ anchors.bottom: box.bottom
+ anchors.left: listView.right
+ anchors.leftMargin: 20
+
+ Behavior on opacity {
+ NumberAnimation {
+ duration: 500
+ easing.type: Easing.OutCirc
+ }
+ }
+ }
+
+ Button {
+ id: button
+
+ text: dialog.buttonText
+ anchors {
+ verticalCenter: box.bottom
+ verticalCenterOffset: -25
+ horizontalCenter: box.horizontalCenter
+ horizontalCenterOffset: 90
+ }
+
+ onClicked: {
+ button.enabled = false
+ quitButton.enabled = false
+ title.text = "Connecting..."
+
+ if (listView.currentIndex != -1)
+ listView.model.selectedIndex = listView.currentIndex
+ }
+ }
+
+ Button {
+ id: quitButton
+ text: dialog.cancelText
+ anchors {
+ verticalCenter: box.bottom
+ verticalCenterOffset: -25
+ horizontalCenter: box.horizontalCenter
+ horizontalCenterOffset: -90
+ }
+
+ onClicked: {
+ if (quitDialog.opacity == 0) {
+ quitDialog.show()
+ }
+ }
+ }
+}
+
diff --git a/chicken-wranglers/src/qml/widgets/ConnectivityListModel.qml b/chicken-wranglers/src/qml/widgets/ConnectivityListModel.qml
new file mode 100644
index 0000000..df1449f
--- /dev/null
+++ b/chicken-wranglers/src/qml/widgets/ConnectivityListModel.qml
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+import Qt 4.7
+
+ListModel {
+ ListElement {
+ // N8 cellphone
+ name: "cw"; address: "18:14:56:44:F4:DB"
+ category: 2; pairing: 1
+ }
+
+ ListElement {
+ name: "5800gard"; address: "00:25:CF:11:2B:8A"
+ category: 2; pairing: 1
+ }
+
+ ListElement {
+ name: "FabyAAAAAAAAAAAAAAAAAAAAAAAAAA"; address: "00:24:03:DA:45:00"
+ category: 1; pairing: 0
+ }
+
+ ListElement {
+ name: "device-0BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"; address: "00:24:03:DA:45:00"
+ category: 1; pairing: 0
+ }
+
+ ListElement {
+ name: "pc-1"; address: "00:24:03:DA:45:00"
+ category: 1; pairing: 0
+ }
+
+ ListElement {
+ name: "device-1"; address: "00:24:03:DA:45:00"
+ category: 1; pairing: 0
+ }
+
+ ListElement {
+ name: "mobile-0"; address: "00:24:03:DA:45:00"
+ category: 1; pairing: 0
+ }
+}
+
diff --git a/chicken-wranglers/src/qml/widgets/ConnectivityListView.qml b/chicken-wranglers/src/qml/widgets/ConnectivityListView.qml
new file mode 100644
index 0000000..ca04c5b
--- /dev/null
+++ b/chicken-wranglers/src/qml/widgets/ConnectivityListView.qml
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+import Qt 4.7
+import game.types 1.0
+
+ListView {
+ id: listView
+
+ Component {
+ id: delegate
+
+ Item {
+ width: lineDivisor.width
+ height: 43
+
+ Image {
+ id: lineDivisor
+
+ source: "qrc:/images/general/list_line_divisor.png"
+
+ anchors.top: parent.top
+ }
+
+ Text {
+ text: name
+
+ width: parent.width - 110
+
+ style: Text.Raised
+ styleColor: "white"
+
+ color: "#4d908f"
+
+ font {
+ family: "Nokia Sans"
+ bold: true
+ pixelSize: 21
+ }
+
+ elide: Text.ElideRight
+
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.left: parent.left
+ anchors.leftMargin: 23
+
+ horizontalAlignment: Text.AlignLeft
+ verticalAlignment: Text.AlignVCenter
+ }
+
+ MouseArea {
+ anchors.fill: parent
+
+ onClicked: {
+ var pos = mapToItem(listView.contentItem, mouseX, mouseY)
+ var selectedIndex = listView.indexAt(pos.x, pos.y)
+
+ if (selectedIndex == listView.currentIndex) {
+ listView.currentIndex = -1
+ } else {
+ listView.currentIndex = selectedIndex
+ }
+ }
+ }
+ }
+ }
+
+ model: ConnectivityListModel {}
+ delegate: delegate
+
+ focus: false
+ clip: true
+
+ Component {
+ id: highlightIcon
+
+ Item {
+ width: listView.width
+ height: 43
+
+ Image {
+ source: "qrc:/images/general/list_selected_icon.png"
+
+ anchors.left: parent.right
+ anchors.leftMargin: -70
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.verticalCenterOffset: 1
+ }
+ }
+ }
+
+ currentIndex: model.selectedIndex
+
+ highlight: highlightIcon
+ highlightMoveDuration: 100
+
+ snapMode: ListView.SnapToItem
+}
+
diff --git a/chicken-wranglers/src/qml/widgets/Countdown.qml b/chicken-wranglers/src/qml/widgets/Countdown.qml
new file mode 100644
index 0000000..31b5ad9
--- /dev/null
+++ b/chicken-wranglers/src/qml/widgets/Countdown.qml
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+import Qt 4.7
+
+Item {
+ id: countdown
+
+ property int startValue: 3
+ property int currentValue: startValue
+ property int interval: 800
+ property string timeoutText: "Go!"
+
+ signal timeout
+
+ function start() {
+ countdown.opacity = 1
+ animation.start()
+ }
+
+ function decrement() {
+ if (currentValue - 1 > 0) {
+ currentValue--
+ return
+ }
+
+ if (currentValue == 1) {
+ number.text = countdown.timeoutText
+ currentValue--
+ return
+ }
+
+ countdown.opacity = 0
+ countdown.timeout()
+ }
+
+ Text {
+ id: number
+
+ text: currentValue
+ smooth: true
+ anchors.centerIn: parent
+ color: "white"
+
+ font {
+ family: "Nokia Sans"
+ pointSize: 100
+ bold: true
+ }
+
+ style: Text.Outline
+ styleColor: "darkgreen"
+ }
+
+ SequentialAnimation {
+ id: animation
+
+ loops: startValue + 1
+
+ ParallelAnimation {
+ PropertyAnimation { duration: countdown.interval; target: number; property: "scale"; from: 1; to: 2 }
+ PropertyAnimation { duration: countdown.interval; target: number; property: "opacity"; from: 1; to: 0 }
+ }
+
+ PropertyAction { target: number; properties: "scale,opacity"; value: 1 }
+ ScriptAction { script: countdown.decrement() }
+ }
+}
diff --git a/chicken-wranglers/src/qml/widgets/Feather.qml b/chicken-wranglers/src/qml/widgets/Feather.qml
new file mode 100644
index 0000000..b46585c
--- /dev/null
+++ b/chicken-wranglers/src/qml/widgets/Feather.qml
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+import Qt 4.7
+
+import game.types 1.0
+import "featherfall.js" as Feather
+
+Image {
+ id: feather
+
+ property int xMax: 0
+ property int xMin: 0
+ property int yMax: 768
+
+ // the delay offset for the initial creation of each feather.
+ property real delay: 0
+
+ source: {
+ if (game.environment() == Global.Symbian)
+ "qrc:/images/general/symbian/feather1.png"
+ else
+ "qrc:/images/general/feather1.png"
+ }
+ smooth: true
+ y: -feather.height
+
+ function startAnimation() {
+ animY.running = true
+ animX.running = true
+ animRotation.running = true
+ }
+
+ function stopAnimation() {
+ animY.running = false
+ animX.running = false
+ animRotation.running = false
+ }
+
+ SequentialAnimation on y {
+ id: animY
+
+ running: false
+
+ PauseAnimation { duration: delay }
+ NumberAnimation { to: 100; easing.type: Easing.InOutSine; duration: 1050 }
+ NumberAnimation { to: 300; easing.type: Easing.InOutSine; duration: 950 }
+ NumberAnimation { to: 500; easing.type: Easing.InOutSine; duration: 1050 }
+ NumberAnimation { to: 700; easing.type: Easing.InOutSine; duration: 950 }
+ NumberAnimation { to: 900; easing.type: Easing.InOutSine; duration: 1050 }
+ NumberAnimation { to: yMax + 2 * feather.height; easing.type: Easing.InOutSine; duration: 950 }
+
+ onRunningChanged: {
+ if (!running)
+ feather.destroy()
+ }
+ }
+
+ SequentialAnimation on x {
+ id: animX
+
+ running: false
+
+ PauseAnimation { duration: delay }
+ NumberAnimation { to: xMax; easing.type: Easing.InOutSine; duration: 950 }
+ NumberAnimation { to: xMin; easing.type: Easing.InOutSine; duration: 1050 }
+ NumberAnimation { to: xMax; easing.type: Easing.InOutSine; duration: 950 }
+ NumberAnimation { to: xMin; easing.type: Easing.InOutSine; duration: 1050 }
+ NumberAnimation { to: xMax; easing.type: Easing.InOutSine; duration: 950 }
+ NumberAnimation { to: xMin; easing.type: Easing.InOutSine; duration: 1050 }
+ }
+
+ SequentialAnimation on rotation {
+ id: animRotation
+
+ running: false
+
+ PauseAnimation { duration: delay }
+ NumberAnimation { to: -40; easing.type: Easing.InOutSine; duration: 1000 }
+ NumberAnimation { to: 25; easing.type: Easing.InOutSine; duration: 1000 }
+ NumberAnimation { to: -40; easing.type: Easing.InOutSine; duration: 1000 }
+ NumberAnimation { to: 25; easing.type: Easing.InOutSine; duration: 1000 }
+ NumberAnimation { to: -40; easing.type: Easing.InOutSine; duration: 1000 }
+ NumberAnimation { to: 25; easing.type: Easing.InOutSine; duration: 1000 }
+ NumberAnimation { to: -40; easing.type: Easing.InOutSine; duration: 1000 }
+ }
+}
diff --git a/chicken-wranglers/src/qml/widgets/FeatherFall.qml b/chicken-wranglers/src/qml/widgets/FeatherFall.qml
new file mode 100644
index 0000000..d8b49d7
--- /dev/null
+++ b/chicken-wranglers/src/qml/widgets/FeatherFall.qml
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+import Qt 4.7
+
+import game.types 1.0
+import "featherfall.js" as FeatherFall
+
+Item {
+ id: featherFall
+
+ property real fallWidth: 800
+ property real fallHeight: 768
+ property int number: 5
+
+ function start() {
+ timer.start()
+ }
+
+ function stop() {
+ timer.stop()
+ FeatherFall.destroy()
+ }
+
+ Timer {
+ id: timer
+
+ triggeredOnStart: true
+ repeat: true
+ interval: 6000
+ onTriggered: {
+ FeatherFall.create(featherFall.width, featherFall.height)
+ }
+ }
+}
diff --git a/chicken-wranglers/src/qml/widgets/ImageButton.qml b/chicken-wranglers/src/qml/widgets/ImageButton.qml
new file mode 100644
index 0000000..2ccdbf1
--- /dev/null
+++ b/chicken-wranglers/src/qml/widgets/ImageButton.qml
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+import Qt 4.7
+
+Image {
+ id: button
+
+ property bool blink: false
+ property string name: ""
+ property string path: "qrc:/images/general"
+ property alias buttonPressed: mouseArea.pressed
+
+ signal clicked
+
+ smooth: true
+ source: {
+ if (path == "")
+ return ""
+
+ if (mouseArea.pressed)
+ path + "/bt_" + name + "_pressed.png"
+ else
+ path + "/bt_" + name + ".png"
+ }
+
+ PropertyAnimation {
+ id: blinkAnimation
+
+ target: button
+ properties: "opacity"
+ loops: 2
+ from: 0
+ to: 1
+ duration: 200
+
+ onRunningChanged: {
+ if (!running)
+ button.clicked()
+ }
+ }
+
+ MouseArea {
+ id: mouseArea
+
+ anchors.fill: parent
+ onClicked: {
+ if (blink)
+ blinkAnimation.running = true
+ else
+ button.clicked()
+ }
+ }
+}
diff --git a/chicken-wranglers/src/qml/widgets/Loading.qml b/chicken-wranglers/src/qml/widgets/Loading.qml
new file mode 100644
index 0000000..19eeff5
--- /dev/null
+++ b/chicken-wranglers/src/qml/widgets/Loading.qml
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+import Qt 4.7
+
+Item {
+ id: loading
+
+ property int count: 0
+
+ width: row.width
+ height: row.height
+
+ Component {
+ id: dot
+
+ Rectangle {
+ id: outer
+
+ width: 15
+ height: 15
+ color: "#e0fce5"
+ radius: 50
+ smooth: true
+
+ Rectangle {
+ id: inner
+
+ anchors.centerIn: parent
+
+ smooth: true
+ color: "#9bbaae"
+ radius: 50
+
+ anchors.fill: parent
+ anchors.margins: 3
+ }
+
+ states {
+ State {
+ name: "off"
+ PropertyChanges { target: outer; scale: 1 }
+ PropertyChanges { target: inner; color: "#9bbaae" }
+ }
+ State {
+ name: "on"
+ PropertyChanges { target: outer; scale: 1.33 }
+ PropertyChanges { target: inner; color: "#f6c200" }
+ }
+ }
+
+ transitions: Transition {
+ ParallelAnimation {
+ NumberAnimation { target: outer; property: "scale"; easing.type: Easing.InOutQuad }
+ ColorAnimation { target: inner; property: "color"; easing.type: Easing.InOutQuad }
+ }
+ }
+ }
+ }
+
+ Row {
+ id: row
+
+ spacing: 4
+
+ children: [
+ Loader { sourceComponent: dot },
+ Loader { sourceComponent: dot },
+ Loader { sourceComponent: dot }
+ ]
+ }
+
+ Timer {
+ id: timer
+
+ repeat: true
+ interval: 200
+ running: true
+
+ onTriggered: {
+ if (count > 0)
+ row.children[count - 1].item.state = "off"
+
+ if (count < row.children.length)
+ row.children[count].item.state = "on"
+
+ count = (count + 1) % (row.children.length + 1)
+ }
+ }
+
+ onOpacityChanged: {
+ if (opacity == 1 && !timer.running) {
+ timer.start()
+ }
+ else if (opacity == 0 && timer.running) {
+ timer.stop()
+ }
+ }
+}
diff --git a/chicken-wranglers/src/qml/widgets/MessageDialog.qml b/chicken-wranglers/src/qml/widgets/MessageDialog.qml
new file mode 100644
index 0000000..44cc8d1
--- /dev/null
+++ b/chicken-wranglers/src/qml/widgets/MessageDialog.qml
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+import Qt 4.7
+
+BaseDialog {
+ id: dialog
+
+ property string text: "Message Dialog"
+ property string buttonText: "Ok"
+
+ signal buttonClicked
+
+ Text {
+ color: "#4d908f"
+ text: dialog.text
+ style: Text.Raised
+ styleColor: "white"
+
+ anchors.fill: box
+ anchors.margins: 60
+
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ wrapMode: Text.WordWrap
+
+ font {
+ family: "Nokia Sans"
+ pixelSize: 34
+ }
+ }
+
+ Button {
+ id: button
+
+ text: dialog.buttonText
+ anchors {
+ verticalCenter: box.bottom
+ verticalCenterOffset: -25
+ horizontalCenter: box.horizontalCenter
+ }
+
+ onClicked: buttonClicked()
+ }
+}
+
diff --git a/chicken-wranglers/src/qml/widgets/OptionSlider.qml b/chicken-wranglers/src/qml/widgets/OptionSlider.qml
new file mode 100644
index 0000000..205f299
--- /dev/null
+++ b/chicken-wranglers/src/qml/widgets/OptionSlider.qml
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+import Qt 4.7
+
+Item {
+ id: slider
+
+ property string option: "Wifi"
+
+ signal selected(string option)
+
+ width: sliderSelector.width
+ height: sliderPath.height
+
+ Image {
+ id: sliderPath
+
+ anchors.centerIn: parent
+
+ source: "qrc:/images/general/slider_path.png"
+ }
+
+ Image {
+ anchors {
+ horizontalCenter: slider.horizontalCenter
+ bottom: slider.verticalCenter
+ bottomMargin: 21
+ }
+
+ source: "qrc:/images/general/slider_wifi_icon.png"
+ }
+
+ Image {
+ anchors {
+ horizontalCenter: slider.horizontalCenter
+ horizontalCenterOffset: 3
+ top: slider.verticalCenter
+ topMargin: 16
+ }
+
+ source: "qrc:/images/general/slider_bluetooth_icon.png"
+ }
+
+ Image {
+ id: sliderSelector
+
+ source: "qrc:/images/general/slider_selector.png"
+
+ x: 0
+ y: 10
+
+ Behavior on y {
+ NumberAnimation {
+ id: slideAnimation
+
+ duration: 500
+ easing.type: Easing.OutCirc
+ }
+ }
+ }
+
+ MouseArea {
+ anchors.fill: parent
+
+ enabled: !slideAnimation.running
+
+ onReleased: {
+ // Wifi selected
+ if (mouse.y <= ((slider.height / 2) - 1)) {
+ if (slider.option != "Wifi") {
+ slider.option = "Wifi"
+
+ selected(slider.option)
+
+ sliderSelector.y = 10
+ }
+
+ // Bluetooth selected
+ } else {
+ if (slider.option != "Bluetooth") {
+ slider.option = "Bluetooth"
+
+ selected(slider.option)
+
+ sliderSelector.y = (slider.height / 2) - 10
+ }
+ }
+ }
+ }
+}
+
diff --git a/chicken-wranglers/src/qml/widgets/Screen.qml b/chicken-wranglers/src/qml/widgets/Screen.qml
new file mode 100644
index 0000000..967f443
--- /dev/null
+++ b/chicken-wranglers/src/qml/widgets/Screen.qml
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+import Qt 4.7
+
+Rectangle {
+ id: screen
+
+ signal transitionFinished(bool visible)
+
+ anchors.fill: parent
+ opacity: 0
+
+ function show() {
+ screen.state = "visible"
+ }
+
+ function hide() {
+ screen.state = "hidden"
+ }
+
+ states {
+ State {
+ name: "visible"
+ PropertyChanges { target: screen; opacity: 1 }
+ }
+ State {
+ name: "hidden"
+ PropertyChanges { target: screen; opacity: 0 }
+ }
+ }
+
+ Behavior on opacity {
+ NumberAnimation {
+ duration: 200
+
+ onRunningChanged: {
+ if (!running) {
+ if (opacity == 1)
+ transitionFinished(true)
+ else
+ transitionFinished(false)
+ }
+ }
+ }
+ }
+}
diff --git a/chicken-wranglers/src/qml/widgets/Scrollbar.qml b/chicken-wranglers/src/qml/widgets/Scrollbar.qml
new file mode 100644
index 0000000..0d59208
--- /dev/null
+++ b/chicken-wranglers/src/qml/widgets/Scrollbar.qml
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+import Qt 4.7
+
+Item {
+ id: scrollbar
+
+ property real value: 0.0
+ property real minimumValue: 0.0
+ property real maximumValue: 100.0
+ property real offset: 8.0
+ property real minimumPos: offset
+ property real maximumPos: scrollbarPath.height - scrollbarKnob.height - offset
+ property real scrollSize: maximumPos - minimumPos + 1
+
+ width: scrollbarKnob.width
+ height: scrollbarPath.height
+
+ function setValue(newValue) {
+ if (newValue <= minimumValue) {
+ value = minimumValue;
+ } else if (newValue >= maximumValue) {
+ value = maximumValue;
+ } else {
+ value = newValue;
+ }
+ }
+
+ Image {
+ id: scrollbarPath
+
+ anchors.centerIn: parent
+
+ source: "qrc:/images/general/list_scrollbar_path.png"
+ }
+
+ Image {
+ id: scrollbarKnob
+
+ anchors.horizontalCenter: parent.horizontalCenter
+
+ y: ((scrollbar.value / scrollbar.maximumValue) * scrollbar.scrollSize) + scrollbar.offset
+
+ source: "qrc:/images/general/list_scrollbar_knob.png"
+ }
+}
+
diff --git a/chicken-wranglers/src/qml/widgets/ToggleButton.qml b/chicken-wranglers/src/qml/widgets/ToggleButton.qml
new file mode 100644
index 0000000..939602f
--- /dev/null
+++ b/chicken-wranglers/src/qml/widgets/ToggleButton.qml
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+import Qt 4.7
+
+Image {
+ id: button
+ signal clicked
+ property string mode: "bluetooth"
+ source: "qrc:/images/general/toggle_bt.png"
+
+ MouseArea {
+ id: mouseArea
+
+ anchors.fill: parent
+ onClicked: {
+ if (button.mode == "bluetooth") {
+ button.mode = "lan"
+ button.source = "qrc:/images/general/toggle_lan.png"
+ } else {
+ button.mode = "bluetooth"
+ button.source = "qrc:/images/general/toggle_bt.png"
+ }
+
+ game.setConnectivity(button.mode)
+ }
+ }
+}
diff --git a/chicken-wranglers/src/qml/widgets/featherfall.js b/chicken-wranglers/src/qml/widgets/featherfall.js
new file mode 100644
index 0000000..6ae51a4
--- /dev/null
+++ b/chicken-wranglers/src/qml/widgets/featherfall.js
@@ -0,0 +1,66 @@
+var component;
+var featherObjList = new Array;
+
+function create(fallWidth, fallHeight) {
+ var i, range, lowRange, highRange;
+
+ if (component == null)
+ component = Qt.createComponent("Feather.qml");
+
+ range = fallWidth / featherFall.number;
+ lowRange = -range;
+ highRange = 0;
+
+ var resourcePath = "";
+ if (game.environment() == Global.Symbian)
+ resourcePath = "qrc:/images/general/symbian/feather"
+ else
+ resourcePath = "qrc:/images/general/feather"
+
+ for (i = 0; i < featherFall.number; i++) {
+ if (component.status == Component.Ready) {
+
+ featherObjList[i] = component.createObject(background);
+
+ if (featherObjList[i] == null) {
+ console.log("error creating featherObj");
+ console.log(component.errorString());
+ return false;
+ }
+
+ lowRange = lowRange + range;
+ highRange = highRange + range;
+
+ var xpos = (highRange - range) * Math.random() + lowRange;
+ featherObjList[i].x = xpos;
+
+ featherObjList[i].delay = Math.random() * 3000 * i;
+
+ var swing = Math.random() * range;
+ if (swing < 100)
+ swing += 100;
+
+ featherObjList[i].xMax = xpos + swing;
+ featherObjList[i].xMin = xpos - swing;
+ featherObjList[i].yMax = fallHeight;
+ featherObjList[i].source = resourcePath + (Math.floor(5 * Math.random()) + 1) + ".png";
+
+ featherObjList[i].startAnimation();
+ } else {
+ console.log("error loading featherObj component");
+ console.log(component.errorString());
+ return false;
+ }
+ }
+
+ return true;
+}
+
+function destroy() {
+ for (var i = 0; i < featherFall.number; i++) {
+ if (featherObjList[i] == null)
+ continue;
+
+ featherObjList[i].destroy()
+ }
+}
diff --git a/chicken-wranglers/src/sound/sound.cpp b/chicken-wranglers/src/sound/sound.cpp
new file mode 100644
index 0000000..0661a63
--- /dev/null
+++ b/chicken-wranglers/src/sound/sound.cpp
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+#include "sound.h"
+
+#include <QtCore/QDebug>
+#include <QtCore/QFile>
+
+Sound::Sound(const QByteArray &sound, bool isLoop, QObject *parent)
+ : QThread(parent), m_sound(sound), m_isLoop(isLoop)
+{
+}
+
+Sound::~Sound()
+{
+}
+
+void Sound::run()
+{
+}
+
+void Sound::play()
+{
+}
diff --git a/chicken-wranglers/src/sound/sound.h b/chicken-wranglers/src/sound/sound.h
new file mode 100644
index 0000000..86e5017
--- /dev/null
+++ b/chicken-wranglers/src/sound/sound.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+#ifndef SOUND_H
+#define SOUND_H
+
+#include <QtCore/QByteArray>
+#include <QtCore/QThread>
+
+class Sound : public QThread
+{
+ Q_OBJECT
+
+public:
+ Sound(const QByteArray &sound, bool isLoop = false, QObject *parent = 0);
+ ~Sound();
+
+ void run();
+
+public slots:
+ void play();
+
+private:
+ QByteArray m_sound;
+ bool m_isLoop;
+};
+
+#endif
diff --git a/chicken-wranglers/src/sound/sound.pri b/chicken-wranglers/src/sound/sound.pri
new file mode 100644
index 0000000..c7853fe
--- /dev/null
+++ b/chicken-wranglers/src/sound/sound.pri
@@ -0,0 +1,9 @@
+PATH = $$PWD
+
+HEADERS += \
+ $$PATH/soundmanager.h \
+ $$PATH/sound.h
+
+SOURCES += \
+ $$PATH/soundmanager.cpp \
+ $$PATH/sound.cpp
diff --git a/chicken-wranglers/src/sound/sound_linux.cpp b/chicken-wranglers/src/sound/sound_linux.cpp
new file mode 100644
index 0000000..d555eb3
--- /dev/null
+++ b/chicken-wranglers/src/sound/sound_linux.cpp
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+#include "sound_linux.h"
+
+#include <pulse/error.h>
+#include <pulse/gccmacro.h>
+#include <pulse/simple.h>
+
+#include <QtCore/QDebug>
+#include <QtCore/QFile>
+
+Sound::Sound(const QByteArray &sound, bool isLoop, QObject *parent)
+ : QThread(parent), m_sound(sound), m_isLoop(isLoop)
+{
+ int error;
+
+ static const pa_sample_spec sampleSpec = {
+ PA_SAMPLE_S16LE, // format
+ 44100, // rate
+ 2 // channels
+ };
+
+ // create a new playback stream
+ if (!(m_playbackStream = pa_simple_new(NULL, "name", PA_STREAM_PLAYBACK, NULL,
+ "playback", &sampleSpec, NULL, NULL, &error))) {
+ // error
+ qWarning() << "Failure to create a new simple playback stream:" << error;
+ }
+}
+
+Sound::~Sound()
+{
+ if (m_playbackStream)
+ pa_simple_free(m_playbackStream);
+}
+
+void Sound::run()
+{
+ if (!m_playbackStream) {
+ qWarning() << "Failure to play: playback stream was not created.";
+ return;
+ }
+
+ if (!m_sound.size()) {
+ qWarning() << "Failure to play: Invalid sound stream.";
+ return;
+ }
+
+ int error;
+ int rtv;
+
+ do {
+ rtv = pa_simple_write(m_playbackStream, m_sound.data(), (size_t) m_sound.size(), &error);
+ } while (m_isLoop && rtv >= 0);
+
+ if (rtv < 0)
+ qWarning() << "Failure to play sound.";
+
+ deleteLater();
+}
+
+void Sound::play()
+{
+ start();
+}
diff --git a/chicken-wranglers/src/sound/sound_linux.h b/chicken-wranglers/src/sound/sound_linux.h
new file mode 100644
index 0000000..ae2431a
--- /dev/null
+++ b/chicken-wranglers/src/sound/sound_linux.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+#ifndef SOUND_H
+#define SOUND_H
+
+#include <QtCore/QByteArray>
+#include <QtCore/QThread>
+
+struct pa_simple;
+
+class Sound : public QThread
+{
+ Q_OBJECT
+
+public:
+ Sound(const QByteArray &sound, bool isLoop = false, QObject *parent = 0);
+ ~Sound();
+
+ void run();
+
+public slots:
+ void play();
+
+private:
+ pa_simple *m_playbackStream;
+ QByteArray m_sound;
+ bool m_isLoop;
+};
+
+#endif
diff --git a/chicken-wranglers/src/sound/sound_linux.pri b/chicken-wranglers/src/sound/sound_linux.pri
new file mode 100644
index 0000000..cfbfb58
--- /dev/null
+++ b/chicken-wranglers/src/sound/sound_linux.pri
@@ -0,0 +1,9 @@
+PATH = $$PWD
+
+HEADERS += \
+ $$PATH/soundmanager.h \
+ $$PATH/sound_linux.h
+
+SOURCES += \
+ $$PATH/soundmanager.cpp \
+ $$PATH/sound_linux.cpp
diff --git a/chicken-wranglers/src/sound/soundmanager.cpp b/chicken-wranglers/src/sound/soundmanager.cpp
new file mode 100644
index 0000000..9e190ba
--- /dev/null
+++ b/chicken-wranglers/src/sound/soundmanager.cpp
@@ -0,0 +1,128 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+#include "soundmanager.h"
+
+#include "global.h"
+
+#if defined(Q_WS_X11)
+#include "sound_linux.h"
+#else
+#include "sound.h"
+#endif
+
+#include <QtCore/QDebug>
+
+SoundManager::SoundManager(QObject *parent)
+ : QObject(parent), m_isLoaded(false)
+{
+}
+
+SoundManager *SoundManager::instance()
+{
+ static SoundManager *const soundManager = new SoundManager();
+
+ return soundManager;
+}
+
+void SoundManager::load()
+{
+ if (m_isLoaded)
+ return;
+
+ QString soundPath(Global::rootDirectory().absoluteFilePath() + "/sounds/");
+
+ QFile soundFile;
+
+ soundFile.setFileName(soundPath + "match.raw");
+ if (soundFile.open(QIODevice::ReadOnly)) {
+ m_backgroundSound = soundFile.readAll();
+ soundFile.close();
+ } else {
+ qWarning() << "Error loading sound file:" << soundFile.fileName();
+ }
+
+ soundFile.setFileName(soundPath + "laser.raw");
+ if (soundFile.open(QIODevice::ReadOnly)) {
+ m_laserSound = soundFile.readAll();
+ soundFile.close();
+ } else {
+ qWarning() << "Error loading sound file:" << soundFile.fileName();
+ }
+
+ soundFile.setFileName(soundPath + "score.raw");
+ if (soundFile.open(QIODevice::ReadOnly)) {
+ m_scoreSound = soundFile.readAll();
+ soundFile.close();
+ } else {
+ qWarning() << "Error loading sound file:" << soundFile.fileName();
+ }
+
+ m_isLoaded = true;
+}
+
+void SoundManager::play(SoundType type)
+{
+ // NOTE: Currently sounds are supported only on Linux builds.
+
+#if defined(Q_WS_X11)
+ instance()->load();
+
+ Sound *sound = 0;
+
+ switch (type) {
+ case Background:
+ sound = new Sound(instance()->m_backgroundSound, true);
+ break;
+ case Score:
+ sound = new Sound(instance()->m_scoreSound);
+ break;
+ case Laser:
+ sound = new Sound(instance()->m_laserSound);
+ break;
+ default:
+ qWarning("No valid sound type");
+ return;
+ }
+
+ sound->play();
+#endif
+}
diff --git a/chicken-wranglers/src/sound/soundmanager.h b/chicken-wranglers/src/sound/soundmanager.h
new file mode 100644
index 0000000..52915a4
--- /dev/null
+++ b/chicken-wranglers/src/sound/soundmanager.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+#ifndef SOUNDMANAGER_H
+#define SOUNDMANAGER_H
+
+#include <QtCore/QObject>
+#include <QtCore/QString>
+
+class SoundManager : public QObject
+{
+ Q_ENUMS(SoundType)
+
+public:
+ enum SoundType {
+ Background,
+ Score,
+ Laser
+ };
+
+ static void play(SoundType type);
+
+protected:
+ static SoundManager *instance();
+
+private:
+ explicit SoundManager(QObject *parent = 0);
+
+ void load();
+
+ bool m_isLoaded;
+ QByteArray m_backgroundSound;
+ QByteArray m_scoreSound;
+ QByteArray m_laserSound;
+};
+
+#endif
diff --git a/chicken-wranglers/src/utils/global.cpp b/chicken-wranglers/src/utils/global.cpp
new file mode 100644
index 0000000..21c647f
--- /dev/null
+++ b/chicken-wranglers/src/utils/global.cpp
@@ -0,0 +1,135 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+#include "global.h"
+
+// TODO: conditional compilation module instead of ifdef's
+#ifdef Q_OS_SYMBIAN
+#include <eikenv.h>
+#include <coemain.h>
+#include <aknappui.h>
+#endif
+
+#include <QBluetoothLocalDevice>
+#include <qmobilityglobal.h>
+#include <QtCore/QStringList>
+#include <QtGlobal>
+
+QTM_USE_NAMESPACE
+
+QFileInfo Global::rootDirectory()
+{
+#ifdef Q_OS_SYMBIAN
+ return QFileInfo("c:\\data\\chicken-wranglers\\");
+#endif
+ QStringList pathList(QString(XSTR(DATA_PATH)).split(":", QString::SkipEmptyParts));
+
+ foreach (QFileInfo path, pathList)
+ if (path.exists() && path.isDir())
+ return path;
+
+ return QFileInfo();
+}
+
+QString Global::directionString(Global::Direction direction)
+{
+ switch (direction) {
+ case Global::DirectionUp:
+ return QString("Up");
+ case Global::DirectionDown:
+ return QString("Down");
+ case Global::DirectionRight:
+ return QString("Right");
+ case Global::DirectionLeft:
+ return QString("Left");
+ default:
+ return QString("Stop");
+ }
+}
+
+void Global::setScreenOrientation(const ScreenOrientation &orientation)
+{
+#ifdef Q_OS_SYMBIAN
+ CAknAppUi *aknAppUi = dynamic_cast<CAknAppUi *>(CEikonEnv::Static()->AppUi());
+ if (!aknAppUi)
+ return;
+
+ switch (orientation) {
+ case Landscape:
+ aknAppUi->SetOrientationL(CAknAppUi::EAppUiOrientationLandscape);
+ break;
+ case Portrait:
+ aknAppUi->SetOrientationL(CAknAppUi::EAppUiOrientationPortrait);
+ break;
+ case Auto:
+ aknAppUi->SetOrientationL(CAknAppUi::EAppUiOrientationAutomatic);
+ }
+#endif
+}
+
+void Global::setPowerOn()
+{
+ QList<QBluetoothHostInfo> devices(QBluetoothLocalDevice::allDevices());
+ foreach(const QBluetoothHostInfo &i, devices) {
+ QBluetoothLocalDevice hci(i.getAddress());
+ hci.setHostMode(QBluetoothLocalDevice::HostDiscoverable);
+ hci.powerOn();
+ }
+}
+
+Global::Environment Global::environment()
+{
+ // Set default environment to Linux
+ Environment result = Linux;
+#if defined(Q_WS_MAEMO_5)
+ result = Maemo;
+#elif defined(Q_WS_X11)
+ result = Linux;
+#elif defined(Q_WS_S60)
+ result = Symbian;
+#elif defined(Q_WS_WIN)
+ result = Windows;
+#elif defined(Q_WS_MAC)
+ result = Mac;
+#endif
+
+ return result;
+}
diff --git a/chicken-wranglers/src/utils/global.h b/chicken-wranglers/src/utils/global.h
new file mode 100644
index 0000000..b69b3cc
--- /dev/null
+++ b/chicken-wranglers/src/utils/global.h
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Nokia Corporation 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."
+**
+****************************************************************************/
+
+
+#ifndef GLOBAL_H
+#define GLOBAL_H
+
+#define XSTR(s) STR(s)
+#define STR(s) #s
+
+#include <QtCore/QFileInfo>
+#include <QtCore/QObject>
+#include <QtGlobal>
+
+class Global : public QObject
+{
+ Q_OBJECT
+
+ Q_ENUMS(Direction LaserDirection ScreenOrientation Environment)
+
+public:
+ enum Direction {
+ DirectionUp,
+ DirectionDown,
+ DirectionLeft,
+ DirectionRight,
+ DirectionStop
+ };
+
+ enum LaserDirection {
+ LaserUp,
+ LaserDown,
+ LaserLeft,
+ LaserRight
+ };
+
+ enum ScreenOrientation {
+ Portrait,
+ Landscape,
+ Auto
+ };
+
+ enum Environment {
+ Linux,
+ Symbian,
+ Maemo,
+ Windows,
+ Mac
+ };
+
+ static QFileInfo rootDirectory();
+
+ static QString directionString(Direction direction);
+
+ static void setScreenOrientation(const ScreenOrientation &orientation = Portrait);
+
+ static void setPowerOn();
+
+ static Environment environment();
+
+ static const int maximumPlayers = 4;
+};
+
+#endif
diff --git a/chicken-wranglers/src/utils/utils.pri b/chicken-wranglers/src/utils/utils.pri
new file mode 100644
index 0000000..b7444a5
--- /dev/null
+++ b/chicken-wranglers/src/utils/utils.pri
@@ -0,0 +1,9 @@
+DEFINES += DATA_PATH=$$SOURCE_TREE/:$$INSTALL_PREFIX/share/chicken-wranglers/
+
+PATH = $$PWD
+
+HEADERS += \
+ $$PATH/global.h
+
+SOURCES += \
+ $$PATH/global.cpp