diff options
author | Mateusz Piekos <mateuszpiekos@gmail.com> | 2012-05-30 12:40:27 (GMT) |
---|---|---|
committer | Remko Tronçon <git@el-tramo.be> | 2012-09-08 16:14:27 (GMT) |
commit | fe8a8aa031da734f3112184420b372021d9e10c7 (patch) | |
tree | 9f8e0b7d11d7612eb25a8682cf940fa647ca67f2 /Swift/Controllers | |
parent | 0174723efbc1f612433d45c6916a2ad4596b96ba (diff) | |
download | swift-fe8a8aa031da734f3112184420b372021d9e10c7.zip swift-fe8a8aa031da734f3112184420b372021d9e10c7.tar.bz2 |
Support whiteboarding.
License: This patch is BSD-licensed, see http://www.opensource.org/licenses/bsd-license.php
Diffstat (limited to 'Swift/Controllers')
23 files changed, 453 insertions, 9 deletions
diff --git a/Swift/Controllers/Chat/ChatController.cpp b/Swift/Controllers/Chat/ChatController.cpp index f40f704..16b22fe 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,6 +261,14 @@ void ChatController::handleNewFileTransferController(FileTransferController* ftc ftControllers[ftID] = ftc; } +void ChatController::handleWhiteboardSessionRequest(bool senderIsSelf) { + lastWbID_ = chatWindow_->addWhiteboardRequest(senderIsSelf); +} + +void ChatController::handleWhiteboardStateChange(const ChatWindow::WhiteboardSessionState state) { + chatWindow_->setWhiteboardSessionStatus(lastWbID_, state); +} + void ChatController::handleFileTransferCancel(std::string id) { SWIFT_LOG(debug) << "handleFileTransferCancel(" << id << ")" << std::endl; if (ftControllers.find(id) != ftControllers.end()) { @@ -287,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 a873ae9..66ec37d 100644 --- a/Swift/Controllers/Chat/ChatController.h +++ b/Swift/Controllers/Chat/ChatController.h @@ -30,6 +30,8 @@ namespace Swift { virtual void setToJID(const JID& jid); virtual void setOnline(bool online); virtual void handleNewFileTransferController(FileTransferController* ftc); + virtual void handleWhiteboardSessionRequest(bool senderIsSelf); + virtual void handleWhiteboardStateChange(const ChatWindow::WhiteboardSessionState state); virtual void setContactIsReceivingPresence(bool /*isReceivingPresence*/); protected: @@ -57,6 +59,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(); @@ -78,6 +84,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 6b51df6..1e0e9c2 100644 --- a/Swift/Controllers/Chat/ChatsManager.cpp +++ b/Swift/Controllers/Chat/ChatsManager.cpp @@ -42,6 +42,7 @@ #include <Swift/Controllers/Settings/SettingsProvider.h> #include <Swift/Controllers/SettingConstants.h> #include <Swiften/Client/StanzaChannel.h> +#include <Swift/Controllers/WhiteboardManager.h> namespace Swift { @@ -72,7 +73,8 @@ ChatsManager::ChatsManager( XMPPRoster* roster, bool eagleMode, SettingsProvider* settings, - HistoryController* historyController) : + HistoryController* historyController, + WhiteboardManager* whiteboardManager) : jid_(jid), joinMUCWindowFactory_(joinMUCWindowFactory), useDelayForLatency_(useDelayForLatency), @@ -83,7 +85,8 @@ ChatsManager::ChatsManager( roster_(roster), eagleMode_(eagleMode), settings_(settings), - historyController_(historyController) { + historyController_(historyController), + whiteboardManager_(whiteboardManager) { timerFactory_ = timerFactory; eventController_ = eventController; stanzaChannel_ = stanzaChannel; @@ -109,6 +112,10 @@ 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)); + whiteboardManager_->onSessionRequest.connect(boost::bind(&ChatsManager::handleWhiteboardSessionRequest, this, _1, _2)); + whiteboardManager_->onRequestAccepted.connect(boost::bind(&ChatsManager::handleWhiteboardStateChange, this, _1, ChatWindow::WhiteboardAccepted)); + whiteboardManager_->onSessionTerminate.connect(boost::bind(&ChatsManager::handleWhiteboardStateChange, this, _1, ChatWindow::WhiteboardTerminated)); + whiteboardManager_->onRequestRejected.connect(boost::bind(&ChatsManager::handleWhiteboardStateChange, this, _1, ChatWindow::WhiteboardRejected)); 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)); @@ -657,6 +664,29 @@ void ChatsManager::handleNewFileTransferController(FileTransferController* ftc) chatController->activateChatWindow(); } +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(); + if (state == ChatWindow::WhiteboardAccepted) { + boost::filesystem::path path; + JID bareJID = contact.toBare(); + if (avatarManager_) { + path = avatarManager_->getAvatarPath(bareJID); + } + ChatListWindow::Chat chat(bareJID, nickResolver_->jidToNick(bareJID), "", 0, StatusShow::None, path, false); + chatListWindow_->addWhiteboardSession(chat); + } else { + chatListWindow_->removeWhiteboardSession(contact.toBare()); + } +} + void ChatsManager::handleRecentActivated(const ChatListWindow::Chat& chat) { if (chat.isMUC) { /* FIXME: This means that recents requiring passwords will just flat-out not work */ diff --git a/Swift/Controllers/Chat/ChatsManager.h b/Swift/Controllers/Chat/ChatsManager.h index 94efde1..5b8b785 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 { @@ -47,11 +48,12 @@ namespace Swift { class FileTransferController; class XMPPRoster; class SettingsProvider; + class WhiteboardManager; class HistoryController; class ChatsManager { public: - ChatsManager(JID jid, StanzaChannel* stanzaChannel, IQRouter* iqRouter, EventController* eventController, ChatWindowFactory* chatWindowFactory, JoinMUCWindowFactory* joinMUCWindowFactory, NickResolver* nickResolver, PresenceOracle* presenceOracle, PresenceSender* presenceSender, UIEventStream* uiEventStream, ChatListWindowFactory* chatListWindowFactory, bool useDelayForLatency, TimerFactory* timerFactory, MUCRegistry* mucRegistry, EntityCapsProvider* entityCapsProvider, MUCManager* mucManager, MUCSearchWindowFactory* mucSearchWindowFactory, ProfileSettingsProvider* profileSettings, FileTransferOverview* ftOverview, XMPPRoster* roster, bool eagleMode, SettingsProvider* settings, HistoryController* historyController_); + ChatsManager(JID jid, StanzaChannel* stanzaChannel, IQRouter* iqRouter, EventController* eventController, ChatWindowFactory* chatWindowFactory, JoinMUCWindowFactory* joinMUCWindowFactory, NickResolver* nickResolver, PresenceOracle* presenceOracle, PresenceSender* presenceSender, UIEventStream* uiEventStream, ChatListWindowFactory* chatListWindowFactory, bool useDelayForLatency, TimerFactory* timerFactory, MUCRegistry* mucRegistry, EntityCapsProvider* entityCapsProvider, MUCManager* mucManager, MUCSearchWindowFactory* mucSearchWindowFactory, ProfileSettingsProvider* profileSettings, FileTransferOverview* ftOverview, XMPPRoster* roster, bool eagleMode, SettingsProvider* settings, HistoryController* historyController_, WhiteboardManager* whiteboardManager); virtual ~ChatsManager(); void setAvatarManager(AvatarManager* avatarManager); void setOnline(bool enabled); @@ -73,6 +75,8 @@ namespace Swift { void handleBookmarksReady(); void handleChatActivity(const JID& jid, const std::string& activity, bool isMUC); void handleNewFileTransferController(FileTransferController*); + 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(); @@ -131,5 +135,6 @@ namespace Swift { bool userWantsReceipts_; SettingsProvider* settings_; HistoryController* historyController_; + WhiteboardManager* whiteboardManager_; }; } diff --git a/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp b/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp index 294dcb8..482b19c 100644 --- a/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp +++ b/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp @@ -17,6 +17,7 @@ #include "Swift/Controllers/Settings/DummySettingsProvider.h" #include "Swift/Controllers/UIInterfaces/ChatWindowFactory.h" #include "Swift/Controllers/UIInterfaces/ChatListWindowFactory.h" +#include "Swift/Controllers/UIInterfaces/WhiteboardWindowFactory.h" #include "Swift/Controllers/UIInterfaces/JoinMUCWindowFactory.h" #include "Swift/Controllers/UIInterfaces/MUCSearchWindowFactory.h" #include "Swiften/Client/Client.h" @@ -49,6 +50,8 @@ #include "Swiften/Elements/DeliveryReceipt.h" #include <Swiften/Base/Algorithm.h> #include <Swift/Controllers/SettingConstants.h> +#include <Swift/Controllers/WhiteboardManager.h> +#include <Swiften/Whiteboard/WhiteboardSessionManager.h> using namespace Swift; @@ -100,11 +103,13 @@ public: chatListWindow_ = new MockChatListWindow(); ftManager_ = new DummyFileTransferManager(); ftOverview_ = new FileTransferOverview(ftManager_); + avatarManager_ = new NullAvatarManager(); + wbSessionManager_ = new WhiteboardSessionManager(iqRouter_, stanzaChannel_, presenceOracle_, entityCapsManager_); + wbManager_ = new WhiteboardManager(whiteboardWindowFactory_, uiEventStream_, nickResolver_, wbSessionManager_); mocks_->ExpectCall(chatListWindowFactory_, ChatListWindowFactory::createChatListWindow).With(uiEventStream_).Return(chatListWindow_); - manager_ = new ChatsManager(jid_, stanzaChannel_, iqRouter_, eventController_, chatWindowFactory_, joinMUCWindowFactory_, nickResolver_, presenceOracle_, directedPresenceSender_, uiEventStream_, chatListWindowFactory_, true, NULL, mucRegistry_, entityCapsManager_, mucManager_, mucSearchWindowFactory_, profileSettings_, ftOverview_, xmppRoster_, false, settings_, NULL); + manager_ = new ChatsManager(jid_, stanzaChannel_, iqRouter_, eventController_, chatWindowFactory_, joinMUCWindowFactory_, nickResolver_, presenceOracle_, directedPresenceSender_, uiEventStream_, chatListWindowFactory_, true, NULL, mucRegistry_, entityCapsManager_, mucManager_, mucSearchWindowFactory_, profileSettings_, ftOverview_, xmppRoster_, false, settings_, NULL, wbManager_); - avatarManager_ = new NullAvatarManager(); manager_->setAvatarManager(avatarManager_); }; @@ -115,6 +120,8 @@ public: delete manager_; delete ftOverview_; delete ftManager_; + delete wbSessionManager_; + delete wbManager_; delete directedPresenceSender_; delete presenceSender_; delete presenceOracle_; @@ -460,6 +467,7 @@ private: MockRepository* mocks_; UIEventStream* uiEventStream_; ChatListWindowFactory* chatListWindowFactory_; + WhiteboardWindowFactory* whiteboardWindowFactory_; MUCSearchWindowFactory* mucSearchWindowFactory_; MUCRegistry* mucRegistry_; DirectedPresenceSender* directedPresenceSender_; @@ -471,6 +479,8 @@ private: ChatListWindow* chatListWindow_; FileTransferOverview* ftOverview_; FileTransferManager* ftManager_; + WhiteboardSessionManager* wbSessionManager_; + WhiteboardManager* wbManager_; }; CPPUNIT_TEST_SUITE_REGISTRATION(ChatsManagerTest); diff --git a/Swift/Controllers/Chat/UnitTest/MockChatListWindow.h b/Swift/Controllers/Chat/UnitTest/MockChatListWindow.h index 6ac8d4a..5bbd490 100644 --- a/Swift/Controllers/Chat/UnitTest/MockChatListWindow.h +++ b/Swift/Controllers/Chat/UnitTest/MockChatListWindow.h @@ -16,6 +16,8 @@ namespace Swift { virtual ~MockChatListWindow() {}; void addMUCBookmark(const MUCBookmark& /*bookmark*/) {} void removeMUCBookmark(const MUCBookmark& /*bookmark*/) {} + void addWhiteboardSession(const ChatListWindow::Chat& /*chat*/) {}; + void removeWhiteboardSession(const JID& /*jid*/) {}; void setBookmarksEnabled(bool /*enabled*/) {} void setRecents(const std::list<ChatListWindow::Chat>& /*recents*/) {} void setUnreadCount(int /*unread*/) {} diff --git a/Swift/Controllers/MainController.cpp b/Swift/Controllers/MainController.cpp index f3a0226..c2a7b33 100644 --- a/Swift/Controllers/MainController.cpp +++ b/Swift/Controllers/MainController.cpp @@ -46,6 +46,7 @@ #include "Swift/Controllers/PresenceNotifier.h" #include "Swift/Controllers/EventNotifier.h" #include "Swift/Controllers/Storages/StoragesFactory.h" +#include "Swift/Controllers/WhiteboardManager.h" #include "SwifTools/Dock/Dock.h" #include "SwifTools/Notifier/TogglableNotifier.h" #include "Swiften/Base/foreach.h" @@ -254,6 +255,8 @@ void MainController::resetClient() { userSearchControllerAdd_ = NULL; delete adHocManager_; adHocManager_ = NULL; + delete whiteboardManager_; + whiteboardManager_ = NULL; clientInitialized_ = false; } @@ -303,6 +306,7 @@ void MainController::handleConnected() { rosterController_->getWindow()->onShowCertificateRequest.connect(boost::bind(&MainController::handleShowCertificateRequest, this)); contactEditController_ = new ContactEditController(rosterController_, client_->getVCardManager(), uiFactory_, uiEventStream_); + whiteboardManager_ = new WhiteboardManager(uiFactory_, uiEventStream_, client_->getNickResolver(), client_->getWhiteboardSessionManager()); /* Doing this early as an ordering fix. Various things later will * want to have the user's nick available and this means it will @@ -312,9 +316,9 @@ void MainController::handleConnected() { #ifdef SWIFT_EXPERIMENTAL_HISTORY historyController_ = new HistoryController(storages_->getHistoryStorage()); historyViewController_ = new HistoryViewController(jid_, uiEventStream_, historyController_, client_->getNickResolver(), client_->getAvatarManager(), client_->getPresenceOracle(), uiFactory_); - chatsManager_ = new ChatsManager(jid_, client_->getStanzaChannel(), client_->getIQRouter(), eventController_, uiFactory_, uiFactory_, client_->getNickResolver(), client_->getPresenceOracle(), client_->getPresenceSender(), uiEventStream_, uiFactory_, useDelayForLatency_, networkFactories_->getTimerFactory(), client_->getMUCRegistry(), client_->getEntityCapsProvider(), client_->getMUCManager(), uiFactory_, profileSettings_, ftOverview_, client_->getRoster(), !settings_->getSetting(SettingConstants::REMEMBER_RECENT_CHATS), settings_, historyController_); + chatsManager_ = new ChatsManager(jid_, client_->getStanzaChannel(), client_->getIQRouter(), eventController_, uiFactory_, uiFactory_, client_->getNickResolver(), client_->getPresenceOracle(), client_->getPresenceSender(), uiEventStream_, uiFactory_, useDelayForLatency_, networkFactories_->getTimerFactory(), client_->getMUCRegistry(), client_->getEntityCapsProvider(), client_->getMUCManager(), uiFactory_, profileSettings_, ftOverview_, client_->getRoster(), !settings_->getSetting(SettingConstants::REMEMBER_RECENT_CHATS), settings_, historyController_, whiteboardManager_); #else - chatsManager_ = new ChatsManager(jid_, client_->getStanzaChannel(), client_->getIQRouter(), eventController_, uiFactory_, uiFactory_, client_->getNickResolver(), client_->getPresenceOracle(), client_->getPresenceSender(), uiEventStream_, uiFactory_, useDelayForLatency_, networkFactories_->getTimerFactory(), client_->getMUCRegistry(), client_->getEntityCapsProvider(), client_->getMUCManager(), uiFactory_, profileSettings_, ftOverview_, client_->getRoster(), !settings_->getSetting(SettingConstants::REMEMBER_RECENT_CHATS), settings_, NULL); + chatsManager_ = new ChatsManager(jid_, client_->getStanzaChannel(), client_->getIQRouter(), eventController_, uiFactory_, uiFactory_, client_->getNickResolver(), client_->getPresenceOracle(), client_->getPresenceSender(), uiEventStream_, uiFactory_, useDelayForLatency_, networkFactories_->getTimerFactory(), client_->getMUCRegistry(), client_->getEntityCapsProvider(), client_->getMUCManager(), uiFactory_, profileSettings_, ftOverview_, client_->getRoster(), !settings_->getSetting(SettingConstants::REMEMBER_RECENT_CHATS), settings_, NULL, whiteboardManager_); #endif client_->onMessageReceived.connect(boost::bind(&ChatsManager::handleIncomingMessage, chatsManager_, _1)); @@ -335,6 +339,9 @@ void MainController::handleConnected() { discoInfo.addFeature(DiscoInfo::JingleTransportsIBBFeature); discoInfo.addFeature(DiscoInfo::JingleTransportsS5BFeature); #endif +#ifdef SWIFT_EXPERIMENTAL_WB + discoInfo.addFeature(DiscoInfo::WhiteboardFeature); +#endif discoInfo.addFeature(DiscoInfo::MessageDeliveryReceiptsFeature); client_->getDiscoManager()->setCapsNode(CLIENT_NODE); client_->getDiscoManager()->setDiscoInfo(discoInfo); @@ -342,6 +349,7 @@ void MainController::handleConnected() { userSearchControllerChat_ = new UserSearchController(UserSearchController::StartChat, jid_, uiEventStream_, client_->getVCardManager(), uiFactory_, client_->getIQRouter(), rosterController_); userSearchControllerAdd_ = new UserSearchController(UserSearchController::AddContact, jid_, uiEventStream_, client_->getVCardManager(), uiFactory_, client_->getIQRouter(), rosterController_); adHocManager_ = new AdHocManager(JID(boundJID_.getDomain()), uiFactory_, client_->getIQRouter(), uiEventStream_, rosterController_->getWindow()); + } loginWindow_->setIsLoggingIn(false); diff --git a/Swift/Controllers/MainController.h b/Swift/Controllers/MainController.h index 6f7482e..2e5bd05 100644 --- a/Swift/Controllers/MainController.h +++ b/Swift/Controllers/MainController.h @@ -70,6 +70,7 @@ namespace Swift { class AdHocManager; class AdHocCommandWindowFactory; class FileTransferOverview; + class WhiteboardManager; class MainController { public: @@ -174,5 +175,6 @@ namespace Swift { bool offlineRequested_; static const int SecondsToWaitBeforeForceQuitting; FileTransferOverview* ftOverview_; + WhiteboardManager* whiteboardManager_; }; } diff --git a/Swift/Controllers/Roster/ContactRosterItem.h b/Swift/Controllers/Roster/ContactRosterItem.h index 9932dc4..8389a44 100644 --- a/Swift/Controllers/Roster/ContactRosterItem.h +++ b/Swift/Controllers/Roster/ContactRosterItem.h @@ -25,6 +25,7 @@ class ContactRosterItem : public RosterItem { public: enum Feature { FileTransferFeature, + WhiteboardFeature, }; public: diff --git a/Swift/Controllers/Roster/RosterController.cpp b/Swift/Controllers/Roster/RosterController.cpp index 170bfd0..ec52993 100644 --- a/Swift/Controllers/Roster/RosterController.cpp +++ b/Swift/Controllers/Roster/RosterController.cpp @@ -321,6 +321,9 @@ void RosterController::handleOnCapsChanged(const JID& jid) { if (info->hasFeature(DiscoInfo::JingleFeature) && info->hasFeature(DiscoInfo::JingleFTFeature) && info->hasFeature(DiscoInfo::JingleTransportsIBBFeature)) { features.insert(ContactRosterItem::FileTransferFeature); } + if (info->hasFeature(DiscoInfo::WhiteboardFeature)) { + features.insert(ContactRosterItem::WhiteboardFeature); + } roster_->setAvailableFeatures(jid, features); } } diff --git a/Swift/Controllers/SConscript b/Swift/Controllers/SConscript index b6f81b3..7cd017b 100644 --- a/Swift/Controllers/SConscript +++ b/Swift/Controllers/SConscript @@ -73,7 +73,8 @@ if env["SCONS_STAGE"] == "build" : "Translator.cpp", "XMPPURIController.cpp", "ChatMessageSummarizer.cpp", - "SettingConstants.cpp" + "SettingConstants.cpp", + "WhiteboardManager.cpp" ]) env.Append(UNITTEST_SOURCES = [ diff --git a/Swift/Controllers/UIEvents/AcceptWhiteboardSessionUIEvent.h b/Swift/Controllers/UIEvents/AcceptWhiteboardSessionUIEvent.h new file mode 100644 index 0000000..93cad03 --- /dev/null +++ b/Swift/Controllers/UIEvents/AcceptWhiteboardSessionUIEvent.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2012 Mateusz Piękos + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> + +#include <Swiften/JID/JID.h> + +#include <Swift/Controllers/UIEvents/UIEvent.h> + +namespace Swift { + class AcceptWhiteboardSessionUIEvent : public UIEvent { + typedef boost::shared_ptr<AcceptWhiteboardSessionUIEvent> ref; + public: + AcceptWhiteboardSessionUIEvent(const JID& jid) : jid_(jid) {} + const JID& getContact() const {return jid_;} + private: + JID jid_; + }; +} diff --git a/Swift/Controllers/UIEvents/CancelWhiteboardSessionUIEvent.h b/Swift/Controllers/UIEvents/CancelWhiteboardSessionUIEvent.h new file mode 100644 index 0000000..f5c3b0e --- /dev/null +++ b/Swift/Controllers/UIEvents/CancelWhiteboardSessionUIEvent.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2012 Mateusz Piękos + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> + +#include <Swiften/JID/JID.h> + +#include <Swift/Controllers/UIEvents/UIEvent.h> + +namespace Swift { + class CancelWhiteboardSessionUIEvent : public UIEvent { + typedef boost::shared_ptr<CancelWhiteboardSessionUIEvent> ref; + public: + CancelWhiteboardSessionUIEvent(const JID& jid) : jid_(jid) {} + const JID& getContact() const {return jid_;} + private: + JID jid_; + }; +} diff --git a/Swift/Controllers/UIEvents/RequestWhiteboardUIEvent.h b/Swift/Controllers/UIEvents/RequestWhiteboardUIEvent.h new file mode 100644 index 0000000..f5b995b --- /dev/null +++ b/Swift/Controllers/UIEvents/RequestWhiteboardUIEvent.h @@ -0,0 +1,21 @@ +/* + * 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 RequestWhiteboardUIEvent : public UIEvent { + public: + RequestWhiteboardUIEvent(const JID& contact) : contact_(contact) {}; + const JID& getContact() const {return contact_;} + private: + JID contact_; + }; +} 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/ChatListWindow.h b/Swift/Controllers/UIInterfaces/ChatListWindow.h index d047f8c..cb55bb3 100644 --- a/Swift/Controllers/UIInterfaces/ChatListWindow.h +++ b/Swift/Controllers/UIInterfaces/ChatListWindow.h @@ -48,6 +48,8 @@ namespace Swift { virtual void setBookmarksEnabled(bool enabled) = 0; virtual void addMUCBookmark(const MUCBookmark& bookmark) = 0; + virtual void addWhiteboardSession(const ChatListWindow::Chat& chat) = 0; + virtual void removeWhiteboardSession(const JID& jid) = 0; virtual void removeMUCBookmark(const MUCBookmark& bookmark) = 0; virtual void setRecents(const std::list<Chat>& recents) = 0; virtual void setUnreadCount(int unread) = 0; @@ -55,6 +57,7 @@ namespace Swift { boost::signal<void (const MUCBookmark&)> onMUCBookmarkActivated; boost::signal<void (const Chat&)> onRecentActivated; + boost::signal<void (const JID&)> onWhiteboardActivated; boost::signal<void ()> onClearRecentsRequested; }; } diff --git a/Swift/Controllers/UIInterfaces/ChatWindow.h b/Swift/Controllers/UIInterfaces/ChatWindow.h index 9188c7f..5db1a54 100644 --- a/Swift/Controllers/UIInterfaces/ChatWindow.h +++ b/Swift/Controllers/UIInterfaces/ChatWindow.h @@ -37,6 +37,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, WhiteboardTerminated, WhiteboardRejected}; ChatWindow() {} virtual ~ChatWindow() {}; @@ -60,6 +61,9 @@ 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 std::string addWhiteboardRequest(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; @@ -132,6 +136,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/UIFactory.h b/Swift/Controllers/UIInterfaces/UIFactory.h index d6bea77..6b4efd8 100644 --- a/Swift/Controllers/UIInterfaces/UIFactory.h +++ b/Swift/Controllers/UIInterfaces/UIFactory.h @@ -20,6 +20,7 @@ #include <Swift/Controllers/UIInterfaces/ContactEditWindowFactory.h> #include <Swift/Controllers/UIInterfaces/AdHocCommandWindowFactory.h> #include <Swift/Controllers/UIInterfaces/FileTransferListWidgetFactory.h> +#include <Swift/Controllers/UIInterfaces/WhiteboardWindowFactory.h> namespace Swift { class UIFactory : @@ -36,7 +37,8 @@ namespace Swift { public ProfileWindowFactory, public ContactEditWindowFactory, public AdHocCommandWindowFactory, - public FileTransferListWidgetFactory { + public FileTransferListWidgetFactory, + public WhiteboardWindowFactory { public: virtual ~UIFactory() {} }; diff --git a/Swift/Controllers/UIInterfaces/WhiteboardWindow.h b/Swift/Controllers/UIInterfaces/WhiteboardWindow.h new file mode 100644 index 0000000..a4a9ef0 --- /dev/null +++ b/Swift/Controllers/UIInterfaces/WhiteboardWindow.h @@ -0,0 +1,26 @@ +/* + * 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/Base/boost_bsignals.h" + +#include <string> + +namespace Swift { + class WhiteboardSession; + class WhiteboardElement; + + class WhiteboardWindow { + public: + virtual ~WhiteboardWindow() {} + + virtual void show() = 0; + virtual void setSession(boost::shared_ptr<WhiteboardSession> session) = 0; + virtual void activateWindow() = 0; + virtual void setName(const std::string& name) = 0; + }; +} diff --git a/Swift/Controllers/UIInterfaces/WhiteboardWindowFactory.h b/Swift/Controllers/UIInterfaces/WhiteboardWindowFactory.h new file mode 100644 index 0000000..c2d2f6c --- /dev/null +++ b/Swift/Controllers/UIInterfaces/WhiteboardWindowFactory.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2012 Mateusz Piękos + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +namespace Swift { + class WhiteboardSession; + class WhiteboardWindow; + + class WhiteboardWindowFactory { + public : + virtual ~WhiteboardWindowFactory() {}; + + virtual WhiteboardWindow* createWhiteboardWindow(boost::shared_ptr<WhiteboardSession> whiteboardSession) = 0; + }; +} diff --git a/Swift/Controllers/UnitTest/MockChatWindow.h b/Swift/Controllers/UnitTest/MockChatWindow.h index dbfef3e..998a4eb 100644 --- a/Swift/Controllers/UnitTest/MockChatWindow.h +++ b/Swift/Controllers/UnitTest/MockChatWindow.h @@ -52,6 +52,10 @@ namespace Swift { void setSubject(const std::string& /*subject*/) {} virtual void showRoomConfigurationForm(Form::ref) {} virtual void addMUCInvitation(const std::string& /*senderName*/, const JID& /*jid*/, const std::string& /*reason*/, const std::string& /*password*/, bool = true) {}; + + virtual std::string addWhiteboardRequest(bool) {return "";}; + virtual void setWhiteboardSessionStatus(std::string, const ChatWindow::WhiteboardSessionState){}; + virtual void setAffiliations(MUCOccupant::Affiliation, const std::vector<JID>&) {} virtual void setAvailableRoomActions(const std::vector<RoomAction> &) {}; virtual InviteToChatWindow* createInviteToChatWindow() {return NULL;} diff --git a/Swift/Controllers/WhiteboardManager.cpp b/Swift/Controllers/WhiteboardManager.cpp new file mode 100644 index 0000000..50aba6f --- /dev/null +++ b/Swift/Controllers/WhiteboardManager.cpp @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2012 Mateusz Piękos + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <Swift/Controllers/WhiteboardManager.h> + +#include <boost/bind.hpp> + +#include <Swiften/Base/foreach.h> +#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/NickResolver.h" +#include <Swiften/Client/StanzaChannel.h> +#include <Swiften/Whiteboard/WhiteboardSessionManager.h> + +namespace Swift { + typedef std::pair<JID, WhiteboardWindow*> JIDWhiteboardWindowPair; + + WhiteboardManager::WhiteboardManager(WhiteboardWindowFactory* whiteboardWindowFactory, UIEventStream* uiEventStream, NickResolver* nickResolver, WhiteboardSessionManager* whiteboardSessionManager) : whiteboardWindowFactory_(whiteboardWindowFactory), uiEventStream_(uiEventStream), nickResolver_(nickResolver), whiteboardSessionManager_(whiteboardSessionManager) { + +#ifdef SWIFT_EXPERIMENTAL_WB + whiteboardSessionManager_->onSessionRequest.connect(boost::bind(&WhiteboardManager::handleIncomingSession, this, _1)); +#endif + uiEventConnection_ = uiEventStream_->onUIEvent.connect(boost::bind(&WhiteboardManager::handleUIEvent, this, _1)); + } + + WhiteboardManager::~WhiteboardManager() { + foreach (JIDWhiteboardWindowPair whiteboardWindowPair, whiteboardWindows_) { + delete whiteboardWindowPair.second; + } + } + + WhiteboardWindow* WhiteboardManager::createNewWhiteboardWindow(const JID& contact, WhiteboardSession::ref session) { + WhiteboardWindow *window = whiteboardWindowFactory_->createWhiteboardWindow(session); + window->setName(nickResolver_->jidToNick(contact)); + whiteboardWindows_[contact.toBare()] = window; + return window; + } + + WhiteboardWindow* WhiteboardManager::findWhiteboardWindow(const JID& contact) { + if (whiteboardWindows_.find(contact.toBare()) == whiteboardWindows_.end()) { + return NULL; + } + return whiteboardWindows_[contact.toBare()]; + } + + void WhiteboardManager::handleUIEvent(boost::shared_ptr<UIEvent> event) { + boost::shared_ptr<RequestWhiteboardUIEvent> requestWhiteboardEvent = boost::dynamic_pointer_cast<RequestWhiteboardUIEvent>(event); + if (requestWhiteboardEvent) { + requestSession(requestWhiteboardEvent->getContact()); + } + boost::shared_ptr<AcceptWhiteboardSessionUIEvent> sessionAcceptEvent = boost::dynamic_pointer_cast<AcceptWhiteboardSessionUIEvent>(event); + if (sessionAcceptEvent) { + acceptSession(sessionAcceptEvent->getContact()); + } + boost::shared_ptr<CancelWhiteboardSessionUIEvent> sessionCancelEvent = boost::dynamic_pointer_cast<CancelWhiteboardSessionUIEvent>(event); + 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) { + IncomingWhiteboardSession::ref session = boost::dynamic_pointer_cast<IncomingWhiteboardSession>(whiteboardSessionManager_->getSession(from)); + WhiteboardWindow* window = findWhiteboardWindow(from); + if (session && window) { + session->accept(); + window->show(); + } + } + + void WhiteboardManager::requestSession(const JID& contact) { + WhiteboardSession::ref session = whiteboardSessionManager_->requestSession(contact); + session->onSessionTerminated.connect(boost::bind(&WhiteboardManager::handleSessionTerminate, this, _1)); + session->onRequestAccepted.connect(boost::bind(&WhiteboardManager::handleSessionAccept, this, _1)); + session->onRequestRejected.connect(boost::bind(&WhiteboardManager::handleRequestReject, this, _1)); + + WhiteboardWindow* window = findWhiteboardWindow(contact); + if (window == NULL) { + createNewWhiteboardWindow(contact, session); + } else { + window->setSession(session); + } + onSessionRequest(session->getTo(), true); + } + + void WhiteboardManager::cancelSession(const JID& from) { + WhiteboardSession::ref session = whiteboardSessionManager_->getSession(from); + if (session) { + session->cancel(); + } + } + + void WhiteboardManager::handleIncomingSession(IncomingWhiteboardSession::ref session) { + session->onSessionTerminated.connect(boost::bind(&WhiteboardManager::handleSessionTerminate, this, _1)); + session->onRequestAccepted.connect(boost::bind(&WhiteboardManager::handleSessionAccept, this, _1)); + + WhiteboardWindow* window = findWhiteboardWindow(session->getTo()); + if (window == NULL) { + createNewWhiteboardWindow(session->getTo(), session); + } else { + window->setSession(session); + } + + onSessionRequest(session->getTo(), false); + } + + void WhiteboardManager::handleSessionTerminate(const JID& contact) { + onSessionTerminate(contact); + } + + void WhiteboardManager::handleSessionCancel(const JID& contact) { + onSessionTerminate(contact); + } + + void WhiteboardManager::handleSessionAccept(const JID& contact) { + WhiteboardWindow* window = findWhiteboardWindow(contact); + window->show(); + onRequestAccepted(contact); + } + + void WhiteboardManager::handleRequestReject(const JID& contact) { + onRequestRejected(contact); + } + +} diff --git a/Swift/Controllers/WhiteboardManager.h b/Swift/Controllers/WhiteboardManager.h new file mode 100644 index 0000000..2f5767b --- /dev/null +++ b/Swift/Controllers/WhiteboardManager.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2012 Mateusz Piękos + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + + +#pragma once + +#include <map> + +#include <boost/shared_ptr.hpp> + +#include <Swiften/JID/JID.h> + +#include <Swift/Controllers/UIEvents/UIEventStream.h> +#include <Swift/Controllers/UIInterfaces/WhiteboardWindowFactory.h> +#include <Swift/Controllers/UIInterfaces/WhiteboardWindow.h> +#include <Swiften/Whiteboard/WhiteboardSession.h> +#include <Swiften/Whiteboard/IncomingWhiteboardSession.h> + +namespace Swift { + class WhiteboardSessionManager; + class NickResolver; + + class WhiteboardManager { + public: + WhiteboardManager(WhiteboardWindowFactory* whiteboardWindowFactory, UIEventStream* uiEventStream, NickResolver* nickResolver, WhiteboardSessionManager* whiteboardSessionManager); + ~WhiteboardManager(); + + WhiteboardWindow* createNewWhiteboardWindow(const JID& contact, WhiteboardSession::ref session); + + public: + boost::signal< void (const JID&, bool senderIsSelf)> onSessionRequest; + boost::signal< void (const JID&)> onSessionTerminate; + boost::signal< void (const JID&)> onRequestAccepted; + boost::signal< void (const JID&)> onRequestRejected; + + private: + void handleUIEvent(boost::shared_ptr<UIEvent> event); + void handleSessionTerminate(const JID& contact); + void handleSessionCancel(const JID& contact); + void handleSessionAccept(const JID& contact); + void handleRequestReject(const JID& contact); + void handleIncomingSession(IncomingWhiteboardSession::ref session); + void acceptSession(const JID& from); + void requestSession(const JID& contact); + void cancelSession(const JID& from); + WhiteboardWindow* findWhiteboardWindow(const JID& contact); + + private: + std::map<JID, WhiteboardWindow*> whiteboardWindows_; + WhiteboardWindowFactory* whiteboardWindowFactory_; + UIEventStream* uiEventStream_; + NickResolver* nickResolver_; + boost::bsignals::scoped_connection uiEventConnection_; + WhiteboardSessionManager* whiteboardSessionManager_; + }; +} |