Code

refactored session establishment
authordaleharvey <daleharvey@users.sourceforge.net>
Wed, 2 Aug 2006 18:36:41 +0000 (18:36 +0000)
committerdaleharvey <daleharvey@users.sourceforge.net>
Wed, 2 Aug 2006 18:36:41 +0000 (18:36 +0000)
src/jabber_whiteboard/Makefile_insert
src/jabber_whiteboard/defines.cpp
src/jabber_whiteboard/defines.h
src/jabber_whiteboard/inkboard-document.cpp
src/jabber_whiteboard/inkboard-document.h
src/jabber_whiteboard/invitation-handlers.cpp [deleted file]
src/jabber_whiteboard/new-inkboard-document.cpp [deleted file]
src/jabber_whiteboard/new-inkboard-document.h [deleted file]
src/jabber_whiteboard/pedrogui.cpp
src/jabber_whiteboard/session-manager.cpp
src/jabber_whiteboard/session-manager.h

index 1f2d2667163549de71a5d84ddfcb58227dc1b659..bea89e80378812ae59e48b43446ca40f12f3f92e 100644 (file)
@@ -23,13 +23,10 @@ jabber_whiteboard_SOURCES = \
        jabber_whiteboard/message-tags.h \
        jabber_whiteboard/message-utilities.cpp \
        jabber_whiteboard/message-utilities.h \
-       jabber_whiteboard/new-inkboard-document.cpp \
-       jabber_whiteboard/new-inkboard-document.h \
        jabber_whiteboard/inkboard-document.cpp \
        jabber_whiteboard/inkboard-document.h \
        jabber_whiteboard/invitation-confirm-dialog.cpp \
        jabber_whiteboard/invitation-confirm-dialog.h \
-       jabber_whiteboard/invitation-handlers.cpp \
        jabber_whiteboard/session-file-selector.cpp \
        jabber_whiteboard/session-file-selector.h \
        jabber_whiteboard/session-manager.cpp \
