From 83f6dbd0036f3f2e23f9015626ef42d4836fbeee Mon Sep 17 00:00:00 2001
From: Mateusz Piekos <mateuszpiekos@gmail.com>
Date: Thu, 14 Jun 2012 16:23:32 +0200
Subject: Improved session initialization from UI side


diff --git a/Swift/Controllers/Chat/ChatController.cpp b/Swift/Controllers/Chat/ChatController.cpp
index 12d3814..3b74368 100644
--- a/Swift/Controllers/Chat/ChatController.cpp
+++ b/Swift/Controllers/Chat/ChatController.cpp
@@ -26,6 +26,9 @@
 #include <Swiften/Base/foreach.h>
 #include <Swift/Controllers/UIEvents/UIEventStream.h>
 #include <Swift/Controllers/UIEvents/SendFileUIEvent.h>
+#include <Swift/Controllers/UIEvents/AcceptWhiteboardSessionUIEvent.h>
+#include <Swift/Controllers/UIEvents/CancelWhiteboardSessionUIEvent.h>
+#include <Swift/Controllers/UIEvents/ShowWhiteboardUIEvent.h>
 #include <Swiften/Elements/DeliveryReceipt.h>
 #include <Swiften/Elements/DeliveryReceiptRequest.h>
 #include <Swift/Controllers/SettingConstants.h>
