summaryrefslogtreecommitdiffstats
path: root/src/jabber_whiteboard/connection-establishment.cpp
diff options
context:
space:
mode:
authorMenTaLguY <mental@rydia.net>2006-01-16 02:36:01 +0000
committermental <mental@users.sourceforge.net>2006-01-16 02:36:01 +0000
commit179fa413b047bede6e32109e2ce82437c5fb8d34 (patch)
treea5a6ac2c1708bd02288fbd8edb2ff500ff2e0916 /src/jabber_whiteboard/connection-establishment.cpp
downloadinkscape-179fa413b047bede6e32109e2ce82437c5fb8d34.tar.gz
inkscape-179fa413b047bede6e32109e2ce82437c5fb8d34.zip
moving trunk for module inkscape
(bzr r1)
Diffstat (limited to 'src/jabber_whiteboard/connection-establishment.cpp')
-rw-r--r--src/jabber_whiteboard/connection-establishment.cpp307
1 files changed, 307 insertions, 0 deletions
diff --git a/src/jabber_whiteboard/connection-establishment.cpp b/src/jabber_whiteboard/connection-establishment.cpp
new file mode 100644
index 000000000..9382227fb
--- /dev/null
+++ b/src/jabber_whiteboard/connection-establishment.cpp
@@ -0,0 +1,307 @@
+/**
+ * Whiteboard session manager
+ * Methods for establishing connections and notifying the user of events
+ *
+ * Authors:
+ * David Yip <yipdw@rose-hulman.edu>
+ *
+ * Copyright (c) 2005 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "util/ucompose.hpp"
+#include <glibmm/i18n.h>
+#include <gtkmm/dialog.h>
+#include <gtkmm/messagedialog.h>
+
+#include "desktop.h"
+#include "file.h"
+#include "document.h"
+
+#include "xml/repr.h"
+
+#include "jabber_whiteboard/defines.h"
+#include "jabber_whiteboard/typedefs.h"
+#include "jabber_whiteboard/node-tracker.h"
+#include "jabber_whiteboard/chat-handler.h"
+#include "jabber_whiteboard/message-queue.h"
+#include "jabber_whiteboard/session-manager.h"
+#include "jabber_whiteboard/invitation-confirm-dialog.h"
+
+namespace Inkscape {
+
+namespace Whiteboard {
+
+void
+SessionManager::sendRequestToUser(std::string const& recipientJID)
+{
+ /*
+ Glib::ustring doccopy;
+ if (document != NULL) {
+ doccopy = *document;
+ }
+ */
+ this->session_data->status.set(WAITING_FOR_INVITE_RESPONSE, 1);
+ this->sendMessage(CONNECT_REQUEST_USER, 0, "", recipientJID.c_str(), false);
+}
+
+void
+SessionManager::sendRequestToChatroom(Glib::ustring const& server, Glib::ustring const& chatroom, Glib::ustring const& handle, Glib::ustring const& password)
+{
+ // We do not yet use the Basic MUC Protocol for connection establishment etc
+ // <http://www.jabber.org/jeps/jep-0045.html>. The protocol we use is the
+ // old GroupChat system; extension to MUC is TODO
+
+ // Compose room@service/nick string for "to" field
+ Glib::ustring dest = String::ucompose("%1@%2/%3", chatroom, server, handle);
+ LmMessage* presence_req = lm_message_new(dest.data(), LM_MESSAGE_TYPE_PRESENCE);
+
+ // Add 'from' attribute
+ LmMessageNode* preq_root = lm_message_get_node(presence_req);
+
+ lm_message_node_set_attribute(preq_root, "from", lm_connection_get_jid(this->session_data->connection));
+
+ // Add <x xmlns='http://jabber.org/protocol/muc/' />
+ // (Not anymore: we don't speak it! -- yipdw)
+ LmMessageNode* xmlns_node = lm_message_node_add_child(preq_root, "x", "");
+ lm_message_node_set_attribute(xmlns_node, "xmlns", "http://jabber.org/protocol/muc/");
+
+ // If a password was supplied, add it to xmlns_node
+ if (password != NULL) {
+ lm_message_node_add_child(xmlns_node, "password", password.c_str());
+ }
+
+ // Create chat message handler and node tracker
+ if (!this->_myChatHandler) {
+ this->_myChatHandler = new ChatMessageHandler(this);
+ }
+
+ // Flag ourselves as connecting to a chatroom (but not yet connected)
+ this->session_data->status.set(CONNECTING_TO_CHAT, 1);
+ // Send the message
+ GError *error = NULL;
+ if (!lm_connection_send(this->session_data->connection, presence_req, &error)) {
+ g_error("Presence message could not be sent to %s: %s", dest.data(), error->message);
+ this->session_data->status.set(CONNECTING_TO_CHAT, 0);
+ }
+
+ this->session_data->chat_handle = handle;
+ this->session_data->chat_server = server;
+ this->session_data->chat_name = chatroom;
+
+ this->setRecipient(String::ucompose("%1@%2", chatroom, server).data());
+
+ lm_message_unref(presence_req);
+}
+
+void
+SessionManager::sendConnectRequestResponse(char const* recipientJID, gboolean accepted_request)
+{
+ if (accepted_request == TRUE) {
+ this->setRecipient(recipientJID);
+ this->session_data->status.set(IN_WHITEBOARD, 1);
+ }
+
+ this->sendMessage(CONNECT_REQUEST_RESPONSE_USER, accepted_request, "", recipientJID, false);
+}
+
+// When this method is invoked, it means that the user has received an invitation from another peer
+// to engage in a whiteboard session (i.e. 1:1 communication). The user may accept or reject this invitation.
+void
+SessionManager::receiveConnectRequest(gchar const* requesterJID)
+{
+ int x, y;
+ Gdk::ModifierType mt;
+ Gdk::Display::get_default()->get_pointer(x, y, mt);
+
+ if (mt) {
+ // Attach a polling timeout
+ this->_notify_incoming_request = Glib::signal_timeout().connect(sigc::bind< 0 >(sigc::mem_fun(*this, &SessionManager::_pollReceiveConnectRequest), requesterJID), 50);
+ return;
+ }
+
+ if (this->session_data->status[IN_WHITEBOARD]) {
+ this->sendMessage(ALREADY_IN_SESSION, 0, "", requesterJID, false);
+ }
+
+ // Check to see if the user made any modifications to this document. If so,
+ // we want to give them the option of (1) letting us clear their document or (2)
+ // opening a new, blank document for the whiteboard session.
+ Glib::ustring primary = "<span weight=\"bold\" size=\"larger\">" + String::ucompose(_("<b>%1</b> has invited you to a whiteboard session."), requesterJID) + "</span>\n\n";
+ Glib::ustring title = String::ucompose(_("Incoming whiteboard invitation from %1"), requesterJID);
+
+ if (sp_document_repr_root(this->_myDoc)->attribute("sodipodi:modified") == NULL) {
+ primary += String::ucompose(_("Do you wish to accept <b>%1</b>'s whiteboard session invitation?"), requesterJID);
+ } else {
+ primary += String::ucompose(_("Would you like to accept %1's invitation in a new document window?\nAccepting the invitation in your current window will discard unsaved changes."), requesterJID);
+ }
+
+ // Construct confirmation dialog
+ InvitationConfirmDialog dialog(primary);
+
+ dialog.add_button(_("Accept invitation"), ACCEPT_INVITATION);
+ dialog.add_button(_("Decline invitation"), DECLINE_INVITATION);
+ dialog.add_button(_("Accept invitation in new document window"), ACCEPT_INVITATION_IN_NEW_WINDOW);
+
+ bool undecided = true;
+ InvitationResponses resp = static_cast< InvitationResponses >(dialog.run());
+
+ while(undecided) {
+ if (resp == ACCEPT_INVITATION) {
+ undecided = false;
+ this->clearDocument();
+
+ // Create a receive queue for the initiator of this request
+ this->session_data->receive_queues[requesterJID] = new ReceiveMessageQueue(this);
+
+ this->setupInkscapeInterface();
+ if (dialog.useSessionFile()) {
+ this->session_data->sessionFile = dialog.getSessionFilePath();
+ this->_tryToStartLog();
+ }
+ this->sendConnectRequestResponse(requesterJID, TRUE);
+
+ } else if (resp == ACCEPT_INVITATION_IN_NEW_WINDOW) {
+ SPDesktop* newdesktop = sp_file_new_default();
+ if (newdesktop != NULL) {
+ undecided = false;
+
+ // Swap desktops around
+
+ // Destroy the new desktop's session manager and add this one in
+ delete newdesktop->_whiteboard_session_manager;
+ newdesktop->_whiteboard_session_manager = this;
+
+ // Assign a new session manager to our old desktop
+ this->_myDesktop->_whiteboard_session_manager = new SessionManager(this->_myDesktop);
+
+ // Reset our desktop and document pointers
+ this->setDesktop(newdesktop);
+
+ // Prepare document and send acceptance notification
+ this->session_data->receive_queues[requesterJID] = new ReceiveMessageQueue(this);
+ this->clearDocument();
+ this->setupInkscapeInterface();
+ if (dialog.useSessionFile()) {
+ this->session_data->sessionFile = dialog.getSessionFilePath();
+ this->_tryToStartLog();
+ }
+ this->sendConnectRequestResponse(requesterJID, TRUE);
+
+ } else {
+ // We could not create a new desktop; ask the user if she or he wants to
+ // replace the current document and accept the invitation, or reject the invitation.
+ // TRANSLATORS: %1 is a userid here
+ Glib::ustring msg = "<span weight=\"bold\" size=\"larger\">" + String::ucompose(_("A new document window could not be opened for a whiteboard session with <b>%1</b>"), requesterJID) + ".</span>\n\nWould you like to accept the whiteboard connection in the active document or refuse the invitation?";
+ InvitationConfirmDialog replace_dialog(msg);
+ dialog.add_button(_("Accept invitation"), ACCEPT_INVITATION);
+ dialog.add_button(_("Decline invitation"), DECLINE_INVITATION);
+ resp = static_cast< InvitationResponses >(dialog.run());
+ }
+ } else {
+ undecided = false;
+ this->sendMessage(CONNECT_REQUEST_REFUSED_BY_PEER, 0, "", requesterJID, false);
+ }
+ }
+}
+
+// When this method is invoked, it means that the other peer
+// has accepted our request.
+void
+SessionManager::receiveConnectRequestResponse(InvitationResponses response, std::string& sender)
+{
+ this->session_data->status.set(WAITING_FOR_INVITE_RESPONSE, 0);
+
+ switch(response) {
+ case ACCEPT_INVITATION:
+ {
+
+ // Create a receive queue for the other peer.
+ this->session_data->receive_queues[sender] = new ReceiveMessageQueue(this);
+
+ KeyToNodeMap newids;
+ NodeToKeyMap newnodes;
+ this->_myTracker = new XMLNodeTracker(this);
+ this->setupInkscapeInterface();
+ this->_tryToStartLog();
+ this->resendDocument(this->session_data->recipient, newids, newnodes);
+ this->_myTracker->put(newids, newnodes);
+// this->_myTracker->dump();
+ this->setupCommitListener();
+ break;
+ }
+
+ case DECLINE_INVITATION:
+ {
+ // TRANSLATORS: %1 is the peer whom refused our invitation.
+ Glib::ustring primary = String::ucompose(_("<span weight=\"bold\" size=\"larger\">The user <b>%1</b> has refused your whiteboard invitation.</span>\n\n"), sender);
+
+ // 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."), sender, lm_connection_get_jid(this->session_data->connection));
+
+ Gtk::MessageDialog dialog(primary + secondary, true, Gtk::MESSAGE_INFO, Gtk::BUTTONS_CLOSE, false);
+ dialog.run();
+ break;
+
+ }
+
+ case PEER_ALREADY_IN_SESSION:
+ {
+ // TRANSLATORS: %1 is the peer whom we tried to contact, but is already in a whiteboard session.
+ Glib::ustring primary = String::ucompose(_("<span weight=\"bold\" size=\"larger\">The user <b>%1</b> is already in a whiteboard session.</span>\n\n"), sender);
+
+ // TRANSLATORS: %1 is the peer whom we tried to contact, but is already in a whiteboard session.
+ Glib::ustring secondary = String::ucompose(_("You are still connected to a Jabber server as <b>%1</b>, and may send an invitation to a different user."), sender);
+ Gtk::MessageDialog dialog(primary + secondary, true, Gtk::MESSAGE_INFO, Gtk::BUTTONS_CLOSE, false);
+ dialog.run();
+
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+void
+SessionManager::receiveConnectRequestResponseChat(gchar const* recipient)
+{
+ // When responding to connection request responses in chatrooms,
+ // the responding user is already established in the whiteboard session.
+ // Therefore we do not need to perform any setup of observers or dispatchers; the requesting user
+ // will do that.
+
+ KeyToNodeMap newids;
+ NodeToKeyMap newnodes;
+ this->resendDocument(recipient, newids, newnodes);
+}
+
+bool
+SessionManager::_pollReceiveConnectRequest(Glib::ustring const recipientJID)
+{
+ int x, y;
+ Gdk::ModifierType mt;
+ Gdk::Display::get_default()->get_pointer(x, y, mt);
+
+ if (mt) {
+ return true;
+ } else {
+ this->receiveConnectRequest(recipientJID.c_str());
+ return false;
+ }
+}
+
+}
+
+}
+
+/*
+ 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 :