]> git.zarvox.org Git - shareboard.git/commitdiff
Complete network support, event passing, and tracking.
authorDrew Fisher <drew.m.fisher@gmail.com>
Fri, 8 Oct 2010 03:32:01 +0000 (20:32 -0700)
committerDrew Fisher <drew.m.fisher@gmail.com>
Fri, 8 Oct 2010 03:32:01 +0000 (20:32 -0700)
Actions are posted to the server with correct UserID.
Enabled actions are currently limited to MouseMove and DrawLine.

action.cpp
action.h
connectionmanager.cpp
connectionmanager.h
mainwindow.cpp
mainwindow.h
shareboard.cpp
shareboard.h
shareboard.pro
shareboardcanvas.cpp
shareboardcanvas.h

index ed5df1cb1a9d13d81c11a610e679acbdaa2ef5f7..436fc0b86172df8d82b6b01c42c807a2de15b451 100644 (file)
@@ -1,15 +1,21 @@
 #include "action.h"
+#include <QDataStream>
+#include <QByteArray>
+#include <QBuffer>
+#include "base64.h"
 
 Action::Action() {
        type = INVALID;
        mesgID = 0;
        userID = 0;
+       timestamp = QDateTime::currentDateTime();
 }
 
 Action::Action(Type t) {
        type = t;
        mesgID = 0;
        userID = 0;
+       timestamp = QDateTime::currentDateTime();
 }
 
 Action::~Action() {
@@ -54,7 +60,9 @@ UserChatAction::~UserChatAction() {
 QTextStream& operator<<(QTextStream& out, const Action& action) {
        out << "0 " << action.userID << " " << action.timestamp.toString("yyyy-MM-ddThh:mm:ss.zzz") << " " << static_cast<quint16>(action.type) ; // mesgID, userID, timestamp, mesgType
        switch(action.type) {
-               case Action::INVALID: break;
+               case Action::INVALID:
+               case Action::UserSynced:
+                       break;
                case Action::UserJoin:
                        {
                                const UserJoinAction* a = static_cast<const UserJoinAction*>(&action);
@@ -79,8 +87,13 @@ QTextStream& operator<<(QTextStream& out, const Action& action) {
                case Action::AddImage:
                        {
                                const AddImageAction* a = static_cast<const AddImageAction*>(&action);
-                               // TODO: unbackburner this
-                               //out << " " << a->topLeft << a->image;
+                               out << " " << a->topLeft.x() << " " << a->topLeft.y();
+                               QByteArray ba;
+                               QBuffer buffer(&ba);
+                               buffer.open(QIODevice::WriteOnly);
+                               a->image.save(&buffer, "PNG");
+                               buffer.close();
+                               out << toBase64(ba);
                        } break;
                case Action::UserChat:
                        {
index 25ba71728cb1ec604f410d0da5187960ccb793ff..7241bb423da9b78c1b467610c5dba70813fbf5b3 100644 (file)
--- a/action.h
+++ b/action.h
@@ -18,7 +18,8 @@ public:
                MouseMove=3,
                DrawLine=4,
                AddImage=5,
-               UserChat=6
+               UserChat=6,
+               UserSynced=7
        };
 
        Action();
index 0e4d498855c16bef1bc3a1826420d143979dad27..88eee479a7479b0e2a8c812c8bd0d18df7f5a2bd 100644 (file)
@@ -3,6 +3,8 @@
 #include <QTcpSocket>
 #include <QTextStream>
 #include "action.h"
+#include "base64.h"
+#include "shareboard.h"
 
 ConnectionManager::ConnectionManager(QObject* parent) : QObject(parent) {
        sock = new QTcpSocket();
@@ -17,6 +19,10 @@ ConnectionManager::~ConnectionManager() {
        if (sock) delete sock;
 }
 
+void ConnectionManager::setTarget(Shareboard* t) {
+       board = t;
+}
+
 void ConnectionManager::joinServer(QString _username, QString host) {
        username = _username;
        quint16 port = 4260;
@@ -28,6 +34,7 @@ void ConnectionManager::sendAction(Action* action) {
        QByteArray output;
        QTextStream t(&output);
        t << (*action);
+       t.flush();
        qDebug() << "Sending" << output.size() << "bytes for action of type" << action->type;
        sock->write(output);
 }
@@ -140,9 +147,8 @@ void ConnectionManager::haveData() {
                                QString im;
                                textstream >> im;
                                // im is a base64-encoded binary string.
-                               
-
-
+                               QByteArray ba = fromBase64(im); // Convert back to binary data
+                               action->image.loadFromData(ba, "PNG");
                                action->mesgID = mesgID;
                                action->userID = userID;
                                action->timestamp = timestamp;
@@ -165,13 +171,20 @@ void ConnectionManager::haveData() {
                                action->text = chat;
                                break;
                                }
+                       case Action::UserSynced:
+                               {
+                               board->setUserID(userID);
+                               qDebug() << "User is synced :)";
+                               continue;
+                               }
+                               break;
                        default:
                                qWarning() << "Received invalid type from server :(";
                                continue;
                }
                Q_ASSERT(act != NULL);
 
-               // HistoryManager::instance()->newAction(action);
+               board->postAction(act);
 
                qDebug() << "Dispatched action with type " << act->type << " that was " << data.size() << " bytes long";
        }
index 74f981fa3f37ef4dd9e510c15a24938174aa038f..7f9263bf414f1bc7f252ee620f68677fe40fdb9b 100644 (file)
@@ -9,6 +9,7 @@
 
 class Action;
 class QTcpSocket;
+class Shareboard;
 
 class ConnectionManager : public QObject{
        Q_OBJECT
@@ -22,6 +23,7 @@ class ConnectionManager : public QObject{
                void disconnected();
                void error(QString e);
        public slots:
+               void setTarget(Shareboard* t);
                void joinServer(QString _username, QString host);
                void sendAction(Action* action);
                void onError();
@@ -30,6 +32,7 @@ class ConnectionManager : public QObject{
                //QByteArray data;
                QTcpSocket* sock;
                QTextStream* textStream;
+               Shareboard* board;
        private slots:
                void haveData();
                void onConnect();
index 872d247e051863a203ff145ec3f634487d3210c3..5eca4c896fbbc9fe5371d3973553d13a76398ff3 100644 (file)
@@ -9,21 +9,24 @@
 
 #include "connectionmanager.h"
 #include "shareboard.h"
+#include "action.h"
 
 MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) {
        createActions();
        createMenus();
 
-       connMan = new ConnectionManager(this);
-
        board = new Shareboard(this);
        setCentralWidget(board);
 
+       connMan = new ConnectionManager(this);
+       connMan->setTarget(board);
+
        // Connect all actions
        QObject::connect(board, SIGNAL(connectToServer(QString, QString)), connMan, SLOT(joinServer(QString, QString)));
        QObject::connect(connMan, SIGNAL(connected()),    this, SLOT(switchToBoard()));
        QObject::connect(connMan, SIGNAL(disconnected()), this, SLOT(switchToConnect()));
        QObject::connect(connMan, SIGNAL(error(QString)), this, SLOT(showError(QString)));
+       QObject::connect(board, SIGNAL(actionHappened(Action*)), this, SLOT(marshallAction(Action*)));
 
        statusBar()->showMessage("Ready");
 }
@@ -64,7 +67,6 @@ void MainWindow::quit() {
 }
 
 void MainWindow::switchToBoard() {
-       // Here, we set the central widget to be the as-of-yet unimplemented Shareboard widget
        board->switchToBoard();
        statusBar()->showMessage(QString("Switched to Shareboard drawing surface"));
 }
@@ -78,8 +80,22 @@ void MainWindow::showError(QString error) {
        statusBar()->showMessage(error);
 }
 
+void MainWindow::marshallAction(Action* action) {
+       switch(action->type) {
+               case Action::DrawLine: // set the action's thickness, color
+                       {
+                               DrawLineAction* a = static_cast<DrawLineAction*>(action);
+                               a->color == Qt::blue;
+                               a->width = 3;
+                       }
+                       break;
+               default: break;
+       }
+       board->postLocalAction(action);
+       connMan->sendAction(action);
+}
+
 void MainWindow::createActions() {
-       //joinAction = new QAction("Joi&n a board online", this);
        loadPastAction = new QAction("&Open a board", this);
        saveAction = new QAction("&Save board", this);
        quitAction = new QAction("&Quit", this);
@@ -91,7 +107,6 @@ void MainWindow::createActions() {
 void MainWindow::createMenus() {
 
        fileMenu = menuBar()->addMenu("&File");
-       //fileMenu->addAction(joinAction);
        fileMenu->addAction(loadPastAction);
        fileMenu->addAction(saveAction);
        fileMenu->addSeparator();
index 8f06f9891edfe28294ada3ba338056f174eb92fe..692bc3c2d810b3d45a532ebb5a90d4bf8485b486 100644 (file)
@@ -8,6 +8,7 @@ class QAction;
 class ConnectWidget;
 class ConnectionManager;
 class Shareboard;
+class Action;
 
 class MainWindow : public QMainWindow {
        Q_OBJECT
@@ -22,6 +23,7 @@ public slots:
        void switchToBoard();
        void switchToConnect();
        void showError(QString error);
+       void marshallAction(Action* action);
 private:
        void createActions();
        void createMenus();
index 902c274af73ceebabeff2bbc67a067036b1012b1..cd39d63558bff3832809074d0d69ec3b1be67379 100644 (file)
@@ -3,6 +3,8 @@
 
 #include "shareboardcanvas.h"
 #include "connectwidget.h"
+#include "action.h"
+#include <QDebug>
 
 Shareboard::Shareboard(QWidget* parent) : QWidget(parent) {
        layout = new QStackedLayout(this);
@@ -15,10 +17,46 @@ Shareboard::Shareboard(QWidget* parent) : QWidget(parent) {
        setMinimumSize(640,480);
 
        QObject::connect(prompt, SIGNAL(connectToServer(QString, QString)), this, SIGNAL(connectToServer(QString, QString)));
+       QObject::connect(canvas, SIGNAL(mouseMovedTo(QPointF)), this, SLOT(handleMouseMoved(QPointF)));
+       QObject::connect(canvas, SIGNAL(segmentDrawn(QPointF,QPointF)), this, SLOT(handleSegmentDrawn(QPointF,QPointF)));
 }
 
 Shareboard::~Shareboard() {
+       for(int i = 0; i < history.size(); i++)
+               delete history[i];
+       for(int i = 0; i < localHistory.size(); i++)
+               delete localHistory[i];
+}
+
+void Shareboard::handleMouseMoved(QPointF pos) {
+       MouseMoveAction* action = new MouseMoveAction();
+       action->userID = userID;
+       action->pos = pos;
+       localHistory.append(action);
+       emit actionHappened(action);
+       qDebug() << "shareboard.cpp: mouse moved to" << pos;
+}
+
+void Shareboard::handleSegmentDrawn(QPointF start, QPointF end) {
+       // Add segment to localHistory, dispatch to connMan
+       DrawLineAction* action = new DrawLineAction();
+       action->userID = userID;
+       action->points.append(start);
+       action->points.append(end);
+       emit actionHappened(action);
+       qDebug() << "shareboard.cpp: segment drawn from" << start << "to" << end;
+}
 
+void Shareboard::postAction(Action* action) {
+       if(action->userID == userID) {
+               delete localHistory[0];
+               localHistory.removeFirst();
+       }
+       history.append(action);
+}
+
+void Shareboard::postLocalAction(Action* action) {
+       localHistory.append(action);
 }
 
 void Shareboard::switchToBoard() {
@@ -28,3 +66,7 @@ void Shareboard::switchToBoard() {
 void Shareboard::switchToPrompt() {
        layout->setCurrentWidget(prompt);
 }
+
+void Shareboard::setUserID(int id) {
+       userID = id;
+}
index 9bfa28fb33c7abcfc3252993afff46c680179849..f4422b09050d0e1d02444dd9f67e7abeeb5e0a34 100644 (file)
@@ -2,11 +2,15 @@
 #define __SHAREBOARD_H__
 
 #include <QWidget>
+#include <QPointF>
 
 class QStackedLayout;
 class ConnectWidget;
 class ShareboardCanvas;
 
+class Action;
+typedef QList<Action*> History;
+
 class Shareboard : public QWidget {
        Q_OBJECT
        public:
@@ -14,16 +18,25 @@ class Shareboard : public QWidget {
                ~Shareboard();
 
        public slots:
+               void handleMouseMoved(QPointF pos);
+               void handleSegmentDrawn(QPointF start, QPointF end);
+               void postAction(Action* action);
+               void postLocalAction(Action* action);
                void switchToBoard();
                void switchToPrompt();
+               void setUserID(int id);
 
        signals:
                void connectToServer(QString, QString);
+               void actionHappened(Action* action);
 
        private:
                QStackedLayout* layout;
                ConnectWidget* prompt;
                ShareboardCanvas* canvas;
+               History history;
+               History localHistory;
+               int userID;
 };
 
 #endif // __SHAREBOARD_H__
index 8ffb5819aa5ac5ae4b0b9794bd363535733aa7f0..6a14cc47cdb682abe77b19528f85213356afc8de 100644 (file)
@@ -10,5 +10,20 @@ DEPENDPATH += .
 INCLUDEPATH += .
 
 # Input
-HEADERS += mainwindow.h action.h connectwidget.h connectionmanager.h shareboard.h shareboardcanvas.h base64.h
-SOURCES += main.cpp mainwindow.cpp action.cpp connectwidget.cpp connectionmanager.cpp shareboard.cpp shareboardcanvas.cpp base64.cpp
+HEADERS += \
+               action.h \
+               base64.h \
+               connectionmanager.h \
+               connectwidget.h \
+               mainwindow.h \
+               shareboardcanvas.h \
+               shareboard.h
+
+SOURCES += main.cpp \
+               action.cpp \
+               base64.cpp \
+               connectionmanager.cpp \
+               connectwidget.cpp \
+               mainwindow.cpp \
+               shareboardcanvas.cpp \
+               shareboard.cpp
index 06696f2b5a0626e3899f5b2c9a3e5c3b32fcd179..cc2dae193c32db65a46773eac83cdfb8b22b3f81 100644 (file)
@@ -20,27 +20,35 @@ ShareboardCanvas::~ShareboardCanvas() {
 
 void ShareboardCanvas::mouseMoveEvent(QMouseEvent* event) {
        // Send mouse move event to network thread
+       emit mouseMovedTo(event->posF());
        // If the button is down
-       if(mouseDown)
+       if(mouseDown) {
+               emit segmentDrawn(dragPath.last(), event->posF());
                dragPath.append(event->posF());
+       }
        // Trigger a repaint
        update();
 }
 
 void ShareboardCanvas::mousePressEvent(QMouseEvent* event) {
-       mouseDown = true;
-       dragPath.append(event->posF()); // We're starting a new drag path
+       if(event->button() & Qt::LeftButton) {
+               mouseDown = true;
+               dragPath.append(event->posF()); // We're starting a new drag path
+       }
        //
 }
 
 void ShareboardCanvas::mouseReleaseEvent(QMouseEvent* event) {
-       mouseDown = false;
-       qDebug() << dragPath.size() << "mouse move events counted this drag";
-       // Depending on the tool, we now dispatch different types of events
-       dragPath.clear(); // Clear the path; we're no longer tracking a drag
+       if(event->button() & Qt::LeftButton) {
+               mouseDown = false;
+               qDebug() << dragPath.size() << "mouse move events counted this drag";
+               // Depending on the tool, we now dispatch different types of events
+               dragPath.clear(); // Clear the path; we're no longer tracking a drag
+       }
 }
 
 void ShareboardCanvas::paintEvent(QPaintEvent* event) {
+       Q_UNUSED(event)
        QPainter p(this);
        // Paint the background from the saved state
        p.drawPixmap(0, 0, *currentScene);
index 693485dc8bbec80fd84560ec68e8ae78b6519e5c..c48b02606c903a13e376a710072c33b4c444d23d 100644 (file)
@@ -18,6 +18,9 @@ public:
        void mousePressEvent(QMouseEvent* event);
        void mouseReleaseEvent(QMouseEvent* event);
        void paintEvent(QPaintEvent* event);
+signals:
+       void mouseMovedTo(QPointF pos);
+       void segmentDrawn(QPointF start, QPointF end);
 private:
        bool mouseDown;
        QPixmap* currentScene;