@@ -73,6 +76,9 @@ ChatController::ChatController(const JID& self, StanzaChannel* stanzaChannel, IQ
 	chatWindow_->onFileTransferAccept.connect(boost::bind(&ChatController::handleFileTransferAccept, this, _1, _2));
 	chatWindow_->onFileTransferCancel.connect(boost::bind(&ChatController::handleFileTransferCancel, this, _1));
 	chatWindow_->onSendFileRequest.connect(boost::bind(&ChatController::handleSendFileRequest, this, _1));
+	chatWindow_->onWhiteboardSessionAccept.connect(boost::bind(&ChatController::handleWhiteboardSessionAccept, this));
+	chatWindow_->onWhiteboardSessionCancel.connect(boost::bind(&ChatController::handleWhiteboardSessionCancel, this));
+	chatWindow_->onWhiteboardWindowShow.connect(boost::bind(&ChatController::handleWhiteboardWindowShow, this));
 	handleBareJIDCapsChanged(toJID_);
 
 	settings_->onSettingChanged.connect(boost::bind(&ChatController::handleSettingChanged, this, _1));
@@ -255,8 +261,12 @@ void ChatController::handleNewFileTransferController(FileTransferController* ftc
 	ftControllers[ftID] = ftc;
 }
 
-void ChatController::handleIncomingWhiteboardSession() {
-	chatWindow_->addWhiteboardRequest(toJID_);
+void ChatController::handleWhiteboardSessionRequest(bool senderIsSelf) {
+	lastWbID_ = chatWindow_->addWhiteboardRequest(toJID_, senderIsSelf);
+}
+
+void ChatController::handleWhiteboardStateChange(const ChatWindow::WhiteboardSessionState state) {
+	chatWindow_->setWhiteboardSessionStatus(lastWbID_, state);
 }
 
 void ChatController::handleFileTransferCancel(std::string id) {
@@ -291,6 +301,18 @@ void ChatController::handleSendFileRequest(std::string filename) {
 	eventStream_->send(boost::make_shared<SendFileUIEvent>(getToJID(), filename));
 }
 
+void ChatController::handleWhiteboardSessionAccept() {
+	eventStream_->send(boost::make_shared<AcceptWhiteboardSessionUIEvent>(toJID_));
+}
+
+void ChatController::handleWhiteboardSessionCancel() {
+	eventStream_->send(boost::make_shared<CancelWhiteboardSessionUIEvent>(toJID_));
+}
+
+void ChatController::handleWhiteboardWindowShow() {
+	eventStream_->send(boost::make_shared<ShowWhiteboardUIEvent>(toJID_));
+}
+
 std::string ChatController::senderDisplayNameFromMessage(const JID& from) {
 	return nickResolver_->jidToNick(from);
 }
diff --git a/Swift/Controllers/Chat/ChatController.h b/Swift/Controllers/Chat/ChatController.h
index 561bbf4..6687c70 100644
--- a/Swift/Controllers/Chat/ChatController.h
+++ b/Swift/Controllers/Chat/ChatController.h
@@ -29,7 +29,8 @@ namespace Swift {
 			virtual void setToJID(const JID& jid);
 			virtual void setOnline(bool online);
 			virtual void handleNewFileTransferController(FileTransferController* ftc);
-			virtual void handleIncomingWhiteboardSession();
+			virtual void handleWhiteboardSessionRequest(bool senderIsSelf);
+			virtual void handleWhiteboardStateChange(const ChatWindow::WhiteboardSessionState state);
 			virtual void setContactIsReceivingPresence(bool /*isReceivingPresence*/);
 
 		protected:
@@ -56,6 +57,10 @@ namespace Swift {
 			void handleFileTransferAccept(std::string /* id */, std::string /* filename */);
 			void handleSendFileRequest(std::string filename);
 
+			void handleWhiteboardSessionAccept();
+			void handleWhiteboardSessionCancel();
+			void handleWhiteboardWindowShow();
+
 			void handleSettingChanged(const std::string& settingPath);
 			void checkForDisplayingDisplayReceiptsAlert();
 
@@ -77,6 +82,7 @@ namespace Swift {
 			bool userWantsReceipts_;
 			std::map<std::string, FileTransferController*> ftControllers;
 			SettingsProvider* settings_;
+			std::string lastWbID_;
 	};
 }
 
diff --git a/Swift/Controllers/Chat/ChatsManager.cpp b/Swift/Controllers/Chat/ChatsManager.cpp
index 380b3ae..616c0c6 100644
--- a/Swift/Controllers/Chat/ChatsManager.cpp
+++ b/Swift/Controllers/Chat/ChatsManager.cpp
@@ -110,7 +110,9 @@ ChatsManager::ChatsManager(
 	mucSearchController_ = new MUCSearchController(jid_, mucSearchWindowFactory, iqRouter, profileSettings_);
 	mucSearchController_->onMUCSelected.connect(boost::bind(&ChatsManager::handleMUCSelectedAfterSearch, this, _1));
 	ftOverview_->onNewFileTransferController.connect(boost::bind(&ChatsManager::handleNewFileTransferController, this, _1));
-	whiteboardSessionManager_->onRequestReceived.connect(boost::bind(&ChatsManager::handleIncomingWhiteboardSession, this, _1));
+	whiteboardSessionManager_->onSessionRequest.connect(boost::bind(&ChatsManager::handleWhiteboardSessionRequest, this, _1, _2));
+	whiteboardSessionManager_->onRequestAccepted.connect(boost::bind(&ChatsManager::handleWhiteboardStateChange, this, _1, ChatWindow::WhiteboardAccepted));
+	whiteboardSessionManager_->onSessionTerminate.connect(boost::bind(&ChatsManager::handleWhiteboardStateChange, this, _1, ChatWindow::WhiteboardCanceled));
 	roster_->onJIDAdded.connect(boost::bind(&ChatsManager::handleJIDAddedToRoster, this, _1));
 	roster_->onJIDRemoved.connect(boost::bind(&ChatsManager::handleJIDRemovedFromRoster, this, _1));
 	roster_->onJIDUpdated.connect(boost::bind(&ChatsManager::handleJIDUpdatedInRoster, this, _1));
@@ -659,9 +661,15 @@ void ChatsManager::handleNewFileTransferController(FileTransferController* ftc)
 	chatController->activateChatWindow();
 }
 
-void ChatsManager::handleIncomingWhiteboardSession(const JID& from) {
-	ChatController* chatController = getChatControllerOrCreate(from);
-	chatController->handleIncomingWhiteboardSession();
+void ChatsManager::handleWhiteboardSessionRequest(const JID& contact, bool senderIsSelf) {
+	ChatController* chatController = getChatControllerOrCreate(contact);
+	chatController->handleWhiteboardSessionRequest(senderIsSelf);
+	chatController->activateChatWindow();
+}
+
+void ChatsManager::handleWhiteboardStateChange(const JID& contact, const ChatWindow::WhiteboardSessionState state) {
+	ChatController* chatController = getChatControllerOrCreate(contact);
+	chatController->handleWhiteboardStateChange(state);
 	chatController->activateChatWindow();
 }
 
diff --git a/Swift/Controllers/Chat/ChatsManager.h b/Swift/Controllers/Chat/ChatsManager.h
index 3fcd3fb..69cf1bd 100644
--- a/Swift/Controllers/Chat/ChatsManager.h
+++ b/Swift/Controllers/Chat/ChatsManager.h
@@ -18,6 +18,7 @@
 #include <Swiften/MUC/MUCRegistry.h>
 #include <Swift/Controllers/UIEvents/UIEventStream.h>
 #include <Swift/Controllers/UIInterfaces/ChatListWindow.h>
+#include <Swift/Controllers/UIInterfaces/ChatWindow.h>
 #include <Swiften/MUC/MUCBookmark.h>
 
 namespace Swift {
@@ -73,7 +74,8 @@ namespace Swift {
 			void handleBookmarksReady();
 			void handleChatActivity(const JID& jid, const std::string& activity, bool isMUC);
 			void handleNewFileTransferController(FileTransferController*);
-			void handleIncomingWhiteboardSession(const JID& from);
+			void handleWhiteboardSessionRequest(const JID& contact, bool senderIsSelf);
+			void handleWhiteboardStateChange(const JID& contact, const ChatWindow::WhiteboardSessionState state);
 			void appendRecent(const ChatListWindow::Chat& chat);
 			void prependRecent(const ChatListWindow::Chat& chat);
 			void setupBookmarks();
diff --git a/Swift/Controllers/UIEvents/ShowWhiteboardUIEvent.h b/Swift/Controllers/UIEvents/ShowWhiteboardUIEvent.h
new file mode 100644
index 0000000..265bf7d
--- /dev/null
+++ b/Swift/Controllers/UIEvents/ShowWhiteboardUIEvent.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2012 Mateusz Piękos
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include "Swiften/JID/JID.h"
+
+#include "Swift/Controllers/UIEvents/UIEvent.h"
+
+namespace Swift {
+	class ShowWhiteboardUIEvent : public UIEvent {
+	public:
+		ShowWhiteboardUIEvent(const JID& contact) : contact_(contact) {};
+		const JID& getContact() const {return contact_;}
+	private:
+		JID contact_;
+	};
+}
+
diff --git a/Swift/Controllers/UIInterfaces/ChatWindow.h b/Swift/Controllers/UIInterfaces/ChatWindow.h
index 66cc8c3..db9e322 100644
--- a/Swift/Controllers/UIInterfaces/ChatWindow.h
+++ b/Swift/Controllers/UIInterfaces/ChatWindow.h
@@ -36,6 +36,7 @@ namespace Swift {
 			enum OccupantAction {Kick, Ban, MakeModerator, MakeParticipant, MakeVisitor, AddContact};
 			enum RoomAction {ChangeSubject, Configure, Affiliations, Destroy, Invite};
 			enum FileTransferState {WaitingForAccept, Negotiating, Transferring, Canceled, Finished, FTFailed};
+			enum WhiteboardSessionState {WhiteboardAccepted, WhiteboardCanceled, WhiteboardTerminated};
 			ChatWindow() {}
 			virtual ~ChatWindow() {};
 
@@ -59,7 +60,8 @@ namespace Swift {
 			virtual void setFileTransferStatus(std::string, const FileTransferState state, const std::string& msg = "") = 0;
 			virtual void addMUCInvitation(const std::string& senderName, const JID& jid, const std::string& reason, const std::string& password, bool direct = true) = 0;
 
-			virtual void addWhiteboardRequest(const JID& from) = 0;
+			virtual std::string addWhiteboardRequest(const JID& from, bool senderIsSelf) = 0;
+			virtual void setWhiteboardSessionStatus(std::string id, const ChatWindow::WhiteboardSessionState state) = 0;
 
 			// message receipts
 			virtual void setMessageReceiptState(const std::string& id, ChatWindow::ReceiptState state) = 0;
@@ -131,6 +133,11 @@ namespace Swift {
 			boost::signal<void (std::string /* id */, std::string /* description */)> onFileTransferStart;
 			boost::signal<void (std::string /* id */, std::string /* path */)> onFileTransferAccept;
 			boost::signal<void (std::string /* path */)> onSendFileRequest;
+
+			//Whiteboard related	
+			boost::signal<void ()> onWhiteboardSessionAccept;
+			boost::signal<void ()> onWhiteboardSessionCancel;
+			boost::signal<void ()> onWhiteboardWindowShow;
 	};
 }
 
diff --git a/Swift/Controllers/UIInterfaces/WhiteboardWindow.h b/Swift/Controllers/UIInterfaces/WhiteboardWindow.h
index ae736d7..b821940 100644
--- a/Swift/Controllers/UIInterfaces/WhiteboardWindow.h
+++ b/Swift/Controllers/UIInterfaces/WhiteboardWindow.h
@@ -20,6 +20,7 @@ namespace Swift {
 		virtual void show() = 0;
 		virtual void addItem(const std::string& item) = 0;
 		virtual void setSession(boost::shared_ptr<WhiteboardSession> session) = 0;
+		virtual void activateWindow() = 0;
 
 		boost::signal<void (std::string)> onItemAdd;
 	};
diff --git a/Swift/Controllers/WhiteboardManager.cpp b/Swift/Controllers/WhiteboardManager.cpp
index f6db4ff..c62ce3d 100644
--- a/Swift/Controllers/WhiteboardManager.cpp
+++ b/Swift/Controllers/WhiteboardManager.cpp
@@ -12,6 +12,7 @@
 #include <Swift/Controllers/UIEvents/RequestWhiteboardUIEvent.h>
 #include <Swift/Controllers/UIEvents/AcceptWhiteboardSessionUIEvent.h>
 #include <Swift/Controllers/UIEvents/CancelWhiteboardSessionUIEvent.h>
+#include <Swift/Controllers/UIEvents/ShowWhiteboardUIEvent.h>
 #include <Swiften/Client/StanzaChannel.h>
 #include <Swiften/Whiteboard/WhiteboardSessionManager.h>
 
@@ -61,6 +62,13 @@ namespace Swift {
 		if (sessionCancelEvent) {
 			cancelSession(sessionCancelEvent->getContact());
 		}
+		boost::shared_ptr<ShowWhiteboardUIEvent> showWindowEvent = boost::dynamic_pointer_cast<ShowWhiteboardUIEvent>(event);
+		if (showWindowEvent) {
+			WhiteboardWindow* window = findWhiteboardWindow(showWindowEvent->getContact());
+			if (window != NULL) {
+				window->activateWindow();
+			}
+		}
 	}
 
 	void WhiteboardManager::acceptSession(const JID& from) {
diff --git a/Swift/QtUI/QtChatView.cpp b/Swift/QtUI/QtChatView.cpp
index 54bce09..d8c0df1 100644
--- a/Swift/QtUI/QtChatView.cpp
+++ b/Swift/QtUI/QtChatView.cpp
@@ -361,6 +361,18 @@ void QtChatView::setFileTransferStatus(QString id, const ChatWindow::FileTransfe
 	ftElement.setInnerXml(newInnerHTML);
 }
 
+void QtChatView::setWhiteboardSessionStatus(QString id, const ChatWindow::WhiteboardSessionState state) {
+	QWebElement divElement = findDivElementWithID(document_, id);
+	QString newInnerHTML;
+	if (state == ChatWindow::WhiteboardAccepted) {
+		newInnerHTML =	tr("Started whiteboard session") + "<br/>" +
+			QtChatWindow::buildChatWindowButton(tr("Show whitebaord"), QtChatWindow::ButtonWhiteboardShowWindow, id);
+	} else if (state == ChatWindow::WhiteboardCanceled) {
+		newInnerHTML =	tr("Whiteboard session has been canceled");
+	}
+	divElement.setInnerXml(newInnerHTML);
+}
+
 void QtChatView::setMUCInvitationJoined(QString id) {
 	QWebElement divElement = findDivElementWithID(document_, id);
 	QWebElement buttonElement = divElement.findFirst("input#mucinvite");
diff --git a/Swift/QtUI/QtChatView.h b/Swift/QtUI/QtChatView.h
index 2e64593..7e4328a 100644
--- a/Swift/QtUI/QtChatView.h
+++ b/Swift/QtUI/QtChatView.h
@@ -42,6 +42,7 @@ namespace Swift {
 			void addToJSEnvironment(const QString&, QObject*);
 			void setFileTransferProgress(QString id, const int percentageDone);
 			void setFileTransferStatus(QString id, const ChatWindow::FileTransferState state, const QString& msg);
+			void setWhiteboardSessionStatus(QString id, const ChatWindow::WhiteboardSessionState state);
 			void setMUCInvitationJoined(QString id);
 
 		signals:
diff --git a/Swift/QtUI/QtChatWindow.cpp b/Swift/QtUI/QtChatWindow.cpp
index b1ee3a8..3204933 100644
--- a/Swift/QtUI/QtChatWindow.cpp
+++ b/Swift/QtUI/QtChatWindow.cpp
@@ -23,8 +23,6 @@
 #include <Swift/Controllers/UIEvents/UIEventStream.h>
 #include <Swift/Controllers/UIEvents/SendFileUIEvent.h>
 #include <Swift/Controllers/UIEvents/JoinMUCUIEvent.h>
-#include <Swift/Controllers/UIEvents/AcceptWhiteboardSessionUIEvent.h>
-#include <Swift/Controllers/UIEvents/CancelWhiteboardSessionUIEvent.h>
 #include "QtChatWindowJSBridge.h"
 
 #include <boost/cstdint.hpp>
@@ -56,6 +54,7 @@ namespace Swift {
 
 const QString QtChatWindow::ButtonWhiteboardSessionCancel = QString("whiteboard-cancel");
 const QString QtChatWindow::ButtonWhiteboardSessionAcceptRequest = QString("whiteboard-acceptrequest");
+const QString QtChatWindow::ButtonWhiteboardShowWindow = QString("whiteboard-showwindow");
 const QString QtChatWindow::ButtonFileTransferCancel = QString("filetransfer-cancel");
 const QString QtChatWindow::ButtonFileTransferSetDescription = QString("filetransfer-setdescription");
 const QString QtChatWindow::ButtonFileTransferSendRequest = QString("filetransfer-sendrequest");
@@ -597,13 +596,17 @@ void QtChatWindow::setFileTransferStatus(std::string id, const FileTransferState
 	messageLog_->setFileTransferStatus(QString::fromStdString(id), state, QString::fromStdString(msg));
 }
 
-void QtChatWindow::addWhiteboardRequest(const JID& from) {
-	QString id = QString("wb%1").arg(P2QSTRING(boost::lexical_cast<std::string>(idCounter_++)));
-	QString htmlString = Qt::escape(contact_) + tr(" would like to start whiteboard session") + ": <br/>" +
-			"<div id='" + id + "'>" +
-				buildChatWindowButton(tr("Cancel"), ButtonWhiteboardSessionCancel, P2QSTRING(from.toString())) +
-				buildChatWindowButton(tr("Accept"), ButtonWhiteboardSessionAcceptRequest, P2QSTRING(from.toString())) +
+std::string QtChatWindow::addWhiteboardRequest(const JID& from, bool senderIsSelf) {
+	QString wb_id = QString("wb%1").arg(P2QSTRING(boost::lexical_cast<std::string>(idCounter_++)));
+	QString htmlString;
+	if (senderIsSelf) {
+		htmlString = "<div id='" + wb_id + "'>Sent session request</div>";
+	} else {
+		htmlString = "<div id='" + wb_id + "'>" + Qt::escape(contact_) + tr(" would like to start whiteboard session") + ": <br/>" +
+				buildChatWindowButton(tr("Cancel"), ButtonWhiteboardSessionCancel, wb_id) +
+				buildChatWindowButton(tr("Accept"), ButtonWhiteboardSessionAcceptRequest, wb_id) +
 			"</div>";
+	}
 
 	if (lastLineTracker_.getShouldMoveLastLine()) {
 		/* should this be queued? */
@@ -612,11 +615,16 @@ void QtChatWindow::addWhiteboardRequest(const JID& from) {
 //		appendToPrevious = false;
 	}
 	QString qAvatarPath = "qrc:/icons/avatar.png";
-
-	messageLog_->addMessage(boost::shared_ptr<ChatSnippet>(new MessageSnippet(htmlString, Qt::escape(contact_), B2QDATE(boost::posix_time::second_clock::local_time()), qAvatarPath, false, false, theme_, id)));
+	std::string id = "wbmessage" + boost::lexical_cast<std::string>(idCounter_++);
+	messageLog_->addMessage(boost::shared_ptr<ChatSnippet>(new MessageSnippet(htmlString, Qt::escape(contact_), B2QDATE(boost::posix_time::second_clock::local_time()), qAvatarPath, false, false, theme_, P2QSTRING(id))));
 
 	previousMessageWasSelf_ = false;
 	previousSenderName_ = contact_;
+	return Q2PSTRING(wb_id);
+}
+
+void QtChatWindow::setWhiteboardSessionStatus(std::string id, const ChatWindow::WhiteboardSessionState state) {
+	messageLog_->setWhiteboardSessionStatus(QString::fromStdString(id), state);
 }
 
 void QtChatWindow::handleHTMLButtonClicked(QString id, QString encodedArgument1, QString encodedArgument2, QString encodedArgument3) {
@@ -652,12 +660,18 @@ void QtChatWindow::handleHTMLButtonClicked(QString id, QString encodedArgument1,
 		}
 	}
 	else if (id.startsWith(ButtonWhiteboardSessionAcceptRequest)) {
-		QString fromJID = arg1;
-		eventStream_->send(boost::make_shared<AcceptWhiteboardSessionUIEvent>(Q2PSTRING(fromJID)));
+		QString id = arg1;
+		messageLog_->setWhiteboardSessionStatus(QString::fromStdString(Q2PSTRING(id)), ChatWindow::WhiteboardAccepted);
+		onWhiteboardSessionAccept();
 	}
 	else if (id.startsWith(ButtonWhiteboardSessionCancel)) {
-		QString fromJID = arg1;
-		eventStream_->send(boost::make_shared<CancelWhiteboardSessionUIEvent>(Q2PSTRING(fromJID)));
+		QString id = arg1;
+		messageLog_->setWhiteboardSessionStatus(QString::fromStdString(Q2PSTRING(id)), ChatWindow::WhiteboardCanceled);
+		onWhiteboardSessionCancel();
+	}
+	else if (id.startsWith(ButtonWhiteboardShowWindow)) {
+		QString id = arg1;
+		onWhiteboardWindowShow();
 	}
 	else if (id.startsWith(ButtonMUCInvite)) {
 		QString roomJID = arg1;
diff --git a/Swift/QtUI/QtChatWindow.h b/Swift/QtUI/QtChatWindow.h
index bf30078..a70f280 100644
--- a/Swift/QtUI/QtChatWindow.h
+++ b/Swift/QtUI/QtChatWindow.h
@@ -41,6 +41,7 @@ namespace Swift {
 		public:
 			static const QString ButtonWhiteboardSessionCancel;
 			static const QString ButtonWhiteboardSessionAcceptRequest;
+			static const QString ButtonWhiteboardShowWindow;
 			static const QString ButtonFileTransferCancel;
 			static const QString ButtonFileTransferSetDescription;
 			static const QString ButtonFileTransferSendRequest;
@@ -62,7 +63,8 @@ namespace Swift {
 			void setFileTransferProgress(std::string id, const int percentageDone);
 			void setFileTransferStatus(std::string id, const FileTransferState state, const std::string& msg);
 			
-			void addWhiteboardRequest(const JID& from);
+			std::string addWhiteboardRequest(const JID& from, bool senderIsSelf);
+			void setWhiteboardSessionStatus(std::string id, const ChatWindow::WhiteboardSessionState state);
 
 			void show();
 			void activate();
diff --git a/Swift/QtUI/Whiteboard/QtWhiteboardWindow.cpp b/Swift/QtUI/Whiteboard/QtWhiteboardWindow.cpp
index 3527eba..3ea09ef 100644
--- a/Swift/QtUI/Whiteboard/QtWhiteboardWindow.cpp
+++ b/Swift/QtUI/Whiteboard/QtWhiteboardWindow.cpp
@@ -236,6 +236,10 @@ namespace Swift {
 		whiteboardSession_->onSessionTerminateReceived.connect(boost::bind(&QtWhiteboardWindow::handleSessionTerminate, this));
 	}
 
+	void QtWhiteboardWindow::activateWindow() {
+		QWidget::activateWindow();
+	}
+
 	void QtWhiteboardWindow::handleLastItemChanged(QGraphicsItem* item) {
 		std::string serialized;
 		QGraphicsLineItem* lineItem = qgraphicsitem_cast<QGraphicsLineItem*>(item);
@@ -274,10 +278,6 @@ namespace Swift {
 	}
 
 	void QtWhiteboardWindow::handleSessionTerminate() {
-		QMessageBox box(this);
-		box.setText(tr("Session was terminated by other user"));
-		box.setIcon(QMessageBox::Information);
-		box.exec();
 		hide();
 	}
 
diff --git a/Swift/QtUI/Whiteboard/QtWhiteboardWindow.h b/Swift/QtUI/Whiteboard/QtWhiteboardWindow.h
index 4c0a065..5db19e9 100644
--- a/Swift/QtUI/Whiteboard/QtWhiteboardWindow.h
+++ b/Swift/QtUI/Whiteboard/QtWhiteboardWindow.h
@@ -34,6 +34,7 @@ namespace Swift {
 		void addItem(const std::string& item);
 		void show();
 		void setSession(WhiteboardSession::ref session);
+		void activateWindow();
 
 	private slots:
 		void changeLineWidth(int i);
diff --git a/Swiften/Whiteboard/WhiteboardSessionManager.cpp b/Swiften/Whiteboard/WhiteboardSessionManager.cpp
index eae9e5b..eff0aae 100644
--- a/Swiften/Whiteboard/WhiteboardSessionManager.cpp
+++ b/Swiften/Whiteboard/WhiteboardSessionManager.cpp
@@ -38,7 +38,8 @@ namespace Swift {
 		OutgoingWhiteboardSession::ref session = boost::make_shared<OutgoingWhiteboardSession>(fullJID, router_);
 		sessions_[to.toBare()] = session;
 		session->onSessionTerminateReceived.connect(boost::bind(&WhiteboardSessionManager::handleSessionTerminate, this, _1));
-		session->onSessionCancelled.connect(boost::bind(&WhiteboardSessionManager::handleSessionCancelled, this, _1));
+		session->onSessionCancelled.connect(boost::bind(&WhiteboardSessionManager::handleSessionCancel, this, _1));
+		session->onRequestAccepted.connect(boost::bind(&WhiteboardSessionManager::handleSessionAccept, this, _1));
 		return session;
 	}
 
@@ -47,6 +48,7 @@ namespace Swift {
 		if (!session) {
 			OutgoingWhiteboardSession::ref outgoingSession = createOutgoingSession(to);
 			outgoingSession->startSession();
+			onSessionRequest(to, true);
 			return outgoingSession;
 		} else {
 			return session;
@@ -56,8 +58,9 @@ namespace Swift {
 	void WhiteboardSessionManager::handleIncomingSession(IncomingWhiteboardSession::ref session) {
 		sessions_[session->getTo().toBare()] = session;
 		session->onSessionTerminateReceived.connect(boost::bind(&WhiteboardSessionManager::handleSessionTerminate, this, _1));
-		session->onSessionCancelled.connect(boost::bind(&WhiteboardSessionManager::handleSessionCancelled, this, _1));
-		onRequestReceived(session->getTo());
+		session->onSessionCancelled.connect(boost::bind(&WhiteboardSessionManager::handleSessionCancel, this, _1));
+		session->onRequestAccepted.connect(boost::bind(&WhiteboardSessionManager::handleSessionAccept, this, _1));
+		onSessionRequest(session->getTo(), false);
 	}
 
 	JID WhiteboardSessionManager::getFullJID(const JID& bareJID) {
@@ -67,9 +70,15 @@ namespace Swift {
 
 	void WhiteboardSessionManager::handleSessionTerminate(const JID& contact) {
 		sessions_.erase(contact.toBare());
+		onSessionTerminate(contact);
 	}
 
-	void WhiteboardSessionManager::handleSessionCancelled(const JID& contact) {
+	void WhiteboardSessionManager::handleSessionCancel(const JID& contact) {
 		sessions_.erase(contact.toBare());
+		onSessionTerminate(contact);
+	}
+
+	void WhiteboardSessionManager::handleSessionAccept(const JID& contact) {
+		onRequestAccepted(contact);
 	}
 }
diff --git a/Swiften/Whiteboard/WhiteboardSessionManager.h b/Swiften/Whiteboard/WhiteboardSessionManager.h
index d2a59e0..10f27d5 100644
--- a/Swiften/Whiteboard/WhiteboardSessionManager.h
+++ b/Swiften/Whiteboard/WhiteboardSessionManager.h
@@ -29,14 +29,17 @@ namespace Swift {
 		WhiteboardSession::ref requestSession(const JID& to);
 
 	public:
-		boost::signal< void (const JID&)> onRequestReceived;
+		boost::signal< void (const JID&, bool senderIsSelf)> onSessionRequest;
+		boost::signal< void (const JID&)> onSessionTerminate;
+		boost::signal< void (const JID&)> onRequestAccepted;
 
 	private:
 		JID getFullJID(const JID& bareJID);
 		OutgoingWhiteboardSession::ref createOutgoingSession(const JID& to);
 		void handleIncomingSession(IncomingWhiteboardSession::ref session);
 		void handleSessionTerminate(const JID& contact);
-		void handleSessionCancelled(const JID& contact);
+		void handleSessionCancel(const JID& contact);
+		void handleSessionAccept(const JID& contact);
 
 	private:
 		std::map<JID, boost::shared_ptr<WhiteboardSession> > sessions_;
-- 
cgit v0.10.2-6-g49f6