index 3e3895ea04207e71e77e02e48e039ef0eadba4e2..43a75cb7c21ce3a5a4ccd262a8c9d34fed6e206a 100644 (file)
@@ -27,12 +27,12 @@ namespace Message {
     Wrapper CONFIGURE =    "configure";
     Wrapper MOVE =         "move";
 
-    Message CONNECT_REQUEST =     "<connect-request />";
-    Message CONNECTED =           "<connected />";
-    Message ACCEPT_INVITATION =   "<accept-invitation />";
-    Message DECLINE_INVITATION =  "<decline-invitation />";
-    Message DOCUMENT_BEGIN =      "<document-begin />";
-    Message DOCUMENT_END =        "<document-end />";
+    Message CONNECT_REQUEST =     "connect-request";
+    Message CONNECTED =           "connected";
+    Message ACCEPT_INVITATION =   "accept-invitation";
+    Message DECLINE_INVITATION =  "decline-invitation";
+    Message DOCUMENT_BEGIN =      "document-begin";
+    Message DOCUMENT_END =        "document-end";
 }
 
 namespace Vars {
index a5d2d2ce6a7ec867c66c1d9bc7f577740b083485..e08d876a680de0ec5f126fec65f6529b3205f5a3 100644 (file)
@@ -101,17 +101,20 @@ namespace State {
     typedef char const* SessionState;
 }
 
+namespace Dialog {
+
+enum DialogReply {
+
+    ACCEPT_INVITATION =     0,
+    DECLINE_INVITATION =    1
+};
+
+}
+
 // message types
 // explicitly numbered to aid protocol description later on
 
 
-// Responses to whiteboard invitations
-enum InvitationResponses {
-       ACCEPT_INVITATION,
-       DECLINE_INVITATION,
-       PEER_ALREADY_IN_SESSION,
-       UNSUPPORTED_PROTOCOL
-};
 
 // Message handler modes
 enum HandlerMode {
@@ -182,6 +185,9 @@ typedef std::list< ReceivedCommitEvent > CommitsQueue;
 // Message serialization
 typedef std::list< Glib::ustring > SerializedEventList;
 
+
+    //typedef std::pair< Glib::ustring, InvitationResponses > Invitation_response_type;
+    //typedef std::list< Invitation_response_type > Invitation_responses_type;
 // Error handling -- someday
 // TODO: finish and integrate this
 //typedef boost::function< LmHandlerResult (unsigned int code) > ErrorHandlerFunctor;
index 5f0d27e89bc4fb875c9b4c30e4b888f31021e255..bf72d3c2af445b6a30f8f1b06b0f48082e540753 100644 (file)
@@ -74,9 +74,9 @@ InkboardDocument::terminateSession()
 }
 
 void
-InkboardDocument::processInkboardEvent(Message::Wrapper mtype, unsigned int seqnum, Glib::ustring const& data)
+InkboardDocument::processInkboardEvent(Message::Wrapper mtype, Glib::ustring const& data)
 {
-    g_log(NULL, G_LOG_LEVEL_DEBUG, "Processing Inkboard event: mtype=%s seqnum=%d data=%s\n", mtype, seqnum, data.c_str());
+    g_log(NULL, G_LOG_LEVEL_DEBUG, "Processing Inkboard event: mtype=%s data=%s\n",mtype,data.c_str());
 }
 
 bool
@@ -87,7 +87,7 @@ InkboardDocument::sendProtocol(const Glib::ustring &destJid, Message::Wrapper wr
         "<message type='%s' from='%s' to='%s'>"
             "<wb xmlns='%s' session='%s'>"
                 "<%s>"
-                    "%s"
+                    "<%s />"
                 "</%s>"
             "</wb>"
             "<body> </body>"
index 0b0e5baed2790b2dad9d6e59b41674a452b533e9..71de75e19c05b24dcd9bb4b1224a964e19bdcfd4 100644 (file)
@@ -16,7 +16,7 @@
 
 #include "xml/document.h"
 #include "xml/simple-node.h"
-
+#include "jabber_whiteboard/defines.h"
 #include "jabber_whiteboard/keynode.h"
 #include "jabber_whiteboard/session-manager.h"
 
@@ -24,6 +24,7 @@ namespace Inkscape {
 
 namespace Whiteboard {
 
+
 class InkboardDocument : public XML::SimpleNode, public XML::Document {
 public:
        
@@ -42,7 +43,7 @@ public:
 
     void startSessionNegotiation();
     void terminateSession();
-    void processInkboardEvent(Message::Wrapper mtype, unsigned int seqnum, Glib::ustring const& data);
+    void processInkboardEvent(Message::Wrapper mtype, Glib::ustring const& data);
 
     bool sendProtocol(const Glib::ustring &destJid, Message::Wrapper mwrapper, 
         Message::Message message);
diff --git a/src/jabber_whiteboard/invitation-handlers.cpp b/src/jabber_whiteboard/invitation-handlers.cpp
deleted file mode 100644 (file)
index 1ddf479..0000000
+++ /dev/null
@@ -1,150 +0,0 @@
-/**
- * Whiteboard session manager - invitation handling methods
- *
- * Authors: 
- * David Yip <yipdw@rose-hulman.edu>
- * Bob Jamison (Pedro port)
- *
- * Copyright (c) 2005 Authors
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#include <gtkmm.h>
-#include <glibmm/i18n.h>
-
-#include "util/ucompose.hpp"
-
-#include "document.h"
-#include "desktop-handles.h"
-
-#include "jabber_whiteboard/inkboard-document.h"
-#include "jabber_whiteboard/session-manager.h"
-#include "jabber_whiteboard/invitation-confirm-dialog.h"
-#include "jabber_whiteboard/defines.h"
-
-namespace Inkscape {
-
-namespace Whiteboard {
-
-bool
-SessionManager::_checkInvitationQueue()
-{
-       int x, y;
-       Gdk::ModifierType mt;
-       Gdk::Display::get_default()->get_pointer(x, y, mt);
-       if (mt & GDK_BUTTON1_MASK) {
-               // The user is currently busy with an action.  Defer invitation processing 
-               // until the user is free.
-               return true;
-       }
-
-       if (_pending_invitations.size() > 0) {
-               // There's an invitation to process; process it.
-               Glib::ustring from = _pending_invitations.front();
-
-               Glib::ustring primary = "<span weight=\"bold\" size=\"larger\">" + String::ucompose(_("<b>%1</b> has invited you to a whiteboard session."), from) + "</span>\n\n";
-               primary += String::ucompose(_("Do you wish to accept <b>%1</b>'s whiteboard session invitation?"), from);
-
-               InvitationConfirmDialog dialog(primary);
-               
-               dialog.add_button(_("Accept invitation"), ACCEPT_INVITATION);
-               dialog.add_button(_("Decline invitation"), DECLINE_INVITATION);
-
-               InvitationResponses resp = static_cast< InvitationResponses >(dialog.run());
-
-               switch (resp) {
-                       case ACCEPT_INVITATION:
-                       {
-                               SPDesktop* dt = createInkboardDesktop(from, State::WHITEBOARD_PEER);
-                               InkboardDocument* idoc = dynamic_cast< InkboardDocument* >(sp_desktop_document(dt)->rdoc);
-                               //sendProtocol(from, Message::PROTOCOL, " ");
-                               break;
-                       }
-                       case DECLINE_INVITATION:
-                       {
-                               break;
-                       }
-                       default:
-                               //sendProtocol(from, Message::PROTOCOL, " ");
-                               break;
-               }
-
-               _pending_invitations.pop_front();
-       }
-
-       return true;
-}
-
-
-bool
-SessionManager::_checkInvitationResponseQueue()
-{
-       int x, y;
-       Gdk::ModifierType mt;
-       Gdk::Display::get_default()->get_pointer(x, y, mt);
-       if (mt & GDK_BUTTON1_MASK) {
-               // The user is currently busy with an action.  Defer invitation response processing 
-               // until the user is free.
-               return true;
-       }
-
-       if (_invitation_responses.size() > 0) {
-               Invitation_response_type response = _invitation_responses.front();
-
-               switch (response.second) {
-                       case ACCEPT_INVITATION:
-                       {
-                               break;
-                       }
-                       case DECLINE_INVITATION:
-                       {
-                               Glib::ustring primary = String::ucompose(_("<span weight=\"bold\" size=\"larger\">The user <b>%1</b> has refused your whiteboard invitation.</span>\n\n"), response.first);
-
-                               // TRANSLATORS: %1 is the peer whom refused our invitation, %2 is our Jabber identity.
-                               Glib::ustring secondary = String::ucompose(_("You are still connected to a Jabber server as <b>%2</b>, and may send an invitation to <b>%1</b> again, or you may send an invitation to a different user."), response.first, this->getClient().getJid());
-
-                               Gtk::MessageDialog dialog(primary + secondary, true, Gtk::MESSAGE_INFO, Gtk::BUTTONS_CLOSE, false);
-                               dialog.run();
-                               terminateInkboardSession(response.first);
-                               break;
-                       }
-                       case PEER_ALREADY_IN_SESSION:
-                               break;
-
-                       case UNSUPPORTED_PROTOCOL:
-                       {
-                               Glib::ustring primary = String::ucompose(_("<span weight=\"bold\" size=\"larger\">The user <b>%1</b> is using an incompatible version of Inkboard.</span>\n\n"), response.first);
-
-                               // TRANSLATORS: %1 is the peer whom refused our invitation, %2 is our Jabber identity.
-                               Glib::ustring secondary = String::ucompose(_("Inkscape cannot connect to <b>%1</b>.\n\nYou are still connected to a Jabber server as <b>%2</b>."), response.first, this->getClient().getJid());
-
-                               Gtk::MessageDialog dialog(primary + secondary, true, Gtk::MESSAGE_INFO, Gtk::BUTTONS_CLOSE, false);
-                               dialog.run();
-                               terminateInkboardSession(response.first);
-                               break;
-                       }
-                       default:
-                               break;
-               }
-
-               _invitation_responses.pop_front();
-       }
-
-       return true;
-}
-
-}
-
-}
-
-/*
-  Local Variables:
-  mode:c++
-  c-file-style:"stroustrup"
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
-  indent-tabs-mode:nil
-  fill-column:99
-  End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/jabber_whiteboard/new-inkboard-document.cpp b/src/jabber_whiteboard/new-inkboard-document.cpp
deleted file mode 100644 (file)
index 3e47554..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-/**
- * new-inkboard-document.h
- * Functions to create new Inkboard documents, based off of sp_document_new /
- * sp_file_new
- *
- * Authors:
- * David Yip <yipdw@rose-hulman.edu>
- *
- * Copyright (c) 2006 Authors
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#include <glib.h>
-#include <glibmm.h>
-#include <glibmm/i18n.h>
-
-#include "document.h"
-#include "document-private.h"
-#include "desktop.h"
-#include "desktop-handles.h"
-#include "interface.h"
-#include "sp-namedview.h"
-#include "desktop-handles.h"
-
-#include "gc-anchored.h"
-
-#include "ui/view/view-widget.h"
-
-#include "application/application.h"
-#include "application/editor.h"
-
-#include "util/ucompose.hpp"
-
-#include "xml/node.h"
-#include "xml/repr.h"
-
-#include "jabber_whiteboard/inkboard-document.h"
-#include "jabber_whiteboard/new-inkboard-document.h"
-
-namespace Inkscape {
-
-namespace Whiteboard {
-
-SPDocument*
-makeInkboardDocument(int code, gchar const* rootname, State::SessionType type, Glib::ustring const& to)
-{
-       SPDocument* doc;
-       InkboardDocument* rdoc = new InkboardDocument(g_quark_from_static_string("xml"), type, to);
-       rdoc->setAttribute("version", "1.0");
-       rdoc->setAttribute("standalone", "no");
-       XML::Node *comment = sp_repr_new_comment(" Created with Inkscape (http://www.inkscape.org/) ");
-       rdoc->appendChild(comment);
-       GC::release(comment);
-
-       XML::Node* root = sp_repr_new(rootname);
-       rdoc->appendChild(root);
-       GC::release(root);
-
-       Glib::ustring name = String::ucompose(_("Inkboard session (%1 to %2)"), SessionManager::instance().getClient().getJid(), to);
-
-       doc = sp_document_create(rdoc, NULL, NULL, name.c_str(), TRUE);
-       return doc;
-}
-
-// TODO: When the switchover to the new GUI is complete, this function should go away
-// and be replaced with a call to Inkscape::NSApplication::Editor::createDesktop.  
-// It currently only exists to correctly mimic the desktop creation functionality
-// in file.cpp.
-//
-// \see sp_file_new
-SPDesktop*
-makeInkboardDesktop(SPDocument* doc)
-{
-       SPDesktop* dt;
-
-       if (NSApplication::Application::getNewGui()) {
-               dt = NSApplication::Editor::createDesktop(doc);
-       } else {
-        SPViewWidget *dtw = sp_desktop_widget_new(sp_document_namedview(doc, NULL));
-        g_return_val_if_fail(dtw != NULL, NULL);
-        sp_document_unref(doc);
-
-        sp_create_window(dtw, TRUE);
-        dt = static_cast<SPDesktop*>(dtw->view);
-        sp_namedview_window_from_document(dt);
-       }
-
-       return dt;
-}
-
-}
-
-}
diff --git a/src/jabber_whiteboard/new-inkboard-document.h b/src/jabber_whiteboard/new-inkboard-document.h
deleted file mode 100644 (file)
index ead55ef..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/**
- * new-inkboard-document.h
- * Functions to create new Inkboard documents, based off of sp_document_new /
- * sp_file_new
- *
- * Authors:
- * David Yip <yipdw@rose-hulman.edu>
- *
- * Copyright (c) 2006 Authors
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#ifndef __INKSCAPE_WHITEBOARD_NEW_DOCUMENT_H__
-#define __INKSCAPE_WHITEBOARD_NEW_DOCUMENT_H__
-
-#include <glibmm.h>
-
-class SPDocument;
-class SPDesktop;
-
-namespace Inkscape {
-
-namespace Whiteboard {
-
-SPDocument* makeInkboardDocument(int code, gchar const* rootname, State::SessionType type, Glib::ustring const& to);
-SPDesktop* makeInkboardDesktop(SPDocument* doc);
-
-}
-
-}
-
-#endif
index fc58dc349b19ecaa57d2144109c0f10f3085a3b8..64578f9af0a1919d860cc6219158e2302ae338ee 100644 (file)
@@ -2472,14 +2472,14 @@ void PedroGui::doShare(const DOMString &jid)
 {
     Inkscape::Whiteboard::SessionManager& sm =
          Inkscape::Whiteboard::SessionManager::instance();
-    sm.doShare(jid, Inkscape::Whiteboard::State::WHITEBOARD_PEER);
+    sm.initialiseSession(jid, Inkscape::Whiteboard::State::WHITEBOARD_PEER);
 }
 
 void PedroGui::doGroupShare(const DOMString &groupJid)
 {
     Inkscape::Whiteboard::SessionManager& sm =
         Inkscape::Whiteboard::SessionManager::instance();
-    sm.doShare(groupJid, Inkscape::Whiteboard::State::WHITEBOARD_MUC);
+    sm.initialiseSession(groupJid, Inkscape::Whiteboard::State::WHITEBOARD_MUC);
 }
 
 //##################
index 856db5fe79bce3ec4ead8a47811a757d0a79dbdb..dd392c845b4d18940f2bb274504eec50a6ff6d19 100644 (file)
 #include <gtkmm.h>
 #include <glibmm/i18n.h>
 
+#include "xml/node.h"
+#include "xml/repr.h"
+
+#include "util/ucompose.hpp"
+
 #include "xml/node-observer.h"
 
 #include "pedro/pedrodom.h"
 
+#include "ui/view/view-widget.h"
+
+#include "application/application.h"
+#include "application/editor.h"
+
+#include "document-private.h"
+#include "interface.h"
+#include "sp-namedview.h"
 #include "document.h"
 #include "desktop.h"
 #include "desktop-handles.h"
 
+#include "jabber_whiteboard/invitation-confirm-dialog.h"
 #include "jabber_whiteboard/message-verifier.h"
 #include "jabber_whiteboard/session-manager.h"
 #include "jabber_whiteboard/inkboard-document.h"
-#include "jabber_whiteboard/new-inkboard-document.h"
 #include "jabber_whiteboard/defines.h"
 
 #include "jabber_whiteboard/dialog/choose-desktop.h"
@@ -59,11 +72,11 @@ SessionManager::instance()
 
 SessionManager::SessionManager() 
 {
-    sequenceNumber = 0L;
     getClient().addXmppEventListener(*this);
 
-       this->_check_pending_invitations = Glib::signal_timeout().connect(sigc::mem_fun(*this, &SessionManager::_checkInvitationQueue), 50);
-       this->_check_invitation_responses = Glib::signal_timeout().connect(sigc::mem_fun(*this, &SessionManager::_checkInvitationResponseQueue), 50);
+    this->CheckPendingInvitations = 
+        Glib::signal_timeout().connect(sigc::mem_fun(
+            *this, &SessionManager::checkInvitationQueue), 50);
 }
 
 SessionManager::~SessionManager()
@@ -94,38 +107,21 @@ SessionManager::processXmppEvent(const Pedro::XmppEvent &event)
             {
             break;
             }
+        case Pedro::XmppEvent::EVENT_MUC_MESSAGE:
         case Pedro::XmppEvent::EVENT_MESSAGE:
             {
             g_warning("## SM message:%s\n", event.getFrom().c_str());
             Pedro::Element *root = event.getDOM();
 
-            if (root)
-                {
-                if (root->getTagAttribute("inkboard", "xmlns") == Vars::INKBOARD_XMLNS)
-                    {
-                        _processInkboardEvent(event);
-                    }
-                }
+            if (root && root->getTagAttribute("wb", "xmlns") == Vars::INKBOARD_XMLNS)
+                processWhiteboardEvent(event);
+
             break;
             }
         case Pedro::XmppEvent::EVENT_PRESENCE:
             {
             break;
             }
-        case Pedro::XmppEvent::EVENT_MUC_MESSAGE:
-            {
-            g_warning("## SM MUC message:%s\n", event.getFrom().c_str());
-            Pedro::Element *root = event.getDOM();
-
-            if (root)
-                {
-                if (root->getTagAttribute("inkboard", "xmlns") == Vars::INKBOARD_XMLNS)
-                    {
-                        _processInkboardEvent(event);
-                    }
-                }
-            break;
-            }
         case Pedro::XmppEvent::EVENT_MUC_JOIN:
             {
             break;
@@ -152,14 +148,12 @@ SessionManager::processXmppEvent(const Pedro::XmppEvent &event)
  * \param type Type of the session; i.e. private message or group chat.
  */
 void
-SessionManager::doShare(Glib::ustring const& to, State::SessionType type)
+SessionManager::initialiseSession(Glib::ustring const& to, State::SessionType type)
 {
-    SPDocument* doc = makeInkboardDocument(g_quark_from_static_string("xml"), "svg:svg", type, to);
-    if(doc == NULL) return;
 
+    SPDocument* doc = makeInkboardDocument(g_quark_from_static_string("xml"), "svg:svg", type, to);
     InkboardDocument* inkdoc = dynamic_cast< InkboardDocument* >(doc->rdoc);
-    if (inkdoc == NULL) return;
-
+    if(inkdoc == NULL) return;
 
     if(type == State::WHITEBOARD_PEER) 
     {
@@ -176,273 +170,231 @@ SessionManager::doShare(Glib::ustring const& to, State::SessionType type)
                     sp_desktop_document(desktop)->rdoc;
                 inkdoc->root()->mergeFrom(old_doc->root(),"id");
             }
-        }
-    }else{ return; }
+        }else { return; }
+    }
 
-    // Create a random session identifier
-    char * randomString = (char*) malloc (11);
-    for (int n=0; n<11; n++)
-        randomString[n]=rand()%26+'a';
-    randomString[11]='\0';
+    char * sessionId = createSessionId(10);
 
-    inkdoc->setSessionIdent(randomString);
+    inkdoc->setSessionIdent(sessionId);
 
-    _inkboards.push_back(Inkboard_record_type(randomString, inkdoc));
+    addSession(WhiteboardRecord(sessionId, inkdoc));
 
     inkdoc->startSessionNegotiation();
 
-    /*
-    InkboardDocument* doc;
-    SPDesktop* dt;
-
-    // Just create a new blank canvas for MUC sessions
-    if(type == State::WHITEBOARD_MUC) 
-    {
-        dt = createInkboardDesktop(to, type);
-
-        if (dt != NULL) 
-        {
-            doc = dynamic_cast< InkboardDocument* >(sp_desktop_document(dt)->rdoc);
-
-            if (doc != NULL) 
-            {
-                doc->startSessionNegotiation();
-            }
-        }
-           
-
-        // Let the user pick the document which to start a peer ro peer session
-        // with, or a blank one, then create a blank document, copy over the contents
-        // and initialise session
-    } else if (type== State::WHITEBOARD_PEER) {
 
-        ChooseDesktop dialog;
-        int result = dialog.run();
-
-        if(result == Gtk::RESPONSE_OK)
-        {
-            SPDesktop *desktop = dialog.getDesktop();
-            dt = createInkboardDesktop(to, type);
-
-            if (dt != NULL) 
-            {
-                doc = dynamic_cast< InkboardDocument* >(sp_desktop_document(dt)->rdoc);
-
-                if (doc != NULL) 
-                {
-                    if(desktop != NULL)
-                    {
-                        Inkscape::XML::Document *old_doc =
-                            sp_desktop_document(desktop)->rdoc;
-                        doc->root()->mergeFrom(old_doc->root(),"id");
-                    }
-
-                    doc->startSessionNegotiation();
-                }
-            }
-        }
-    }
-    */
-}
-
-/**
- * Clone of sp_file_new and all related subroutines and functions,
- * with appropriate modifications to use the Inkboard document class.
- *
- * \param to The JID to which this Inkboard document will be connected.
- * \return A pointer to the created desktop, or NULL if a new desktop could not be created.
- */
-SPDesktop*
-SessionManager::createInkboardDesktop(Glib::ustring const& to, State::SessionType type)
-{
-// Create document (sp_repr_document_new clone)
-    SPDocument* doc = makeInkboardDocument(g_quark_from_static_string("xml"), "svg:svg", type, to);
-    g_return_val_if_fail(doc != NULL, NULL);
-
-    InkboardDocument* inkdoc = dynamic_cast< InkboardDocument* >(doc->rdoc);
-    if (inkdoc == NULL) { // this shouldn't ever happen...
-        return NULL;
-    }
-
-// Create desktop and attach document
-    SPDesktop *dt = makeInkboardDesktop(doc);
-    _inkboards.push_back(Inkboard_record_type(to, inkdoc));
-    return dt;
 }
 
 void
-SessionManager::terminateInkboardSession(Glib::ustring const& to)
+SessionManager::terminateSession(Glib::ustring const& sessionId)
 {
-       std::cout << "Terminating Inkboard session to " << to << std::endl;
-    Inkboards_type::iterator i = _inkboards.begin();
-    for(; i != _inkboards.end(); ++i) {
-        if ((*i).first == to) {
+    WhiteboardList::iterator i = whiteboards.begin();
+    for(; i != whiteboards.end(); ++i) {
+        if ((*i).first == sessionId) 
             break;
-        }
     }
 
-    if (i != _inkboards.end()) {
-               std::cout << "Erasing Inkboard session to " << to << std::endl;
+    if (i != whiteboards.end()) {
         (*i).second->terminateSession();
-        _inkboards.erase(i);
+        whiteboards.erase(i);
     }
 }
 
+void
+SessionManager::addSession(WhiteboardRecord whiteboard)
+{
+    whiteboards.push_back(whiteboard);
+}
+
 InkboardDocument*
-SessionManager::getInkboardSession(Glib::ustring const& to)
+SessionManager::getInkboardSession(Glib::ustring const& sessionId)
 {
-    Inkboards_type::iterator i = _inkboards.begin();
-    for(; i != _inkboards.end(); ++i) {
-        if ((*i).first == to) {
+    WhiteboardList::iterator i = whiteboards.begin();
+    for(; i != whiteboards.end(); ++i) {
+        if ((*i).first == sessionId) {
             return (*i).second;
         }
     }
     return NULL;
 }
 
+
+/**
+ * Handles all incoming messages from pedro within a valid namespace, CONNECT_REQUEST messages
+ * are handled here, as they have no InkboardDocument to be handled from, all other messages
+ * are passed to their appropriate Inkboard document, which is identified by the 'session' 
+ * attribute of the 'wb' element
+ *
+ */
 void
-SessionManager::_processInkboardEvent(Pedro::XmppEvent const& event)
+SessionManager::processWhiteboardEvent(Pedro::XmppEvent const& event)
 {
     Pedro::Element* root = event.getDOM();
+    if (root == NULL) {
+       g_warning("Received null DOM; ignoring message.");
+       return;
+    }
 
-       if (root == NULL) {
-               g_warning("Received null DOM; ignoring message.");
-               return;
-       }
-
-    Pedro::DOMString type = root->getTagAttribute("inkboard", "type");
-    Pedro::DOMString seq = root->getTagAttribute("inkboard", "seq");
-    Pedro::DOMString protover = root->getTagAttribute("inkboard", "protocol");
+    Pedro::DOMString session = root->getTagAttribute("wb", "session");
+    Pedro::DOMString domwrapper = root->getFirstChild()->getFirstChild()->getFirstChild()->getName();
 
-    if (type.empty() || seq.empty() || protover.empty()) {
-        g_warning("Received incomplete Inkboard message (missing type, protocol, or sequence number); ignoring message.");
+    if (session.empty()) {
+        g_warning("Received incomplete Whiteboard message, missing session identifier; ignoring message.");
         return;
     }
 
-    MessageType mtype = static_cast< MessageType >(atoi(type.c_str()));
-
-       // Messages that deal with the creation and destruction of sessions should be handled
-       // here in the SessionManager.  
-       //
-       // These events are listed below, along with rationale.
-       //
-       // - CONNECT_REQUEST_USER: when we begin to process this message, we will not have an 
-       //   Inkboard session available to send the message to.  Therefore, this message needs
-       //   to be handled by the SessionManager.
-       // 
-       // - CONNECT_REQUEST_REFUSED_BY_PEER: this message means that the recipient of a 
-       //   private invitation refused the invitation.  In this case, we need to destroy the
-       //   Inkboard desktop, document, and session associated with that invitation.
-       //   Destruction of these components seems to be more naturally done in the SessionManager
-       //   than in the Inkboard document itself (especially since the document may be associated
-       //   with multiple desktops).
-       //
-       // - UNSUPPORTED_PROTOCOL_VERSION: this message means that the recipient of an invitation
-       //   does not support the version of the Inkboard protocol we are using.  In this case,
-       //   we have to destroy the Inkboard desktop, document, and session associated with that
-       //   invitation.  The rationale for doing it in the SessionManager is the same as that
-       //   given above.
-       //
-       // - ALREADY_IN_SESSION: similar rationale to above.
-       //
-       // - DISCONNECTED_FROM_USER_SIGNAL: similar rationale to above.
-       //
-       //
-        // All other events can be handled inside an Inkboard session.
-       
-       // The message we are handling will have come from some Jabber ID.  We need to verify
-       // that the Inkboard session associated with that JID is in the correct state for the
-       // incoming message (or, in some cases, that the session correctly exists / does not
-       // exist).
-       InkboardDocument* doc = getInkboardSession(event.getFrom());
-
-//      NOTE: This line refers to a class that hasn't been written yet
-//     MessageValidityTestResult res = MessageVerifier::verifyMessageValidity(event, mtype, doc);
-
-       MessageValidityTestResult res = RESULT_INVALID;
-        /*
-       switch (res) {
-               case RESULT_VALID:
-               {
-                       switch (mtype) {
-                               case CONNECT_REQUEST:
-                               default:
-                                       if (doc != NULL) {
-                                               unsigned int seqnum = atoi(seq.c_str());
-                                               doc->processInkboardEvent(mtype, seqnum, event.getData());
-                                       }
-                                       break;
-                       }
-                       break;
-               }
-               case RESULT_INVALID:
-               default:
-                       // FIXME: better warning message
-                       g_warning("Received message in invalid context.");
-                       break;
-       }
-        */
+    if(root->exists(Message::CONNECT_REQUEST))
+        handleIncomingInvitation(Invitation(event.getFrom(),session));
+
+    else
+    { 
+        Message::Wrapper wrapper = domwrapper.c_str();
+        InkboardDocument* doc = getInkboardSession(session);
+        doc->processInkboardEvent(wrapper, event.getData());
+    }
 }
 
-void
-SessionManager::_handleSessionEvent(Message::Wrapper mtype, Pedro::XmppEvent const& event)
+char*
+SessionManager::createSessionId(int size)
 {
-        /*
-       switch (mtype) {
-               case CONNECT_REQUEST:
-                       _handleIncomingInvitation(event.getFrom());
-                       break;
-               case INVITATION_DECLINE:
-                       _handleInvitationResponse(event.getFrom(), DECLINE_INVITATION);
-                       break;
-               default:
-                       break;
-       }
-        */
+    // Create a random session identifier
+    char * randomString = (char*) malloc (size);
+    for (int n=0; n<size; n++)
+        randomString[n]=rand()%26+'a';
+    randomString[size+1]='\0';
+
+    return randomString;
 }
 
+/**
+ * Adds an invitation to a queue to be executed in SessionManager::_checkInvitationQueue()
+ * as when this method is called, we're still executing in Pedro's context, which causes 
+ * issues when we run a dialog main loop.
+ *
+ */
 void
-SessionManager::_handleIncomingInvitation(Glib::ustring const& from)
+SessionManager::handleIncomingInvitation(Invitation invitation)
 {
-       // don't insert duplicate invitations
-       if (std::find(_pending_invitations.begin(), _pending_invitations.end(), from) != _pending_invitations.end()) {
-               return;
-       }
-
-       // We need to do the invitation confirm/deny dialog elsewhere --
-       // when this method is called, we're still executing in Pedro's context,
-       // which causes issues when we run a dialog main loop.
-       //
-       // The invitation handling is done in a poller timeout that executes approximately
-       // every 50ms.  It calls _checkInvitationQueue.
-       _pending_invitations.push_back(from);
+    // don't insert duplicate invitations
+    if (std::find(invitations.begin(),invitations.end(),invitation) != invitations.end())
+        return;
+
+    invitations.push_back(invitation);
 
 }
 
-void
-SessionManager::_handleInvitationResponse(Glib::ustring const& from, InvitationResponses resp)
+bool
+SessionManager::checkInvitationQueue()
+{
+    // The user is currently busy with an action.  Defer invitation processing 
+    // until the user is free.
+    int x, y;
+    Gdk::ModifierType mt;
+    Gdk::Display::get_default()->get_pointer(x, y, mt);
+    if (mt & GDK_BUTTON1_MASK) 
+        return true;
+
+    if (invitations.size() > 0) 
+    {
+        // There's an invitation to process; process it.
+       Invitation invitation = invitations.front();
+        Glib::ustring from = invitation.first;
+        Glib::ustring sessionId = invitation.second;
+
+       Glib::ustring primary = 
+            "<span weight=\"bold\" size=\"larger\">" + 
+            String::ucompose(_("<b>%1</b> has invited you to a whiteboard session."), from) + 
+            "</span>\n\n" + 
+            String::ucompose(_("Do you wish to accept <b>%1</b>'s whiteboard session invitation?"), from);
+
+        InvitationConfirmDialog dialog(primary);
+
+        dialog.add_button(_("Accept invitation"), Dialog::ACCEPT_INVITATION);
+        dialog.add_button(_("Decline invitation"), Dialog::DECLINE_INVITATION);
+
+        Dialog::DialogReply reply = static_cast< Dialog::DialogReply >(dialog.run());
+
+
+        SPDocument* doc = makeInkboardDocument(g_quark_from_static_string("xml"), "svg:svg", State::WHITEBOARD_PEER, from);
+        InkboardDocument* inkdoc = dynamic_cast< InkboardDocument* >(doc->rdoc);
+        if(inkdoc == NULL) return true;
+
+        addSession(WhiteboardRecord(sessionId, inkdoc));
+
+        switch (reply) {
+
+            case Dialog::ACCEPT_INVITATION:{
+                inkdoc->sendProtocol(from, Message::PROTOCOL,Message::ACCEPT_INVITATION);
+                makeInkboardDesktop(doc);
+                break; }
+
+            case Dialog::DECLINE_INVITATION: default: {
+                inkdoc->sendProtocol(from, Message::PROTOCOL,Message::DECLINE_INVITATION);
+                terminateSession(sessionId);
+                break; }
+        }
+
+        invitations.pop_front();
+
+    }
+
+    return true;
+}
+
+//#########################################################################
+//# HELPER FUNCTIONS
+//#########################################################################
+
+SPDocument*
+makeInkboardDocument(int code, gchar const* rootname, State::SessionType type, Glib::ustring const& to)
 {
-       // only handle one response per invitation sender
-       //
-       // TODO: this could have one huge bug: say that Alice sends an invite to Bob, but
-       // Bob is doing something else at the moment and doesn't want to get in an Inkboard
-       // session.  Eve intercepts Bob's "reject invitation" message and passes a
-       // "accept invitation" message to Alice that comes before Bob's "reject invitation"
-       // message. 
-       //
-       // Does XMPP prevent this sort of attack?  Need to investigate that.
-       if (std::find_if(_invitation_responses.begin(), _invitation_responses.end(), CheckInvitationSender(from)) != _invitation_responses.end()) {
-               return;
-       }
-
-       // We need to do the invitation confirm/deny dialog elsewhere --
-       // when this method is called, we're still executing in Pedro's context,
-       // which causes issues when we run a dialog main loop.
-       //
-       // The invitation handling is done in a poller timeout that executes approximately
-       // every 50ms.  It calls _checkInvitationResponseQueue.
-       _invitation_responses.push_back(Invitation_response_type(from, resp));
+    SPDocument* doc;
+
+    InkboardDocument* rdoc = new InkboardDocument(g_quark_from_static_string("xml"), type, to);
+    rdoc->setAttribute("version", "1.0");
+    rdoc->setAttribute("standalone", "no");
+    XML::Node *comment = sp_repr_new_comment(" Created with Inkscape (http://www.inkscape.org/) ");
+    rdoc->appendChild(comment);
+    GC::release(comment);
+
+    XML::Node* root = sp_repr_new(rootname);
+    rdoc->appendChild(root);
+    GC::release(root);
+
+    Glib::ustring name = String::ucompose(
+        _("Inkboard session (%1 to %2)"), SessionManager::instance().getClient().getJid(), to);
 
+    doc = sp_document_create(rdoc, NULL, NULL, name.c_str(), TRUE);
+    g_return_val_if_fail(doc != NULL, NULL);
+
+    return doc;
+}
+
+// TODO: When the switchover to the new GUI is complete, this function should go away
+// and be replaced with a call to Inkscape::NSApplication::Editor::createDesktop.  
+// It currently only exists to correctly mimic the desktop creation functionality
+// in file.cpp.
+//
+// \see sp_file_new
+SPDesktop*
+makeInkboardDesktop(SPDocument* doc)
+{
+    SPDesktop* dt;
+
+    if (NSApplication::Application::getNewGui()) 
+        dt = NSApplication::Editor::createDesktop(doc);
+
+    else 
+    {
+        SPViewWidget *dtw = sp_desktop_widget_new(sp_document_namedview(doc, NULL));
+        g_return_val_if_fail(dtw != NULL, NULL);
+        sp_document_unref(doc);
+
+        sp_create_window(dtw, TRUE);
+        dt = static_cast<SPDesktop*>(dtw->view);
+        sp_namedview_window_from_document(dt);
+    }
+
+    return dt;
 }
 
 }  // namespace Whiteboard
index 18f6239bbf03acb3dc4e27a1676770a17f3ca922..1ba6266852c99318f7f74d6bc3774f66bdb89e13 100644 (file)
@@ -18,6 +18,8 @@
 #include <list>
 #include <bitset>
 
+#include "desktop.h"
+
 #include "jabber_whiteboard/pedrogui.h"
 #include "jabber_whiteboard/message-queue.h"
 #include "jabber_whiteboard/defines.h"
 
 #include "gc-alloc.h"
 
+class SPDocument;
 class SPDesktop;
 
+
 namespace Inkscape {
 
 namespace Whiteboard {
 
-enum SessionType {
-    INKBOARD_PRIVATE,
-    INKBOARD_MUC
-};
-
-class SessionManager;
 class InkboardDocument;
 
-class SessionManager : public Pedro::XmppEventListener {
+typedef Glib::ustring from,sessionId;
+typedef std::pair< Glib::ustring, InkboardDocument* > WhiteboardRecord;
+typedef std::vector< WhiteboardRecord, GC::Alloc< WhiteboardRecord, GC::MANUAL > > WhiteboardList;
+
+typedef std::pair< from, sessionId > Invitation;
+typedef std::list< Invitation > InvitationList;
+
+class SessionManager : public Pedro::XmppEventListener 
+{
+
 public:
 
-    /**
-     *
-     */
     SessionManager();
 
-    /**
-     *
-     */
     virtual ~SessionManager();
 
 
-    static void showClient();
-    static SessionManager& instance();
+    static void             showClient();
+    static SessionManager&  instance();
 
-    /**
-     *
-     */
     virtual Pedro::XmppClient &getClient()
         { return gui.client; }
 
     /**
-     *
+     * Handles all incoming XMPP events associated with this document
+     * apart from CONNECT_REQUEST, which is handled in SessionManager
      */
     virtual void processXmppEvent(const Pedro::XmppEvent &event);
 
-    /**
-     * The session handling has been broken out into a subclass of XML::Session.  See
-     * Whiteboard::InkboardSession and Whiteboard::InkboardDocument, both of which
-     * are still under heavy construction.  Don't expect them to work just yet.
-     *
-     * This (should) allow us to substitute an InkboardDocument for an
-     * XML::SimpleDocument (InkboardDocument uses InkboardSession), which, I think, should 
-     * lead to a very clean way of integrating Inkboard.  It should also
-     * give us a cleaner way of handling node tracking.  Finally,
-     * it'll let us experiment with data models that may be more appropriate for Inkboard.
-     *
-     * SessionManager still manages sessions insofar as it receives XMPP data from Pedro and
-     * sends it off to the correct InkboardSession.  I'd like to have it still manage
-     * user sessions, which is what the user sees; however, that can be confusing from
-     * a programmer's standpoint.  This class might therefore need to be renamed 
-     * or something.
-     *
-     * Creation of an Inkboard session should be handled in some fashion similar
-     * to this:
-     *
-     * (1) The user chooses a chat room or user with which she wants to share a whiteboard.
-     *
-     * (2) This invokes the appropriate doShare() method in Pedro's GUI.
-     *
-     * (3) doShare() invokes code to create a new Inkscape desktop with a blank document.
-     * This desktop will use InkboardDocument (and hence InkboardSession) for transaction
-     * management.
-        *
-     * (4) Inkboard setup and operation proceeds as it did in the Loudmouth-based code.
-     *
-     * (3) and (4) will probably need tweaking (for example, it's probably a bad idea to
-     * open up a new desktop if an invitation is refused).   Actually, really, nothing
-     * here is set in stone.  Feel free to modify.             -- dwyip 2005-11-21
-     * 
-     */
 
     /**
      * Initiates a shared session with a user or conference room.
@@ -109,29 +73,22 @@ public:
      * \param to The recipient to which this desktop will be linked, specified as a JID.
      * \param type Type of the session; i.e. private message or group chat.
      */
-    virtual void doShare(Glib::ustring const& to, State::SessionType type);
+    virtual void initialiseSession(Glib::ustring const& to, State::SessionType type);
 
     /**
-     * Creates a new desktop with an InkboardDocument.
-     *
-     * An InkboardDocument (and hence desktop)
-     * is identified by the recipient of the document, be it a 
-     * conference room or another user.  If an existing document is found, it will be
-     * returned.
+     * Terminates an Inkboard session to a given recipient.  If the session to be
+     * terminated does not exist, does nothing.
      *
-     * \param to The recipient to which this desktop will be linked, specified as a JID.
-     * \param type Type of the session; i.e. private message or group chat.
-     * \return A pointer to the created SPDesktop.
+     * \param sessionId The session identifier to be terminated.
      */
-    virtual SPDesktop* createInkboardDesktop(Glib::ustring const& to, State::SessionType type);
+    virtual void terminateSession(Glib::ustring const& sessionId);
 
     /**
-     * Terminates an Inkboard session to a given recipient.  If the session to be
-     * terminated does not exist, does nothing.
+     * Adds a session to whiteboard
      *
-     * \param to The recipient JID identifying the session to be terminated.
+     * \param sessionId The session identifier to be terminated.
      */
-    virtual void terminateInkboardSession(Glib::ustring const& to);
+    virtual void addSession(WhiteboardRecord whiteboard);
 
     /**
      * Locates an Inkboard session by recipient JID.  
@@ -142,58 +99,29 @@ public:
      */
     InkboardDocument* getInkboardSession(Glib::ustring const& to);
 
-       void operator=(XmppEventListener const& other) {
 
-       }
+    void operator=(XmppEventListener const& other) {}
+
 private:
-    
-       // types
-    typedef std::pair< Glib::ustring, InkboardDocument* > Inkboard_record_type;
-    typedef std::vector< Inkboard_record_type, GC::Alloc< Inkboard_record_type, GC::MANUAL > > Inkboards_type;
-
-    typedef std::list< Glib::ustring > Pending_invitations_type;
-
-    typedef std::pair< Glib::ustring, InvitationResponses > Invitation_response_type;
-    typedef std::list< Invitation_response_type > Invitation_responses_type;
-
-    // functors
-    struct CheckInvitationSender {
-        public:
-               CheckInvitationSender(Glib::ustring const& x) : x(x) { }
-               ~CheckInvitationSender() { }
-
-               bool operator()(SessionManager::Invitation_response_type const& y) const {
-                       return (x == y.first);
-               }
-       private:
-               Glib::ustring const& x;
-    };
-
-    // objects 
-    Pedro::PedroGui gui;
-    SendMessageQueue sendMessageQueue;
-    ReceiveMessageQueue receiveMessageQueue;
-
-    // members
-    unsigned long sequenceNumber;
-    Inkboards_type _inkboards;
-    Pending_invitations_type _pending_invitations;
-    Invitation_responses_type _invitation_responses;
-
-    sigc::connection _check_pending_invitations;
-    sigc::connection _check_invitation_responses;
-
-       // methods
-    void _processInkboardEvent(Pedro::XmppEvent const& event);
-    void _handleSessionEvent(Message::Wrapper mtype, Pedro::XmppEvent const& event);
-    void _handleIncomingInvitation(Glib::ustring const& from);
-    void _handleInvitationResponse(Glib::ustring const& from, InvitationResponses resp);
-
-    // methods handled externally
-    bool _checkInvitationQueue();
-    bool _checkInvitationResponseQueue();
+
+    Pedro::PedroGui     gui;
+    WhiteboardList      whiteboards;
+    InvitationList      invitations;
+    sigc::connection    CheckPendingInvitations;
+
+    void    processWhiteboardEvent(Pedro::XmppEvent const& event);
+
+    void    handleIncomingInvitation(Invitation invitation);
+
+    bool    checkInvitationQueue();
+
+    char*   createSessionId(int size);
+
 };
 
+SPDocument* makeInkboardDocument(int code, gchar const* rootname, State::SessionType type, Glib::ustring const& to);
+SPDesktop*  makeInkboardDesktop(SPDocument* doc);
+
 }  // namespace Whiteboard
 
 }  // namespace Inkscape