summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTobias Markmann <tm@ayena.de>2011-05-26 18:46:49 (GMT)
committerRemko Tronçon <git@el-tramo.be>2011-09-25 17:42:32 (GMT)
commit4f62e5ec4b42929fe3c1a68667e63cb1b7a35509 (patch)
tree0d19fac3f578dec00ccf3e58930312951e38de89 /Swift/Controllers
parentde660b763459cdd707876ec244b6866abca07fa2 (diff)
downloadswift-contrib-4f62e5ec4b42929fe3c1a68667e63cb1b7a35509.zip
swift-contrib-4f62e5ec4b42929fe3c1a68667e63cb1b7a35509.tar.bz2
Google Summer of Code 2011 Project: Adding support for Jingle File Transfers (XEP-0234), Jingle SOCKS5 Bytestreams Transport Method (XEP-0260), Jingle In-Band Bytestreams Transport Method (XEP-0261) and SOCKS5 Bytestreams (XEP-0065).
License: This patch is BSD-licensed, see http://www.opensource.org/licenses/bsd-license.php
Diffstat (limited to 'Swift/Controllers')
-rw-r--r--Swift/Controllers/Chat/ChatController.cpp50
-rw-r--r--Swift/Controllers/Chat/ChatController.h13
-rw-r--r--Swift/Controllers/Chat/ChatsManager.cpp15
-rw-r--r--Swift/Controllers/Chat/ChatsManager.h8
-rw-r--r--Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp17
-rw-r--r--Swift/Controllers/FileTransfer/FileTransferController.cpp147
-rw-r--r--Swift/Controllers/FileTransfer/FileTransferController.h72
-rw-r--r--Swift/Controllers/FileTransfer/FileTransferOverview.cpp41
-rw-r--r--Swift/Controllers/FileTransfer/FileTransferOverview.h38
-rw-r--r--Swift/Controllers/FileTransfer/FileTransferProgressInfo.cpp31
-rw-r--r--Swift/Controllers/FileTransfer/FileTransferProgressInfo.h29
-rw-r--r--Swift/Controllers/FileTransfer/SOCKS5BytestreamProxyFinder.cpp53
-rw-r--r--Swift/Controllers/FileTransfer/SOCKS5BytestreamProxyFinder.h38
-rw-r--r--Swift/Controllers/FileTransferListController.cpp45
-rw-r--r--Swift/Controllers/FileTransferListController.h35
-rw-r--r--Swift/Controllers/MainController.cpp32
-rw-r--r--Swift/Controllers/MainController.h7
-rw-r--r--Swift/Controllers/Roster/ContactRosterItem.cpp8
-rw-r--r--Swift/Controllers/Roster/ContactRosterItem.h10
-rw-r--r--Swift/Controllers/Roster/Roster.cpp10
-rw-r--r--Swift/Controllers/Roster/Roster.h3
-rw-r--r--Swift/Controllers/Roster/RosterController.cpp32
-rw-r--r--Swift/Controllers/Roster/RosterController.h12
-rw-r--r--Swift/Controllers/Roster/UnitTest/LeastCommonSubsequenceTest.cpp4
-rw-r--r--Swift/Controllers/Roster/UnitTest/RosterControllerTest.cpp26
-rw-r--r--Swift/Controllers/SConscript5
-rw-r--r--Swift/Controllers/UIEvents/RequestFileTransferListUIEvent.h16
-rw-r--r--Swift/Controllers/UIEvents/SendFileUIEvent.h34
-rw-r--r--Swift/Controllers/UIInterfaces/ChatWindow.h13
-rw-r--r--Swift/Controllers/UIInterfaces/FileTransferListWidget.h23
-rw-r--r--Swift/Controllers/UIInterfaces/FileTransferListWidgetFactory.h20
-rw-r--r--Swift/Controllers/UIInterfaces/UIFactory.h6
-rw-r--r--Swift/Controllers/UnitTest/MockChatWindow.h7
33 files changed, 875 insertions, 25 deletions
diff --git a/Swift/Controllers/Chat/ChatController.cpp b/Swift/Controllers/Chat/ChatController.cpp
index f4aa745..a3d9fb5 100644
--- a/Swift/Controllers/Chat/ChatController.cpp
+++ b/Swift/Controllers/Chat/ChatController.cpp
@@ -14,28 +14,33 @@
#include <Swiften/Base/Algorithm.h>
#include <Swiften/Avatars/AvatarManager.h>
#include <Swiften/Chat/ChatStateNotifier.h>
#include <Swiften/Chat/ChatStateTracker.h>
#include <Swiften/Client/StanzaChannel.h>
#include <Swift/Controllers/UIInterfaces/ChatWindow.h>
#include <Swift/Controllers/UIInterfaces/ChatWindowFactory.h>
#include <Swiften/Client/NickResolver.h>
#include <Swift/Controllers/XMPPEvents/EventController.h>
+#include <Swift/Controllers/FileTransfer/FileTransferController.h>
#include <Swift/Controllers/StatusUtil.h>
#include <Swiften/Disco/EntityCapsProvider.h>
+#include <Swiften/Base/foreach.h>
+#include <Swift/Controllers/UIEvents/UIEventStream.h>
+#include <Swift/Controllers/UIEvents/SendFileUIEvent.h>
+
namespace Swift {
/**
* The controller does not gain ownership of the stanzaChannel, nor the factory.
*/
ChatController::ChatController(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &contact, NickResolver* nickResolver, PresenceOracle* presenceOracle, AvatarManager* avatarManager, bool isInMUC, bool useDelayForLatency, UIEventStream* eventStream, EventController* eventController, TimerFactory* timerFactory, EntityCapsProvider* entityCapsProvider)
- : ChatControllerBase(self, stanzaChannel, iqRouter, chatWindowFactory, contact, presenceOracle, avatarManager, useDelayForLatency, eventStream, eventController, timerFactory, entityCapsProvider) {
+ : ChatControllerBase(self, stanzaChannel, iqRouter, chatWindowFactory, contact, presenceOracle, avatarManager, useDelayForLatency, eventStream, eventController, timerFactory, entityCapsProvider), eventStream_(eventStream) {
isInMUC_ = isInMUC;
lastWasPresence_ = false;
chatStateNotifier_ = new ChatStateNotifier(stanzaChannel, contact, entityCapsProvider);
chatStateTracker_ = new ChatStateTracker();
nickResolver_ = nickResolver;
presenceOracle_->onPresenceChange.connect(boost::bind(&ChatController::handlePresenceChange, this, _1));
chatStateTracker_->onChatStateChange.connect(boost::bind(&ChatWindow::setContactChatState, chatWindow_, _1));
stanzaChannel_->onStanzaAcked.connect(boost::bind(&ChatController::handleStanzaAcked, this, _1));
nickResolver_->onNickChanged.connect(boost::bind(&ChatController::handleContactNickChanged, this, _1, _2));
@@ -54,18 +59,22 @@ ChatController::ChatController(const JID& self, StanzaChannel* stanzaChannel, IQ
if (theirPresence && !theirPresence->getStatus().empty()) {
startMessage += " (" + theirPresence->getStatus() + ")";
}
lastShownStatus_ = theirPresence ? theirPresence->getShow() : StatusShow::None;
chatStateNotifier_->setContactIsOnline(theirPresence && theirPresence->getType() == Presence::Available);
startMessage += ".";
chatWindow_->addSystemMessage(startMessage);
chatWindow_->onUserTyping.connect(boost::bind(&ChatStateNotifier::setUserIsTyping, chatStateNotifier_));
chatWindow_->onUserCancelsTyping.connect(boost::bind(&ChatStateNotifier::userCancelledNewMessage, chatStateNotifier_));
+ chatWindow_->onFileTransferStart.connect(boost::bind(&ChatController::handleFileTransferStart, this, _1, _2));
+ 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));
handleBareJIDCapsChanged(toJID_);
}
void ChatController::handleContactNickChanged(const JID& jid, const std::string& /*oldNick*/) {
if (jid.toBare() == toJID_.toBare()) {
chatWindow_->setName(nickResolver_->jidToNick(jid));
}
}
@@ -165,18 +174,57 @@ void ChatController::setOnline(bool online) {
Presence::ref fakeOffline(new Presence());
fakeOffline->setFrom(toJID_);
fakeOffline->setType(Presence::Unavailable);
chatStateTracker_->handlePresenceChange(fakeOffline);
}
ChatControllerBase::setOnline(online);
}
+void ChatController::handleNewFileTransferController(FileTransferController* ftc) {
+ std::string nick = senderDisplayNameFromMessage(ftc->getOtherParty());
+ std::string ftID = ftc->setChatWindow(chatWindow_, nick);
+
+ ftControllers[ftID] = ftc;
+}
+
+void ChatController::handleFileTransferCancel(std::string id) {
+ std::cout << "handleFileTransferCancel(" << id << ")" << std::endl;
+ if (ftControllers.find(id) != ftControllers.end()) {
+ ftControllers[id]->cancel();
+ } else {
+ std::cerr << "unknown file transfer UI id" << std::endl;
+ }
+}
+
+void ChatController::handleFileTransferStart(std::string id, std::string description) {
+ std::cout << "handleFileTransferStart(" << id << ", " << description << ")" << std::endl;
+ if (ftControllers.find(id) != ftControllers.end()) {
+ ftControllers[id]->start(description);
+ } else {
+ std::cerr << "unknown file transfer UI id" << std::endl;
+ }
+}
+
+void ChatController::handleFileTransferAccept(std::string id, std::string filename) {
+ std::cout << "handleFileTransferAccept(" << id << ", " << filename << ")" << std::endl;
+ if (ftControllers.find(id) != ftControllers.end()) {
+ ftControllers[id]->accept(filename);
+ } else {
+ std::cerr << "unknown file transfer UI id" << std::endl;
+ }
+}
+
+void ChatController::handleSendFileRequest(std::string filename) {
+ std::cout << "ChatController::handleSendFileRequest(" << filename << ")" << std::endl;
+ eventStream_->send(boost::make_shared<SendFileUIEvent>(getToJID(), filename));
+}
+
std::string ChatController::senderDisplayNameFromMessage(const JID& from) {
return nickResolver_->jidToNick(from);
}
std::string ChatController::getStatusChangeString(boost::shared_ptr<Presence> presence) {
std::string nick = senderDisplayNameFromMessage(presence->getFrom());
std::string response;
if (!presence || presence->getType() == Presence::Unavailable || presence->getType() == Presence::Error) {
response = QT_TRANSLATE_NOOP("", "%1% has gone offline");
diff --git a/Swift/Controllers/Chat/ChatController.h b/Swift/Controllers/Chat/ChatController.h
index f6b8763..2531adb 100644
--- a/Swift/Controllers/Chat/ChatController.h
+++ b/Swift/Controllers/Chat/ChatController.h
@@ -2,51 +2,64 @@
* Copyright (c) 2010 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#pragma once
#include "Swift/Controllers/Chat/ChatControllerBase.h"
+#include <map>
+#include <string>
+
namespace Swift {
class AvatarManager;
class ChatStateNotifier;
class ChatStateTracker;
class NickResolver;
class EntityCapsProvider;
+ class FileTransferController;
class ChatController : public ChatControllerBase {
public:
ChatController(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &contact, NickResolver* nickResolver, PresenceOracle* presenceOracle, AvatarManager* avatarManager, bool isInMUC, bool useDelayForLatency, UIEventStream* eventStream, EventController* eventController, TimerFactory* timerFactory, EntityCapsProvider* entityCapsProvider);
virtual ~ChatController();
virtual void setToJID(const JID& jid);
virtual void setOnline(bool online);
+ virtual void handleNewFileTransferController(FileTransferController* ftc);
private:
void handlePresenceChange(boost::shared_ptr<Presence> newPresence);
std::string getStatusChangeString(boost::shared_ptr<Presence> presence);
bool isIncomingMessageFromMe(boost::shared_ptr<Message> message);
void postSendMessage(const std::string &body, boost::shared_ptr<Stanza> sentStanza);
void preHandleIncomingMessage(boost::shared_ptr<MessageEvent> messageEvent);
void postHandleIncomingMessage(boost::shared_ptr<MessageEvent> messageEvent);
void preSendMessageRequest(boost::shared_ptr<Message>);
std::string senderDisplayNameFromMessage(const JID& from);
virtual boost::optional<boost::posix_time::ptime> getMessageTimestamp(boost::shared_ptr<Message>) const;
void handleStanzaAcked(boost::shared_ptr<Stanza> stanza);
void dayTicked() {lastWasPresence_ = false;}
void handleContactNickChanged(const JID& jid, const std::string& /*oldNick*/);
void handleBareJIDCapsChanged(const JID& jid);
+ void handleFileTransferCancel(std::string /* id */);
+ void handleFileTransferStart(std::string /* id */, std::string /* description */);
+ void handleFileTransferAccept(std::string /* id */, std::string /* filename */);
+ void handleSendFileRequest(std::string filename);
+
private:
NickResolver* nickResolver_;
ChatStateNotifier* chatStateNotifier_;
ChatStateTracker* chatStateTracker_;
std::string myLastMessageUIID_;
bool isInMUC_;
bool lastWasPresence_;
std::string lastStatusChangeString_;
std::map<boost::shared_ptr<Stanza>, std::string> unackedStanzas_;
StatusShow::Type lastShownStatus_;
+ UIEventStream* eventStream_;
+
+ std::map<std::string, FileTransferController*> ftControllers;
};
}
diff --git a/Swift/Controllers/Chat/ChatsManager.cpp b/Swift/Controllers/Chat/ChatsManager.cpp
index d631494..c61479c 100644
--- a/Swift/Controllers/Chat/ChatsManager.cpp
+++ b/Swift/Controllers/Chat/ChatsManager.cpp
@@ -23,18 +23,20 @@
#include <Swift/Controllers/UIEvents/EditMUCBookmarkUIEvent.h>
#include <Swift/Controllers/UIInterfaces/ChatListWindowFactory.h>
#include <Swift/Controllers/UIInterfaces/JoinMUCWindow.h>
#include <Swift/Controllers/UIInterfaces/JoinMUCWindowFactory.h>
#include <Swiften/Presence/PresenceSender.h>
#include <Swiften/Client/NickResolver.h>
#include <Swiften/MUC/MUCManager.h>
#include <Swiften/Elements/ChatState.h>
#include <Swiften/MUC/MUCBookmarkManager.h>
+#include <Swift/Controllers/FileTransfer/FileTransferController.h>
+#include <Swift/Controllers/FileTransfer/FileTransferOverview.h>
#include <Swift/Controllers/ProfileSettingsProvider.h>
#include <Swiften/Avatars/AvatarManager.h>
namespace Swift {
typedef std::pair<JID, ChatController*> JIDChatControllerPair;
typedef std::pair<JID, MUCController*> JIDMUCControllerPair;
#define RECENT_CHATS "recent_chats"
@@ -50,25 +52,27 @@ ChatsManager::ChatsManager(
PresenceSender* presenceSender,
UIEventStream* uiEventStream,
ChatListWindowFactory* chatListWindowFactory,
bool useDelayForLatency,
TimerFactory* timerFactory,
MUCRegistry* mucRegistry,
EntityCapsProvider* entityCapsProvider,
MUCManager* mucManager,
MUCSearchWindowFactory* mucSearchWindowFactory,
- ProfileSettingsProvider* settings) :
+ ProfileSettingsProvider* settings,
+ FileTransferOverview* ftOverview) :
jid_(jid),
joinMUCWindowFactory_(joinMUCWindowFactory),
useDelayForLatency_(useDelayForLatency),
mucRegistry_(mucRegistry),
entityCapsProvider_(entityCapsProvider),
- mucManager(mucManager) {
+ mucManager(mucManager),
+ ftOverview_(ftOverview) {
timerFactory_ = timerFactory;
eventController_ = eventController;
stanzaChannel_ = stanzaChannel;
iqRouter_ = iqRouter;
chatWindowFactory_ = chatWindowFactory;
nickResolver_ = nickResolver;
presenceOracle_ = presenceOracle;
avatarManager_ = NULL;
serverDiscoInfo_ = boost::shared_ptr<DiscoInfo>(new DiscoInfo());
@@ -80,18 +84,19 @@ ChatsManager::ChatsManager(
uiEventConnection_ = uiEventStream_->onUIEvent.connect(boost::bind(&ChatsManager::handleUIEvent, this, _1));
chatListWindow_ = chatListWindowFactory->createChatListWindow(uiEventStream_);
chatListWindow_->onMUCBookmarkActivated.connect(boost::bind(&ChatsManager::handleMUCBookmarkActivated, this, _1));
chatListWindow_->onRecentActivated.connect(boost::bind(&ChatsManager::handleRecentActivated, this, _1));
joinMUCWindow_ = NULL;
mucSearchController_ = new MUCSearchController(jid_, mucSearchWindowFactory, iqRouter, settings);
mucSearchController_->onMUCSelected.connect(boost::bind(&ChatsManager::handleMUCSelectedAfterSearch, this, _1));
+ ftOverview_->onNewFileTransferController.connect(boost::bind(&ChatsManager::handleNewFileTransferController, this, _1));
setupBookmarks();
loadRecents();
}
ChatsManager::~ChatsManager() {
delete joinMUCWindow_;
foreach (JIDChatControllerPair controllerPair, chatControllers_) {
delete controllerPair.second;
}
@@ -529,18 +534,24 @@ void ChatsManager::handleMUCSelectedAfterSearch(const JID& muc) {
if (joinMUCWindow_) {
joinMUCWindow_->setMUC(muc.toString());
}
}
void ChatsManager::handleMUCBookmarkActivated(const MUCBookmark& mucBookmark) {
uiEventStream_->send(boost::make_shared<JoinMUCUIEvent>(mucBookmark.getRoom(), mucBookmark.getNick()));
}
+void ChatsManager::handleNewFileTransferController(FileTransferController* ftc) {
+ ChatController* chatController = getChatControllerOrCreate(ftc->getOtherParty());
+ chatController->handleNewFileTransferController(ftc);
+ chatController->activateChatWindow();
+}
+
void ChatsManager::handleRecentActivated(const ChatListWindow::Chat& chat) {
if (chat.isMUC) {
uiEventStream_->send(boost::make_shared<JoinMUCUIEvent>(chat.jid, chat.nick));
}
else {
uiEventStream_->send(boost::make_shared<RequestChatUIEvent>(chat.jid));
}
}
diff --git a/Swift/Controllers/Chat/ChatsManager.h b/Swift/Controllers/Chat/ChatsManager.h
index b4db523..46c104d 100644
--- a/Swift/Controllers/Chat/ChatsManager.h
+++ b/Swift/Controllers/Chat/ChatsManager.h
@@ -37,22 +37,24 @@ namespace Swift {
class PresenceSender;
class MUCBookmarkManager;
class ChatListWindowFactory;
class TimerFactory;
class EntityCapsProvider;
class DirectedPresenceSender;
class MUCSearchWindowFactory;
class ProfileSettingsProvider;
class MUCSearchController;
-
+ class FileTransferOverview;
+ class FileTransferController;
+
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* settings);
+ 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* settings, FileTransferOverview* ftOverview);
virtual ~ChatsManager();
void setAvatarManager(AvatarManager* avatarManager);
void setOnline(bool enabled);
void setServerDiscoInfo(boost::shared_ptr<DiscoInfo> info);
void handleIncomingMessage(boost::shared_ptr<Message> message);
private:
ChatListWindow::Chat createChatListChatItem(const JID& jid, const std::string& activity);
void handleChatRequest(const std::string& contact);
@@ -61,18 +63,19 @@ namespace Swift {
void handleMUCSelectedAfterSearch(const JID&);
void rebindControllerJID(const JID& from, const JID& to);
void handlePresenceChange(boost::shared_ptr<Presence> newPresence);
void handleUIEvent(boost::shared_ptr<UIEvent> event);
void handleMUCBookmarkAdded(const MUCBookmark& bookmark);
void handleMUCBookmarkRemoved(const MUCBookmark& bookmark);
void handleUserLeftMUC(MUCController* mucController);
void handleBookmarksReady();
void handleChatActivity(const JID& jid, const std::string& activity, bool isMUC);
+ void handleNewFileTransferController(FileTransferController*);
void appendRecent(const ChatListWindow::Chat& chat);
void prependRecent(const ChatListWindow::Chat& chat);
void setupBookmarks();
void loadRecents();
void saveRecents();
void handleChatMadeRecent();
void handleMUCBookmarkActivated(const MUCBookmark&);
void handleRecentActivated(const ChatListWindow::Chat&);
void handleUnreadCountChanged(ChatControllerBase* controller);
@@ -104,11 +107,12 @@ namespace Swift {
boost::bsignals::scoped_connection uiEventConnection_;
bool useDelayForLatency_;
TimerFactory* timerFactory_;
MUCRegistry* mucRegistry_;
EntityCapsProvider* entityCapsProvider_;
MUCManager* mucManager;
MUCSearchController* mucSearchController_;
std::list<ChatListWindow::Chat> recentChats_;
ProfileSettingsProvider* profileSettings_;
+ FileTransferOverview* ftOverview_;
};
}
diff --git a/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp b/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp
index b8cb368..5339703 100644
--- a/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp
+++ b/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp
@@ -2,18 +2,20 @@
* Copyright (c) 2010-2011 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
#include "3rdParty/hippomocks.h"
+#include <boost/bind.hpp>
+
#include "Swift/Controllers/Chat/ChatsManager.h"
#include "Swift/Controllers/Chat/UnitTest/MockChatListWindow.h"
#include "Swift/Controllers/UIInterfaces/ChatWindow.h"
#include "Swift/Controllers/Settings/DummySettingsProvider.h"
#include "Swift/Controllers/UIInterfaces/ChatWindowFactory.h"
#include "Swift/Controllers/UIInterfaces/ChatListWindowFactory.h"
#include "Swift/Controllers/UIInterfaces/JoinMUCWindowFactory.h"
#include "Swift/Controllers/UIInterfaces/MUCSearchWindowFactory.h"
@@ -30,23 +32,26 @@
#include "Swiften/VCards/VCardManager.h"
#include "Swiften/VCards/VCardMemoryStorage.h"
#include "Swiften/Client/NickResolver.h"
#include "Swiften/Presence/DirectedPresenceSender.h"
#include "Swiften/Roster/XMPPRosterImpl.h"
#include "Swift/Controllers/UnitTest/MockChatWindow.h"
#include "Swiften/Client/DummyStanzaChannel.h"
#include "Swiften/Queries/DummyIQChannel.h"
#include "Swiften/Presence/PresenceOracle.h"
+#include "Swiften/Jingle/JingleSessionManager.h"
+#include "Swiften/FileTransfer/UnitTest/DummyFileTransferManager.h"
#include "Swift/Controllers/UIEvents/RequestChatUIEvent.h"
#include "Swift/Controllers/UIEvents/JoinMUCUIEvent.h"
#include "Swift/Controllers/UIEvents/UIEventStream.h"
#include <Swift/Controllers/ProfileSettingsProvider.h>
-
+#include "Swift/Controllers/FileTransfer/FileTransferOverview.h"
+#include <Swiften/Base/Algorithm.h>
using namespace Swift;
class DummyCapsProvider : public CapsProvider {
DiscoInfo::ref getCaps(const std::string&) const {return DiscoInfo::ref(new DiscoInfo());}
};
class ChatsManagerTest : public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(ChatsManagerTest);
@@ -80,31 +85,35 @@ public:
directedPresenceSender_ = new DirectedPresenceSender(presenceSender_);
mucManager_ = new MUCManager(stanzaChannel_, iqRouter_, directedPresenceSender_, mucRegistry_);
uiEventStream_ = new UIEventStream();
entityCapsManager_ = new EntityCapsManager(capsProvider_, stanzaChannel_);
chatListWindowFactory_ = mocks_->InterfaceMock<ChatListWindowFactory>();
mucSearchWindowFactory_ = mocks_->InterfaceMock<MUCSearchWindowFactory>();
settings_ = new DummySettingsProvider();
profileSettings_ = new ProfileSettingsProvider("a", settings_);
chatListWindow_ = new MockChatListWindow();
+ ftManager_ = new DummyFileTransferManager();
+ ftOverview_ = new FileTransferOverview(ftManager_);
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_);
+ manager_ = new ChatsManager(jid_, stanzaChannel_, iqRouter_, eventController_, chatWindowFactory_, joinMUCWindowFactory_, nickResolver_, presenceOracle_, directedPresenceSender_, uiEventStream_, chatListWindowFactory_, true, NULL, mucRegistry_, entityCapsManager_, mucManager_, mucSearchWindowFactory_, profileSettings_, ftOverview_);
avatarManager_ = new NullAvatarManager();
manager_->setAvatarManager(avatarManager_);
};
void tearDown() {
- //delete chatListWindowFactory_;
+ //delete chatListWindowFactory
delete settings_;
delete profileSettings_;
delete avatarManager_;
delete manager_;
+ delete ftOverview_;
+ delete ftManager_;
delete directedPresenceSender_;
delete presenceSender_;
delete presenceOracle_;
delete nickResolver_;
delete mucRegistry_;
delete stanzaChannel_;
delete eventController_;
delete iqRouter_;
delete iqChannel_;
@@ -348,13 +357,15 @@ private:
MUCSearchWindowFactory* mucSearchWindowFactory_;
MUCRegistry* mucRegistry_;
DirectedPresenceSender* directedPresenceSender_;
EntityCapsManager* entityCapsManager_;
CapsProvider* capsProvider_;
MUCManager* mucManager_;
DummySettingsProvider* settings_;
ProfileSettingsProvider* profileSettings_;
ChatListWindow* chatListWindow_;
+ FileTransferOverview* ftOverview_;
+ FileTransferManager* ftManager_;
};
CPPUNIT_TEST_SUITE_REGISTRATION(ChatsManagerTest);
diff --git a/Swift/Controllers/FileTransfer/FileTransferController.cpp b/Swift/Controllers/FileTransfer/FileTransferController.cpp
new file mode 100644
index 0000000..afa907d
--- /dev/null
+++ b/Swift/Controllers/FileTransfer/FileTransferController.cpp
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2011 Tobias Markmann
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include "FileTransferController.h"
+#include "Swiften/FileTransfer/OutgoingJingleFileTransfer.h"
+#include "Swiften/FileTransfer/FileTransferManager.h"
+#include <Swiften/FileTransfer/FileReadBytestream.h>
+#include <Swiften/Base/boost_bsignals.h>
+#include <boost/bind.hpp>
+#include "Swift/Controllers/UIInterfaces/ChatWindow.h"
+
+#include <boost/smart_ptr/make_shared.hpp>
+
+namespace Swift {
+
+FileTransferController::FileTransferController(const JID& receipient, const std::string& filename, FileTransferManager* fileTransferManager) :
+ sending(true), otherParty(receipient), filename(filename), ftManager(fileTransferManager), ftProgressInfo(0), chatWindow(0), currentState(FileTransfer::State::WaitingForStart) {
+
+}
+
+FileTransferController::FileTransferController(IncomingFileTransfer::ref transfer) :
+ sending(false), otherParty(transfer->getSender()), filename(transfer->filename), transfer(transfer), ftManager(0), ftProgressInfo(0), chatWindow(0), currentState(FileTransfer::State::WaitingForStart) {
+
+}
+
+FileTransferController::~FileTransferController() {
+ delete ftProgressInfo;
+}
+
+const JID &FileTransferController::getOtherParty() const {
+ return otherParty;
+}
+
+std::string FileTransferController::setChatWindow(ChatWindow* wnd, std::string nickname) {
+ chatWindow = wnd;
+ if (sending) {
+ uiID = wnd->addFileTransfer("me", true, filename, boost::filesystem::file_size(boost::filesystem::path(filename)));
+ } else {
+ uiID = wnd->addFileTransfer(nickname, false, filename, transfer->fileSizeInBytes);
+ }
+ return uiID;
+}
+
+void FileTransferController::setReceipient(const JID& receipient) {
+ this->otherParty = receipient;
+}
+
+bool FileTransferController::isIncoming() const {
+ return !sending;
+}
+
+FileTransfer::State FileTransferController::getState() const {
+ return currentState;
+}
+
+int FileTransferController::getProgress() const {
+ return ftProgressInfo ? ftProgressInfo->getPercentage() : 0;
+}
+
+boost::uintmax_t FileTransferController::getSize() const {
+ if (transfer) {
+ return transfer->fileSizeInBytes;
+ } else {
+ return 0;
+ }
+}
+
+void FileTransferController::start(std::string& description) {
+ std::cout << "FileTransferController::start" << std::endl;
+ fileReadStream = boost::make_shared<FileReadBytestream>(boost::filesystem::path(filename));
+ OutgoingFileTransfer::ref outgoingTransfer = ftManager->createOutgoingFileTransfer(otherParty, boost::filesystem::path(filename), description, fileReadStream);
+ if (outgoingTransfer) {
+ ftProgressInfo = new FileTransferProgressInfo(outgoingTransfer->fileSizeInBytes);
+ ftProgressInfo->onProgressPercentage.connect(boost::bind(&FileTransferController::handleProgressPercentageChange, this, _1));
+ outgoingTransfer->onStateChange.connect(boost::bind(&FileTransferController::handleFileTransferStateChange, this, _1));
+ outgoingTransfer->onProcessedBytes.connect(boost::bind(&FileTransferProgressInfo::setBytesProcessed, ftProgressInfo, _1));
+ outgoingTransfer->start();
+ transfer = outgoingTransfer;
+ } else {
+ std::cerr << "File transfer not supported!" << std::endl;
+ }
+}
+
+void FileTransferController::accept(std::string& file) {
+ std::cout << "FileTransferController::accept" << std::endl;
+ IncomingFileTransfer::ref incomingTransfer = boost::dynamic_pointer_cast<IncomingFileTransfer>(transfer);
+ if (incomingTransfer) {
+ fileWriteStream = boost::make_shared<FileWriteBytestream>(boost::filesystem::path(file));
+
+ ftProgressInfo = new FileTransferProgressInfo(transfer->fileSizeInBytes);
+ ftProgressInfo->onProgressPercentage.connect(boost::bind(&FileTransferController::handleProgressPercentageChange, this, _1));
+ transfer->onStateChange.connect(boost::bind(&FileTransferController::handleFileTransferStateChange, this, _1));
+ transfer->onProcessedBytes.connect(boost::bind(&FileTransferProgressInfo::setBytesProcessed, ftProgressInfo, _1));
+ incomingTransfer->accept(fileWriteStream);
+ } else {
+ std::cerr << "Expected an incoming transfer in this situation!" << std::endl;
+ }
+}
+
+void FileTransferController::cancel() {
+ if (transfer) {
+ transfer->cancel();
+ } else {
+ chatWindow->setFileTransferStatus(uiID, ChatWindow::Canceled);
+ }
+}
+
+void FileTransferController::handleFileTransferStateChange(FileTransfer::State state) {
+ currentState = state;
+ onStateChage();
+ switch(state.state) {
+ case FileTransfer::State::Negotiating:
+ chatWindow->setFileTransferStatus(uiID, ChatWindow::Negotiating);
+ return;
+ case FileTransfer::State::Transferring:
+ chatWindow->setFileTransferStatus(uiID, ChatWindow::Transferring);
+ return;
+ case FileTransfer::State::Canceled:
+ chatWindow->setFileTransferStatus(uiID, ChatWindow::Canceled);
+ return;
+ case FileTransfer::State::Finished:
+ chatWindow->setFileTransferStatus(uiID, ChatWindow::Finished);
+ if (fileWriteStream) {
+ fileWriteStream->close();
+ }
+ return;
+ case FileTransfer::State::Failed:
+ chatWindow->setFileTransferStatus(uiID, ChatWindow::FTFailed);
+ return;
+ case FileTransfer::State::WaitingForAccept:
+ chatWindow->setFileTransferStatus(uiID, ChatWindow::WaitingForAccept);
+ return;
+ case FileTransfer::State::WaitingForStart:
+ return;
+ }
+ std::cerr << "Unhandled FileTransfer::State!" << std::endl;
+}
+
+void FileTransferController::handleProgressPercentageChange(int percentage) {
+ onProgressChange();
+ chatWindow->setFileTransferProgress(uiID, percentage);
+}
+
+}
diff --git a/Swift/Controllers/FileTransfer/FileTransferController.h b/Swift/Controllers/FileTransfer/FileTransferController.h
new file mode 100644
index 0000000..5d98468
--- /dev/null
+++ b/Swift/Controllers/FileTransfer/FileTransferController.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2011 Tobias Markmann
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include <string>
+
+#include <boost/shared_ptr.hpp>
+
+#include <Swiften/JID/JID.h>
+#include <Swiften/FileTransfer/FileTransfer.h>
+#include <Swiften/FileTransfer/IncomingFileTransfer.h>
+#include <Swiften/FileTransfer/FileReadBytestream.h>
+#include <Swiften/FileTransfer/FileWriteBytestream.h>
+#include <Swift/Controllers/FileTransfer/FileTransferProgressInfo.h>
+
+namespace Swift {
+
+class FileTransferManager;
+class ChatWindow;
+
+class FileTransferController {
+public:
+ /**
+ * For outgoing file transfers. It'll create a file transfer via FileTransferManager as soon as the descriptive information is available.
+ */
+ FileTransferController(const JID&, const std::string&, FileTransferManager*);
+
+ /**
+ * For incoming file transfers.
+ */
+ FileTransferController(IncomingFileTransfer::ref transfer);
+ ~FileTransferController();
+
+ std::string setChatWindow(ChatWindow*, std::string nickname);
+ void setReceipient(const JID& otherParty);
+
+ void start(std::string& description);
+ void accept(std::string& file);
+ void cancel();
+
+ const JID &getOtherParty() const;
+ bool isIncoming() const;
+ FileTransfer::State getState() const;
+ int getProgress() const;
+ boost::uintmax_t getSize() const;
+
+ boost::signal<void ()> onStateChage;
+ boost::signal<void ()> onProgressChange;
+
+private:
+ void handleFileTransferStateChange(FileTransfer::State);
+ void handleProgressPercentageChange(int percentage);
+
+private:
+ bool sending;
+ JID otherParty;
+ std::string filename;
+ FileTransfer::ref transfer;
+ boost::shared_ptr<FileReadBytestream> fileReadStream;
+ boost::shared_ptr<FileWriteBytestream> fileWriteStream;
+ FileTransferManager* ftManager;
+ FileTransferProgressInfo* ftProgressInfo;
+ ChatWindow* chatWindow;
+ std::string uiID;
+ FileTransfer::State currentState;
+};
+
+}
diff --git a/Swift/Controllers/FileTransfer/FileTransferOverview.cpp b/Swift/Controllers/FileTransfer/FileTransferOverview.cpp
new file mode 100644
index 0000000..c3ffc5c
--- /dev/null
+++ b/Swift/Controllers/FileTransfer/FileTransferOverview.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2011 Tobias Markmann
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include "FileTransferOverview.h"
+
+#include <boost/bind.hpp>
+#include <Swiften/Base/boost_bsignals.h>
+
+#include <Swiften/FileTransfer/FileTransferManager.h>
+
+namespace Swift {
+
+FileTransferOverview::FileTransferOverview(FileTransferManager* ftm) : fileTransferManager(ftm) {
+ fileTransferManager->onIncomingFileTransfer.connect(boost::bind(&FileTransferOverview::handleIncomingFileTransfer, this, _1));
+}
+
+FileTransferOverview::~FileTransferOverview() {
+
+}
+
+void FileTransferOverview::sendFile(const JID& jid, const std::string& filename) {
+ FileTransferController* controller = new FileTransferController(jid, filename, fileTransferManager);
+ fileTransfers.push_back(controller);
+
+ onNewFileTransferController(controller);
+}
+
+void FileTransferOverview::handleIncomingFileTransfer(IncomingFileTransfer::ref transfer) {
+ FileTransferController* controller = new FileTransferController(transfer);
+ fileTransfers.push_back(controller);
+ onNewFileTransferController(controller);
+}
+
+const std::vector<FileTransferController*>& FileTransferOverview::getFileTransfers() const {
+ return fileTransfers;
+}
+
+}
diff --git a/Swift/Controllers/FileTransfer/FileTransferOverview.h b/Swift/Controllers/FileTransfer/FileTransferOverview.h
new file mode 100644
index 0000000..716666a
--- /dev/null
+++ b/Swift/Controllers/FileTransfer/FileTransferOverview.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2011 Tobias Markmann
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include <vector>
+
+#include "Swift/Controllers/FileTransfer/FileTransferController.h"
+
+#include <Swiften/Base/boost_bsignals.h>
+
+namespace Swift {
+
+class ChatsManager;
+class FileTransferManager;
+
+class FileTransferOverview {
+public:
+ FileTransferOverview(FileTransferManager*);
+ ~FileTransferOverview();
+
+ void sendFile(const JID&, const std::string&);
+ const std::vector<FileTransferController*>& getFileTransfers() const;
+
+ boost::signal<void (FileTransferController*)> onNewFileTransferController;
+
+private:
+ void handleIncomingFileTransfer(IncomingFileTransfer::ref transfer);
+
+private:
+ std::vector<FileTransferController*> fileTransfers;
+ FileTransferManager *fileTransferManager;
+};
+
+}
diff --git a/Swift/Controllers/FileTransfer/FileTransferProgressInfo.cpp b/Swift/Controllers/FileTransfer/FileTransferProgressInfo.cpp
new file mode 100644
index 0000000..6d19fa1
--- /dev/null
+++ b/Swift/Controllers/FileTransfer/FileTransferProgressInfo.cpp
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2011 Tobias Markmann
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include "FileTransferProgressInfo.h"
+
+#include <Swiften/Base/Log.h>
+
+namespace Swift {
+
+FileTransferProgressInfo::FileTransferProgressInfo(boost::uintmax_t completeBytes) : completeBytes(completeBytes), completedBytes(0), percentage(0) {
+ onProgressPercentage(0);
+}
+
+void FileTransferProgressInfo::setBytesProcessed(int processedBytes) {
+ int oldPercentage = int(double(completedBytes) / double(completeBytes) * 100.0);
+ completedBytes += processedBytes;
+ int newPercentage = int(double(completedBytes) / double(completeBytes) * 100.0);
+ if (oldPercentage != newPercentage) {
+ onProgressPercentage(newPercentage);
+ }
+ percentage = newPercentage;
+}
+
+int FileTransferProgressInfo::getPercentage() const {
+ return percentage;
+}
+
+}
diff --git a/Swift/Controllers/FileTransfer/FileTransferProgressInfo.h b/Swift/Controllers/FileTransfer/FileTransferProgressInfo.h
new file mode 100644
index 0000000..bb3c0fc
--- /dev/null
+++ b/Swift/Controllers/FileTransfer/FileTransferProgressInfo.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2011 Tobias Markmann
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include <Swiften/Base/boost_bsignals.h>
+
+namespace Swift {
+
+class FileTransferProgressInfo {
+public:
+ FileTransferProgressInfo(boost::uintmax_t completeBytes);
+
+public:
+ void setBytesProcessed(int processedBytes);
+
+ int getPercentage() const;
+ boost::signal<void (int)> onProgressPercentage;
+
+private:
+ boost::uintmax_t completeBytes;
+ boost::uintmax_t completedBytes;
+ int percentage;
+};
+
+}
diff --git a/Swift/Controllers/FileTransfer/SOCKS5BytestreamProxyFinder.cpp b/Swift/Controllers/FileTransfer/SOCKS5BytestreamProxyFinder.cpp
new file mode 100644
index 0000000..da0606c
--- /dev/null
+++ b/Swift/Controllers/FileTransfer/SOCKS5BytestreamProxyFinder.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2011 Tobias Markmann
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include "SOCKS5BytestreamProxyFinder.h"
+
+#include <boost/smart_ptr/make_shared.hpp>
+#include <boost/bind.hpp>
+
+#include <Swiften/Base/Log.h>
+#include <Swiften/Elements/S5BProxyRequest.h>
+#include <Swiften/Queries/GenericRequest.h>
+#include <Swiften/Queries/IQRouter.h>
+
+namespace Swift {
+
+SOCKS5BytestreamProxyFinder::SOCKS5BytestreamProxyFinder(const JID& service, IQRouter *iqRouter) : iqRouter(iqRouter) {
+ serviceWalker = boost::make_shared<DiscoServiceWalker>(service, iqRouter);
+ serviceWalker->onServiceFound.connect(boost::bind(&SOCKS5BytestreamProxyFinder::handleServiceFound, this, _1, _2));
+}
+
+void SOCKS5BytestreamProxyFinder::start() {
+ serviceWalker->beginWalk();
+}
+
+void SOCKS5BytestreamProxyFinder::sendBytestreamQuery(const JID& jid) {
+ S5BProxyRequest::ref proxyRequest = boost::make_shared<S5BProxyRequest>();
+ boost::shared_ptr<GenericRequest<S5BProxyRequest> > request = boost::make_shared<GenericRequest<S5BProxyRequest> >(IQ::Get, jid, proxyRequest, iqRouter);
+ request->onResponse.connect(boost::bind(&SOCKS5BytestreamProxyFinder::handleProxyResponse, this, _1, _2));
+ request->send();
+}
+
+void SOCKS5BytestreamProxyFinder::handleServiceFound(const JID& jid, boost::shared_ptr<DiscoInfo> discoInfo) {
+ if (discoInfo->hasFeature(DiscoInfo::Bytestream)) {
+ sendBytestreamQuery(jid);
+ }
+}
+
+void SOCKS5BytestreamProxyFinder::handleProxyResponse(boost::shared_ptr<S5BProxyRequest> request, ErrorPayload::ref error) {
+ if (error) {
+ SWIFT_LOG(debug) << "ERROR" << std::endl;
+ } else {
+ if (request) {
+ onProxyFound(request);
+ } else {
+ //assert(false);
+ }
+ }
+}
+
+}
diff --git a/Swift/Controllers/FileTransfer/SOCKS5BytestreamProxyFinder.h b/Swift/Controllers/FileTransfer/SOCKS5BytestreamProxyFinder.h
new file mode 100644
index 0000000..1727a63
--- /dev/null
+++ b/Swift/Controllers/FileTransfer/SOCKS5BytestreamProxyFinder.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2011 Tobias Markmann
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include <boost/shared_ptr.hpp>
+
+#include <Swift/Controllers/DiscoServiceWalker.h>
+#include <Swiften/Network/HostAddressPort.h>
+#include <Swiften/Elements/S5BProxyRequest.h>
+
+namespace Swift {
+
+class JID;
+class IQRouter;
+
+class SOCKS5BytestreamProxyFinder {
+public:
+ SOCKS5BytestreamProxyFinder(const JID& service, IQRouter *iqRouter);
+ void start();
+
+ boost::signal<void(boost::shared_ptr<S5BProxyRequest>)> onProxyFound;
+
+private:
+ void sendBytestreamQuery(const JID&);
+
+ void handleServiceFound(const JID&, boost::shared_ptr<DiscoInfo>);
+ void handleProxyResponse(boost::shared_ptr<S5BProxyRequest>, ErrorPayload::ref);
+private:
+ boost::shared_ptr<DiscoServiceWalker> serviceWalker;
+ IQRouter* iqRouter;
+ std::vector<boost::shared_ptr<GenericRequest<S5BProxyRequest> > > requests;
+};
+
+}
diff --git a/Swift/Controllers/FileTransferListController.cpp b/Swift/Controllers/FileTransferListController.cpp
new file mode 100644
index 0000000..093a3c4
--- /dev/null
+++ b/Swift/Controllers/FileTransferListController.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2011 Tobias Markmann
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include "Swift/Controllers/FileTransferListController.h"
+
+#include <boost/bind.hpp>
+
+#include "Swift/Controllers/UIInterfaces/FileTransferListWidgetFactory.h"
+#include "Swift/Controllers/UIEvents/RequestFileTransferListUIEvent.h"
+
+namespace Swift {
+
+FileTransferListController::FileTransferListController(UIEventStream* uiEventStream, FileTransferListWidgetFactory* fileTransferListWidgetFactory) : fileTransferListWidgetFactory(fileTransferListWidgetFactory), fileTransferListWidget(NULL), fileTransferOverview(0) {
+ uiEventStream->onUIEvent.connect(boost::bind(&FileTransferListController::handleUIEvent, this, _1));
+}
+
+FileTransferListController::~FileTransferListController() {
+ delete fileTransferListWidget;
+}
+
+void FileTransferListController::setFileTransferOverview(FileTransferOverview *overview) {
+ fileTransferOverview = overview;
+ if (fileTransferListWidget) {
+ fileTransferListWidget->setFileTransferOverview(fileTransferOverview);
+ }
+}
+
+void FileTransferListController::handleUIEvent(boost::shared_ptr<UIEvent> rawEvent) {
+ boost::shared_ptr<RequestFileTransferListUIEvent> event = boost::dynamic_pointer_cast<RequestFileTransferListUIEvent>(rawEvent);
+ if (event != NULL) {
+ if (fileTransferListWidget == NULL) {
+ fileTransferListWidget = fileTransferListWidgetFactory->createFileTransferListWidget();
+ if (fileTransferOverview) {
+ fileTransferListWidget->setFileTransferOverview(fileTransferOverview);
+ }
+ }
+ fileTransferListWidget->show();
+ fileTransferListWidget->activate();
+ }
+}
+
+}
diff --git a/Swift/Controllers/FileTransferListController.h b/Swift/Controllers/FileTransferListController.h
new file mode 100644
index 0000000..c5c8893
--- /dev/null
+++ b/Swift/Controllers/FileTransferListController.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2011 Tobias Markmann
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include <boost/shared_ptr.hpp>
+
+#include "Swift/Controllers/UIEvents/UIEventStream.h"
+
+namespace Swift {
+
+class FileTransferListWidgetFactory;
+class FileTransferListWidget;
+class FileTransferOverview;
+
+class FileTransferListController {
+public:
+ FileTransferListController(UIEventStream* uiEventStream, FileTransferListWidgetFactory* fileTransferListWidgetFactory);
+ ~FileTransferListController();
+
+ void setFileTransferOverview(FileTransferOverview* overview);
+
+private:
+ void handleUIEvent(boost::shared_ptr<UIEvent> event);
+
+private:
+ FileTransferListWidgetFactory* fileTransferListWidgetFactory;
+ FileTransferListWidget* fileTransferListWidget;
+ FileTransferOverview* fileTransferOverview;
+};
+
+}
diff --git a/Swift/Controllers/MainController.cpp b/Swift/Controllers/MainController.cpp
index 24c5303..b84e7d6 100644
--- a/Swift/Controllers/MainController.cpp
+++ b/Swift/Controllers/MainController.cpp
@@ -31,18 +31,19 @@
#include "Swift/Controllers/Chat/MUCController.h"
#include "Swiften/Client/NickResolver.h"
#include "Swift/Controllers/Roster/RosterController.h"
#include "Swift/Controllers/SoundEventController.h"
#include "Swift/Controllers/SoundPlayer.h"
#include "Swift/Controllers/StatusTracker.h"
#include "Swift/Controllers/SystemTray.h"
#include "Swift/Controllers/SystemTrayController.h"
#include "Swift/Controllers/XMLConsoleController.h"
+#include "Swift/Controllers/FileTransferListController.h"
#include "Swift/Controllers/UIEvents/UIEventStream.h"
#include "Swift/Controllers/PresenceNotifier.h"
#include "Swift/Controllers/EventNotifier.h"
#include "Swift/Controllers/Storages/StoragesFactory.h"
#include "SwifTools/Dock/Dock.h"
#include "SwifTools/Notifier/TogglableNotifier.h"
#include "Swiften/Base/foreach.h"
#include "Swiften/Client/Client.h"
#include "Swiften/Presence/PresenceSender.h"
@@ -62,18 +63,21 @@
#include "Swift/Controllers/UIEvents/JoinMUCUIEvent.h"
#include "Swift/Controllers/Storages/CertificateStorageFactory.h"
#include "Swift/Controllers/Storages/CertificateStorageTrustChecker.h"
#include "Swiften/Network/NetworkFactories.h"
#include <Swift/Controllers/ProfileController.h>
#include <Swift/Controllers/ContactEditController.h>
#include <Swift/Controllers/XMPPURIController.h>
#include "Swift/Controllers/AdHocManager.h"
#include <SwifTools/Idle/IdleDetector.h>
+#include <Swift/Controllers/FileTransfer/FileTransferOverview.h>
+#include <Swiften/FileTransfer/FileTransferManager.h>
+#include <Swiften/Client/ClientXMLTracer.h>
namespace Swift {
static const std::string CLIENT_NAME = "Swift";
static const std::string CLIENT_NODE = "http://swift.im";
static const std::string SHOW_NOTIFICATIONS = "showNotifications";
MainController::MainController(
@@ -95,19 +99,20 @@ MainController::MainController(
networkFactories_(networkFactories),
uiFactory_(uiFactories),
storagesFactory_(storagesFactory),
certificateStorageFactory_(certificateStorageFactory),
settings_(settings),
uriHandler_(uriHandler),
idleDetector_(idleDetector),
loginWindow_(NULL) ,
useDelayForLatency_(useDelayForLatency),
- eagleMode_(eagleMode) {
+ eagleMode_(eagleMode),
+ ftOverview_(NULL) {
storages_ = NULL;
certificateStorage_ = NULL;
statusTracker_ = NULL;
presenceNotifier_ = NULL;
eventNotifier_ = NULL;
rosterController_ = NULL;
chatsManager_ = NULL;
eventWindowController_ = NULL;
profileController_ = NULL;
@@ -158,18 +163,20 @@ MainController::MainController(
loginWindow_->onPurgeSavedLoginRequest.connect(boost::bind(&MainController::handlePurgeSavedLoginRequest, this, _1));
loginWindow_->onCancelLoginRequest.connect(boost::bind(&MainController::handleCancelLoginRequest, this));
loginWindow_->onQuitRequest.connect(boost::bind(&MainController::handleQuitRequest, this));
idleDetector_->setIdleTimeSeconds(600);
idleDetector_->onIdleChanged.connect(boost::bind(&MainController::handleInputIdleChanged, this, _1));
xmlConsoleController_ = new XMLConsoleController(uiEventStream_, uiFactory_);
+ fileTransferListController_ = new FileTransferListController(uiEventStream_, uiFactory_);
+
uiEventStream_->onUIEvent.connect(boost::bind(&MainController::handleUIEvent, this, _1));
bool enabled = settings_->getBoolSetting(SHOW_NOTIFICATIONS, true);
uiEventStream_->send(boost::shared_ptr<ToggleNotificationsUIEvent>(new ToggleNotificationsUIEvent(enabled)));
if (loginAutomatically) {
profileSettings_ = new ProfileSettingsProvider(selectedLoginJID, settings_);
handleLoginRequest(selectedLoginJID, cachedPassword, cachedCertificate, true, true);
} else {
profileSettings_ = NULL;
@@ -178,19 +185,19 @@ MainController::MainController(
MainController::~MainController() {
idleDetector_->onIdleChanged.disconnect(boost::bind(&MainController::handleInputIdleChanged, this, _1));
purgeCachedCredentials();
//setManagersOffline();
eventController_->disconnectAll();
resetClient();
-
+ delete fileTransferListController_;
delete xmlConsoleController_;
delete xmppURIController_;
delete soundEventController_;
delete systemTrayController_;
delete eventController_;
delete notifier_;
delete uiEventStream_;
}
@@ -205,18 +212,22 @@ void MainController::resetClient() {
vCardPhotoHash_.clear();
delete contactEditController_;
contactEditController_ = NULL;
delete profileController_;
profileController_ = NULL;
delete eventWindowController_;
eventWindowController_ = NULL;
delete chatsManager_;
chatsManager_ = NULL;
+ delete s5bProxyFinder_;
+ s5bProxyFinder_ = NULL;
+ delete ftOverview_;
+ ftOverview_ = NULL;
delete rosterController_;
rosterController_ = NULL;
delete eventNotifier_;
eventNotifier_ = NULL;
delete presenceNotifier_;
presenceNotifier_ = NULL;
delete certificateStorage_;
certificateStorage_ = NULL;
delete storages_;
@@ -264,37 +275,50 @@ void MainController::handleConnected() {
if (eagleMode_) {
purgeCachedCredentials();
}
bool freshLogin = rosterController_ == NULL;
myStatusLooksOnline_ = true;
if (freshLogin) {
profileController_ = new ProfileController(client_->getVCardManager(), uiFactory_, uiEventStream_);
- rosterController_ = new RosterController(jid_, client_->getRoster(), client_->getAvatarManager(), uiFactory_, client_->getNickManager(), client_->getNickResolver(), client_->getPresenceOracle(), client_->getSubscriptionManager(), eventController_, uiEventStream_, client_->getIQRouter(), settings_);
+ srand(time(NULL));
+ int randomPort = 10000 + rand() % 10000;
+ client_->getFileTransferManager()->startListeningOnPort(randomPort);
+ s5bProxyFinder_ = new SOCKS5BytestreamProxyFinder(client_->getJID().getDomain(), client_->getIQRouter());
+ s5bProxyFinder_->onProxyFound.connect(boost::bind(&FileTransferManager::addS5BProxy, client_->getFileTransferManager(), _1));
+ s5bProxyFinder_->start();
+ ftOverview_ = new FileTransferOverview(client_->getFileTransferManager());
+ fileTransferListController_->setFileTransferOverview(ftOverview_);
+ rosterController_ = new RosterController(jid_, client_->getRoster(), client_->getAvatarManager(), uiFactory_, client_->getNickManager(), client_->getNickResolver(), client_->getPresenceOracle(), client_->getSubscriptionManager(), eventController_, uiEventStream_, client_->getIQRouter(), settings_, client_->getEntityCapsProvider(), ftOverview_);
rosterController_->onChangeStatusRequest.connect(boost::bind(&MainController::handleChangeStatusRequest, this, _1, _2));
rosterController_->onSignOutRequest.connect(boost::bind(&MainController::signOut, this));
contactEditController_ = new ContactEditController(rosterController_, uiFactory_, uiEventStream_);
- 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_);
+ 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_->onMessageReceived.connect(boost::bind(&ChatsManager::handleIncomingMessage, chatsManager_, _1));
chatsManager_->setAvatarManager(client_->getAvatarManager());
eventWindowController_ = new EventWindowController(eventController_, uiFactory_);
loginWindow_->morphInto(rosterController_->getWindow());
DiscoInfo discoInfo;
discoInfo.addIdentity(DiscoInfo::Identity(CLIENT_NAME, "client", "pc"));
discoInfo.addFeature(DiscoInfo::ChatStatesFeature);
discoInfo.addFeature(DiscoInfo::SecurityLabelsFeature);
discoInfo.addFeature(DiscoInfo::MessageCorrectionFeature);
+ discoInfo.addFeature(DiscoInfo::JingleFeature);
+ discoInfo.addFeature(DiscoInfo::JingleFTFeature);
+ discoInfo.addFeature(DiscoInfo::JingleTransportsIBBFeature);
+ discoInfo.addFeature(DiscoInfo::JingleTransportsS5BFeature);
client_->getDiscoManager()->setCapsNode(CLIENT_NODE);
client_->getDiscoManager()->setDiscoInfo(discoInfo);
userSearchControllerChat_ = new UserSearchController(UserSearchController::StartChat, jid_, uiEventStream_, uiFactory_, client_->getIQRouter(), rosterController_);
userSearchControllerAdd_ = new UserSearchController(UserSearchController::AddContact, jid_, uiEventStream_, uiFactory_, client_->getIQRouter(), rosterController_);
adHocManager_ = new AdHocManager(boundJID_, uiFactory_, client_->getIQRouter(), uiEventStream_, rosterController_->getWindow());
}
loginWindow_->setIsLoggingIn(false);
diff --git a/Swift/Controllers/MainController.h b/Swift/Controllers/MainController.h
index 7ac6648..2aaa542 100644
--- a/Swift/Controllers/MainController.h
+++ b/Swift/Controllers/MainController.h
@@ -17,18 +17,20 @@
#include "Swiften/Elements/DiscoInfo.h"
#include "Swiften/Elements/VCard.h"
#include "Swiften/Elements/ErrorPayload.h"
#include "Swiften/Elements/Presence.h"
#include "Swift/Controllers/Settings/SettingsProvider.h"
#include "Swift/Controllers/ProfileSettingsProvider.h"
#include "Swiften/Elements/CapsInfo.h"
#include "Swift/Controllers/XMPPEvents/ErrorEvent.h"
#include "Swift/Controllers/UIEvents/UIEvent.h"
+#include "Swift/Controllers/FileTransfer/SOCKS5BytestreamProxyFinder.h"
+#include "Swiften/Client/ClientXMLTracer.h"
namespace Swift {
class IdleDetector;
class UIFactory;
class EventLoop;
class Client;
class ChatController;
class ChatsManager;
class CertificateStorageFactory;
@@ -45,32 +47,34 @@ namespace Swift {
class ContactEditController;
class TogglableNotifier;
class PresenceNotifier;
class EventNotifier;
class SystemTray;
class SystemTrayController;
class SoundEventController;
class SoundPlayer;
class XMLConsoleController;
+ class FileTransferListController;
class UIEventStream;
class EventWindowFactory;
class EventWindowController;
class MUCSearchController;
class UserSearchController;
class StatusTracker;
class Dock;
class Storages;
class StoragesFactory;
class NetworkFactories;
class URIHandler;
class XMPPURIController;
class AdHocManager;
class AdHocCommandWindowFactory;
+ class FileTransferOverview;
class MainController {
public:
MainController(
EventLoop* eventLoop,
NetworkFactories* networkFactories,
UIFactory* uiFactories,
SettingsProvider *settings,
SystemTray* systemTray,
@@ -134,18 +138,19 @@ namespace Swift {
PresenceNotifier* presenceNotifier_;
EventNotifier* eventNotifier_;
RosterController* rosterController_;
EventController* eventController_;
EventWindowController* eventWindowController_;
AdHocManager* adHocManager_;
LoginWindow* loginWindow_;
UIEventStream* uiEventStream_;
XMLConsoleController* xmlConsoleController_;
+ FileTransferListController* fileTransferListController_;
ChatsManager* chatsManager_;
ProfileController* profileController_;
ContactEditController* contactEditController_;
JID jid_;
JID boundJID_;
SystemTrayController* systemTrayController_;
SoundEventController* soundEventController_;
XMPPURIController* xmppURIController_;
std::string vCardPhotoHash_;
@@ -156,11 +161,13 @@ namespace Swift {
UserSearchController* userSearchControllerChat_;
UserSearchController* userSearchControllerAdd_;
int timeBeforeNextReconnect_;
Timer::ref reconnectTimer_;
StatusTracker* statusTracker_;
bool myStatusLooksOnline_;
bool quitRequested_;
static const int SecondsToWaitBeforeForceQuitting;
bool eagleMode_;
+ FileTransferOverview* ftOverview_;
+ SOCKS5BytestreamProxyFinder* s5bProxyFinder_;
};
}
diff --git a/Swift/Controllers/Roster/ContactRosterItem.cpp b/Swift/Controllers/Roster/ContactRosterItem.cpp
index bbe81e6..6d707bb 100644
--- a/Swift/Controllers/Roster/ContactRosterItem.cpp
+++ b/Swift/Controllers/Roster/ContactRosterItem.cpp
@@ -107,12 +107,20 @@ const std::vector<std::string>& ContactRosterItem::getGroups() const {
/** Only used so a contact can know about the groups it's in*/
void ContactRosterItem::addGroup(const std::string& group) {
groups_.push_back(group);
}
void ContactRosterItem::removeGroup(const std::string& group) {
groups_.erase(std::remove(groups_.begin(), groups_.end(), group), groups_.end());
}
+void ContactRosterItem::setSupportedFeatures(const std::set<Feature>& features) {
+ features_ = features;
+}
+
+bool ContactRosterItem::supportsFeature(const Feature feat) const {
+ return features_.find(feat) != features_.end();
+}
+
}
diff --git a/Swift/Controllers/Roster/ContactRosterItem.h b/Swift/Controllers/Roster/ContactRosterItem.h
index 7aa948c..67ffaa9 100644
--- a/Swift/Controllers/Roster/ContactRosterItem.h
+++ b/Swift/Controllers/Roster/ContactRosterItem.h
@@ -7,48 +7,58 @@
#pragma once
#include <string>
#include "Swiften/JID/JID.h"
#include "Swift/Controllers/Roster/RosterItem.h"
#include "Swiften/Elements/StatusShow.h"
#include "Swiften/Elements/Presence.h"
#include <map>
+#include <set>
#include <boost/bind.hpp>
#include "Swiften/Base/boost_bsignals.h"
#include <boost/shared_ptr.hpp>
namespace Swift {
class GroupRosterItem;
class ContactRosterItem : public RosterItem {
public:
+ enum Feature {
+ FileTransferFeature,
+ };
+
+ public:
ContactRosterItem(const JID& jid, const JID& displayJID, const std::string& name, GroupRosterItem* parent);
virtual ~ContactRosterItem();
StatusShow::Type getStatusShow() const;
StatusShow::Type getSimplifiedStatusShow() const;
std::string getStatusText() const;
void setAvatarPath(const std::string& path);
const std::string& getAvatarPath() const;
const JID& getJID() const;
void setDisplayJID(const JID& jid);
const JID& getDisplayJID() const;
void applyPresence(const std::string& resource, boost::shared_ptr<Presence> presence);
void clearPresence();
void calculateShownPresence();
const std::vector<std::string>& getGroups() const;
/** Only used so a contact can know about the groups it's in*/
void addGroup(const std::string& group);
void removeGroup(const std::string& group);
+
+ void setSupportedFeatures(const std::set<Feature>& features);
+ bool supportsFeature(Feature feat) const;
private:
JID jid_;
JID displayJID_;
std::string avatarPath_;
std::map<std::string, boost::shared_ptr<Presence> > presences_;
boost::shared_ptr<Presence> offlinePresence_;
boost::shared_ptr<Presence> shownPresence_;
std::vector<std::string> groups_;
+ std::set<Feature> features_;
};
}
diff --git a/Swift/Controllers/Roster/Roster.cpp b/Swift/Controllers/Roster/Roster.cpp
index a62a18a..f3d058e 100644
--- a/Swift/Controllers/Roster/Roster.cpp
+++ b/Swift/Controllers/Roster/Roster.cpp
@@ -11,18 +11,19 @@
#include "Swiften/JID/JID.h"
#include "Swift/Controllers/Roster/ContactRosterItem.h"
#include "Swift/Controllers/Roster/RosterItem.h"
#include "Swift/Controllers/Roster/GroupRosterItem.h"
#include "Swift/Controllers/Roster/RosterItemOperation.h"
#include <boost/bind.hpp>
#include <iostream>
+#include <set>
#include <deque>
namespace Swift {
Roster::Roster(bool sortByStatus, bool fullJIDMapping) {
sortByStatus_ = sortByStatus;
fullJIDMapping_ = fullJIDMapping;
root_ = new GroupRosterItem("Dummy-Root", NULL, sortByStatus_);
root_->onChildrenChanged.connect(boost::bind(&Roster::handleChildrenChanged, this, root_));
@@ -54,33 +55,40 @@ GroupRosterItem* Roster::getGroup(const std::string& groupName) {
}
}
GroupRosterItem* group = new GroupRosterItem(groupName, root_, sortByStatus_);
root_->addChild(group);
group->onChildrenChanged.connect(boost::bind(&Roster::handleChildrenChanged, this, group));
group->onDataChanged.connect(boost::bind(&Roster::handleDataChanged, this, group));
return group;
}
+void Roster::setAvailableFeatures(const JID& jid, const std::set<ContactRosterItem::Feature>& features) {
+ if (itemMap_[fullJIDMapping_ ? jid : jid.toBare()].empty()) return;
+ foreach(ContactRosterItem* item, itemMap_[fullJIDMapping_ ? jid : jid.toBare()]) {
+ item->setSupportedFeatures(features);
+ }
+}
+
void Roster::removeGroup(const std::string& group) {
root_->removeGroupChild(group);
}
void Roster::handleDataChanged(RosterItem* item) {
onDataChanged(item);
}
void Roster::handleChildrenChanged(GroupRosterItem* item) {
onChildrenChanged(item);
}
void Roster::addContact(const JID& jid, const JID& displayJID, const std::string& name, const std::string& groupName, const std::string& avatarPath) {
GroupRosterItem* group(getGroup(groupName));
- ContactRosterItem *item = new ContactRosterItem(jid, displayJID, name, group);
+ ContactRosterItem *item = new ContactRosterItem(jid, displayJID, name, group);
item->setAvatarPath(avatarPath);
group->addChild(item);
if (itemMap_[fullJIDMapping_ ? jid : jid.toBare()].size() > 0) {
foreach (std::string existingGroup, itemMap_[fullJIDMapping_ ? jid : jid.toBare()][0]->getGroups()) {
item->addGroup(existingGroup);
}
}
itemMap_[fullJIDMapping_ ? jid : jid.toBare()].push_back(item);
item->onDataChanged.connect(boost::bind(&Roster::handleDataChanged, this, item));
diff --git a/Swift/Controllers/Roster/Roster.h b/Swift/Controllers/Roster/Roster.h
index 53161a8..2b4dd27 100644
--- a/Swift/Controllers/Roster/Roster.h
+++ b/Swift/Controllers/Roster/Roster.h
@@ -4,18 +4,19 @@
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#pragma once
#include <string>
#include "Swiften/JID/JID.h"
#include "Swift/Controllers/Roster/RosterItemOperation.h"
#include "Swift/Controllers/Roster/RosterFilter.h"
+#include <Swift/Controllers/Roster/ContactRosterItem.h>
#include <vector>
#include <map>
#include "Swiften/Base/boost_bsignals.h"
#include <boost/shared_ptr.hpp>
namespace Swift {
class RosterItem;
@@ -37,18 +38,20 @@ class Roster {
void applyOnItem(const RosterItemOperation& operation, const JID& jid);
void addFilter(RosterFilter *filter) {filters_.push_back(filter);filterAll();};
void removeFilter(RosterFilter *filter);
GroupRosterItem* getRoot();
std::vector<RosterFilter*> getFilters() {return filters_;};
boost::signal<void (GroupRosterItem*)> onChildrenChanged;
boost::signal<void (GroupRosterItem*)> onGroupAdded;
boost::signal<void (RosterItem*)> onDataChanged;
GroupRosterItem* getGroup(const std::string& groupName);
+ void setAvailableFeatures(const JID& jid, const std::set<ContactRosterItem::Feature>& features);
+
private:
void handleDataChanged(RosterItem* item);
void handleChildrenChanged(GroupRosterItem* item);
void filterGroup(GroupRosterItem* item);
void filterContact(ContactRosterItem* contact, GroupRosterItem* group);
void filterAll();
GroupRosterItem* root_;
std::vector<RosterFilter*> filters_;
std::map<JID, std::vector<ContactRosterItem*> > itemMap_;
diff --git a/Swift/Controllers/Roster/RosterController.cpp b/Swift/Controllers/Roster/RosterController.cpp
index 5b61abf..66948c1 100644
--- a/Swift/Controllers/Roster/RosterController.cpp
+++ b/Swift/Controllers/Roster/RosterController.cpp
@@ -30,31 +30,37 @@
#include "Swift/Controllers/Roster/OfflineRosterFilter.h"
#include "Swift/Controllers/Roster/GroupRosterItem.h"
#include "Swiften/Roster/XMPPRoster.h"
#include "Swiften/Roster/XMPPRosterItem.h"
#include "Swift/Controllers/UIEvents/AddContactUIEvent.h"
#include "Swift/Controllers/UIEvents/RemoveRosterItemUIEvent.h"
#include "Swift/Controllers/UIEvents/RenameRosterItemUIEvent.h"
#include "Swift/Controllers/UIEvents/RenameGroupUIEvent.h"
#include "Swift/Controllers/UIEvents/ToggleShowOfflineUIEvent.h"
+#include "Swift/Controllers/UIEvents/SendFileUIEvent.h"
+#include <Swiften/FileTransfer/FileTransferManager.h>
#include <Swiften/Client/NickManager.h>
#include <Swift/Controllers/Intl.h>
#include <Swiften/Base/format.h>
+#include <Swiften/Elements/DiscoInfo.h>
+#include <Swiften/Disco/EntityCapsManager.h>
+#include <Swiften/Jingle/JingleSessionManager.h>
namespace Swift {
static const std::string SHOW_OFFLINE = "showOffline";
/**
* The controller does not gain ownership of these parameters.
*/
-RosterController::RosterController(const JID& jid, XMPPRoster* xmppRoster, AvatarManager* avatarManager, MainWindowFactory* mainWindowFactory, NickManager* nickManager, NickResolver* nickResolver, PresenceOracle* presenceOracle, SubscriptionManager* subscriptionManager, EventController* eventController, UIEventStream* uiEventStream, IQRouter* iqRouter, SettingsProvider* settings)
- : myJID_(jid), xmppRoster_(xmppRoster), mainWindowFactory_(mainWindowFactory), mainWindow_(mainWindowFactory_->createMainWindow(uiEventStream)), roster_(new Roster()), offlineFilter_(new OfflineRosterFilter()), nickManager_(nickManager), nickResolver_(nickResolver), uiEventStream_(uiEventStream) {
+RosterController::RosterController(const JID& jid, XMPPRoster* xmppRoster, AvatarManager* avatarManager, MainWindowFactory* mainWindowFactory, NickManager* nickManager, NickResolver* nickResolver, PresenceOracle* presenceOracle, SubscriptionManager* subscriptionManager, EventController* eventController, UIEventStream* uiEventStream, IQRouter* iqRouter, SettingsProvider* settings, EntityCapsProvider* entityCapsManager, FileTransferOverview* fileTransferOverview)
+ : myJID_(jid), xmppRoster_(xmppRoster), mainWindowFactory_(mainWindowFactory), mainWindow_(mainWindowFactory_->createMainWindow(uiEventStream)), roster_(new Roster()), offlineFilter_(new OfflineRosterFilter()), nickManager_(nickManager), nickResolver_(nickResolver), uiEventStream_(uiEventStream), entityCapsManager_(entityCapsManager), ftOverview_(fileTransferOverview) {
+ assert(fileTransferOverview);
iqRouter_ = iqRouter;
presenceOracle_ = presenceOracle;
subscriptionManager_ = subscriptionManager;
eventController_ = eventController;
settings_ = settings;
expandiness_ = new RosterGroupExpandinessPersister(roster_, settings);
roster_->addFilter(offlineFilter_);
mainWindow_->setRosterModel(roster_);
@@ -68,35 +74,38 @@ RosterController::RosterController(const JID& jid, XMPPRoster* xmppRoster, Avata
presenceOracle_->onPresenceChange.connect(boost::bind(&RosterController::handleIncomingPresence, this, _1));
uiEventConnection_ = uiEventStream->onUIEvent.connect(boost::bind(&RosterController::handleUIEvent, this, _1));
avatarManager_ = avatarManager;
avatarManager_->onAvatarChanged.connect(boost::bind(&RosterController::handleAvatarChanged, this, _1));
mainWindow_->setMyAvatarPath(avatarManager_->getAvatarPath(myJID_).string());
nickManager_->onOwnNickChanged.connect(boost::bind(&MainWindow::setMyNick, mainWindow_, _1));
mainWindow_->setMyJID(jid);
mainWindow_->setMyNick(nickManager_->getOwnNick());
+
+ entityCapsManager_->onCapsChanged.connect(boost::bind(&RosterController::handleOnCapsChanged, this, _1));
if (settings->getBoolSetting(SHOW_OFFLINE, false)) {
uiEventStream->onUIEvent(boost::shared_ptr<UIEvent>(new ToggleShowOfflineUIEvent(true)));
}
}
-RosterController::~RosterController() {
+RosterController::~RosterController() {
nickManager_->onOwnNickChanged.disconnect(boost::bind(&MainWindow::setMyNick, mainWindow_, _1));
-
+
delete offlineFilter_;
delete expandiness_;
mainWindow_->setRosterModel(NULL);
if (mainWindow_->canDelete()) {
delete mainWindow_;
}
delete roster_;
+
}
void RosterController::setEnabled(bool enabled) {
if (!enabled) {
roster_->applyOnItems(AppearOffline());
}
}
void RosterController::handleShowOfflineToggled(bool state) {
@@ -220,18 +229,22 @@ void RosterController::handleUIEvent(boost::shared_ptr<UIEvent> event) {
groups.erase(std::remove(groups.begin(), groups.end(), group), groups.end());
if (std::find(groups.begin(), groups.end(), renameGroupEvent->getNewName()) == groups.end()) {
groups.push_back(renameGroupEvent->getNewName());
}
item.setGroups(groups);
updateItem(item);
}
}
}
+ else if (boost::shared_ptr<SendFileUIEvent> sendFileEvent = boost::dynamic_pointer_cast<SendFileUIEvent>(event)) {
+ //TODO add send file dialog to ChatView of receipient jid
+ ftOverview_->sendFile(sendFileEvent->getJID(), sendFileEvent->getFilename());
+ }
}
void RosterController::setContactGroups(const JID& jid, const std::vector<std::string>& groups) {
updateItem(XMPPRosterItem(jid, xmppRoster_->getNameForJID(jid), groups, xmppRoster_->getSubscriptionStateForJID(jid)));
}
void RosterController::updateItem(const XMPPRosterItem& item) {
RosterItemPayload itemPayload(item.getJID(), item.getName(), item.getSubscription());
itemPayload.setGroups(item.getGroups());
@@ -296,10 +309,21 @@ void RosterController::handleAvatarChanged(const JID& jid) {
boost::optional<XMPPRosterItem> RosterController::getItem(const JID& jid) const {
return xmppRoster_->getItem(jid);
}
std::set<std::string> RosterController::getGroups() const {
return xmppRoster_->getGroups();
}
+void RosterController::handleOnCapsChanged(const JID& jid) {
+ DiscoInfo::ref info = entityCapsManager_->getCaps(jid);
+ if (info) {
+ std::set<ContactRosterItem::Feature> features;
+ if (info->hasFeature(DiscoInfo::JingleFeature) && info->hasFeature(DiscoInfo::JingleFTFeature) && info->hasFeature(DiscoInfo::JingleTransportsIBBFeature)) {
+ features.insert(ContactRosterItem::FileTransferFeature);
+ }
+ roster_->setAvailableFeatures(jid, features);
+ }
+}
+
}
diff --git a/Swift/Controllers/Roster/RosterController.h b/Swift/Controllers/Roster/RosterController.h
index 0a2b818..66748ca 100644
--- a/Swift/Controllers/Roster/RosterController.h
+++ b/Swift/Controllers/Roster/RosterController.h
@@ -2,24 +2,26 @@
* Copyright (c) 2010 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#pragma once
#include "Swiften/JID/JID.h"
#include <string>
+#include <set>
#include "Swiften/Elements/Presence.h"
#include "Swiften/Elements/ErrorPayload.h"
#include "Swiften/Elements/RosterPayload.h"
#include "Swiften/Avatars/AvatarManager.h"
#include "Swift/Controllers/UIEvents/UIEvent.h"
#include "RosterGroupExpandinessPersister.h"
+#include "Swift/Controllers/FileTransfer/FileTransferOverview.h"
#include "Swiften/Base/boost_bsignals.h"
#include <boost/shared_ptr.hpp>
namespace Swift {
class IQRouter;
class Roster;
class XMPPRoster;
class XMPPRosterItem;
@@ -29,22 +31,24 @@ namespace Swift {
class NickResolver;
class PresenceOracle;
class SubscriptionManager;
class EventController;
class SubscriptionRequestEvent;
class UIEventStream;
class IQRouter;
class SettingsProvider;
class NickManager;
-
+ class EntityCapsProvider;
+ class FileTransferManager;
+
class RosterController {
public:
- RosterController(const JID& jid, XMPPRoster* xmppRoster, AvatarManager* avatarManager, MainWindowFactory* mainWindowFactory, NickManager* nickManager, NickResolver* nickResolver, PresenceOracle* presenceOracle, SubscriptionManager* subscriptionManager, EventController* eventController, UIEventStream* uiEventStream, IQRouter* iqRouter_, SettingsProvider* settings);
+ RosterController(const JID& jid, XMPPRoster* xmppRoster, AvatarManager* avatarManager, MainWindowFactory* mainWindowFactory, NickManager* nickManager, NickResolver* nickResolver, PresenceOracle* presenceOracle, SubscriptionManager* subscriptionManager, EventController* eventController, UIEventStream* uiEventStream, IQRouter* iqRouter_, SettingsProvider* settings, EntityCapsProvider* entityCapsProvider, FileTransferOverview* fileTransferOverview);
~RosterController();
void showRosterWindow();
MainWindow* getWindow() {return mainWindow_;};
boost::signal<void (StatusShow::Type, const std::string&)> onChangeStatusRequest;
boost::signal<void ()> onSignOutRequest;
void handleAvatarChanged(const JID& jid);
void setEnabled(bool enabled);
boost::optional<XMPPRosterItem> getItem(const JID&) const;
@@ -63,31 +67,35 @@ namespace Swift {
void handleShowOfflineToggled(bool state);
void handleIncomingPresence(boost::shared_ptr<Presence> newPresence);
void handleSubscriptionRequest(const JID& jid, const std::string& message);
void handleSubscriptionRequestAccepted(SubscriptionRequestEvent* event);
void handleSubscriptionRequestDeclined(SubscriptionRequestEvent* event);
void handleUIEvent(boost::shared_ptr<UIEvent> event);
void handleRosterSetError(ErrorPayload::ref error, boost::shared_ptr<RosterPayload> rosterPayload);
void applyAllPresenceTo(const JID& jid);
void handleEditProfileRequest();
+ void handleOnCapsChanged(const JID& jid);
JID myJID_;
XMPPRoster* xmppRoster_;
MainWindowFactory* mainWindowFactory_;
MainWindow* mainWindow_;
Roster* roster_;
OfflineRosterFilter* offlineFilter_;
AvatarManager* avatarManager_;
NickManager* nickManager_;
NickResolver* nickResolver_;
PresenceOracle* presenceOracle_;
SubscriptionManager* subscriptionManager_;
EventController* eventController_;
RosterGroupExpandinessPersister* expandiness_;
IQRouter* iqRouter_;
SettingsProvider* settings_;
UIEventStream* uiEventStream_;
+ EntityCapsProvider* entityCapsManager_;
+ FileTransferOverview* ftOverview_;
+
boost::bsignals::scoped_connection changeStatusConnection_;
boost::bsignals::scoped_connection signOutConnection_;
boost::bsignals::scoped_connection uiEventConnection_;
};
}
diff --git a/Swift/Controllers/Roster/UnitTest/LeastCommonSubsequenceTest.cpp b/Swift/Controllers/Roster/UnitTest/LeastCommonSubsequenceTest.cpp
index 3acab12..963c5cd 100644
--- a/Swift/Controllers/Roster/UnitTest/LeastCommonSubsequenceTest.cpp
+++ b/Swift/Controllers/Roster/UnitTest/LeastCommonSubsequenceTest.cpp
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2011 Remko Tronçon
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
-#include <cppunit/extensions/HelperMacros.h>
-#include <cppunit/extensions/TestFactoryRegistry.h>
#include <boost/assign/list_of.hpp>
#include <functional>
#include <QA/Checker/IO.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
#include <Swift/Controllers/Roster/LeastCommonSubsequence.h>
using namespace Swift;
struct IsBOrC {
bool operator()(char c, char c2) const {
CPPUNIT_ASSERT_EQUAL(c, c2);
return c == 'b' || c == 'c';
}
diff --git a/Swift/Controllers/Roster/UnitTest/RosterControllerTest.cpp b/Swift/Controllers/Roster/UnitTest/RosterControllerTest.cpp
index ca74dbb..fbee894 100644
--- a/Swift/Controllers/Roster/UnitTest/RosterControllerTest.cpp
+++ b/Swift/Controllers/Roster/UnitTest/RosterControllerTest.cpp
@@ -25,23 +25,33 @@
#include "Swiften/Avatars/NullAvatarManager.h"
#include "Swift/Controllers/XMPPEvents/EventController.h"
#include "Swiften/Presence/PresenceOracle.h"
#include "Swiften/Presence/SubscriptionManager.h"
#include "Swiften/Client/NickResolver.h"
#include "Swift/Controllers/UIEvents/UIEventStream.h"
#include "Swift/Controllers/UIEvents/RenameRosterItemUIEvent.h"
#include "Swiften/MUC/MUCRegistry.h"
#include <Swiften/Client/DummyNickManager.h>
+#include <Swiften/Disco/EntityCapsManager.h>
+#include <Swiften/Disco/CapsProvider.h>
+#include <Swiften/Jingle/JingleSessionManager.h>
+#include <Swiften/FileTransfer/UnitTest/DummyFileTransferManager.h>
+#include <Swiften/Base/Algorithm.h>
+#include <Swiften/EventLoop/DummyEventLoop.h>
using namespace Swift;
#define CHILDREN mainWindow_->roster->getRoot()->getChildren()
+class DummyCapsProvider : public CapsProvider {
+ DiscoInfo::ref getCaps(const std::string&) const {return DiscoInfo::ref(new DiscoInfo());}
+};
+
class RosterControllerTest : public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(RosterControllerTest);
CPPUNIT_TEST(testAdd);
CPPUNIT_TEST(testAddSubscription);
CPPUNIT_TEST(testReceiveRename);
CPPUNIT_TEST(testReceiveRegroup);
CPPUNIT_TEST(testSendRename);
CPPUNIT_TEST(testPresence);
CPPUNIT_TEST(testHighestPresence);
@@ -60,24 +70,33 @@ class RosterControllerTest : public CppUnit::TestFixture {
channel_ = new DummyIQChannel();
router_ = new IQRouter(channel_);
stanzaChannel_ = new DummyStanzaChannel();
presenceOracle_ = new PresenceOracle(stanzaChannel_);
subscriptionManager_ = new SubscriptionManager(stanzaChannel_);
eventController_ = new EventController();
uiEventStream_ = new UIEventStream();
settings_ = new DummySettingsProvider();
nickManager_ = new DummyNickManager();
- rosterController_ = new RosterController(jid_, xmppRoster_, avatarManager_, mainWindowFactory_, nickManager_, nickResolver_, presenceOracle_, subscriptionManager_, eventController_, uiEventStream_, router_, settings_);
+ capsProvider_ = new DummyCapsProvider();
+ entityCapsManager_ = new EntityCapsManager(capsProvider_, stanzaChannel_);
+ jingleSessionManager_ = new JingleSessionManager(router_);
+
+ ftManager_ = new DummyFileTransferManager();
+ ftOverview_ = new FileTransferOverview(ftManager_);
+ rosterController_ = new RosterController(jid_, xmppRoster_, avatarManager_, mainWindowFactory_, nickManager_, nickResolver_, presenceOracle_, subscriptionManager_, eventController_, uiEventStream_, router_, settings_, entityCapsManager_, ftOverview_);
mainWindow_ = mainWindowFactory_->last;
};
void tearDown() {
delete rosterController_;
+ delete ftManager_;
+ delete jingleSessionManager_;
+
delete nickManager_;
delete nickResolver_;
delete mucRegistry_;
delete mainWindowFactory_;
delete avatarManager_;
delete router_;
delete channel_;
delete eventController_;
delete subscriptionManager_;
@@ -307,12 +326,17 @@ class RosterControllerTest : public CppUnit::TestFixture {
DummyIQChannel* channel_;
DummyStanzaChannel* stanzaChannel_;
IQRouter* router_;
PresenceOracle* presenceOracle_;
SubscriptionManager* subscriptionManager_;
EventController* eventController_;
UIEventStream* uiEventStream_;
MockMainWindow* mainWindow_;
DummySettingsProvider* settings_;
+ DummyCapsProvider* capsProvider_;
+ EntityCapsManager* entityCapsManager_;
+ JingleSessionManager* jingleSessionManager_;
+ FileTransferManager* ftManager_;
+ FileTransferOverview* ftOverview_;
};
CPPUNIT_TEST_SUITE_REGISTRATION(RosterControllerTest);
diff --git a/Swift/Controllers/SConscript b/Swift/Controllers/SConscript
index 031e93a..289f055 100644
--- a/Swift/Controllers/SConscript
+++ b/Swift/Controllers/SConscript
@@ -25,29 +25,34 @@ if env["SCONS_STAGE"] == "build" :
"Chat/ChatControllerBase.cpp",
"Chat/ChatsManager.cpp",
"Chat/MUCController.cpp",
"Chat/MUCSearchController.cpp",
"Chat/UserSearchController.cpp",
"DiscoServiceWalker.cpp",
"MainController.cpp",
"ProfileController.cpp",
"ContactEditController.cpp",
+ "FileTransfer/FileTransferController.cpp",
+ "FileTransfer/FileTransferOverview.cpp",
+ "FileTransfer/FileTransferProgressInfo.cpp",
+ "FileTransfer/SOCKS5BytestreamProxyFinder.cpp",
"Roster/RosterController.cpp",
"Roster/RosterGroupExpandinessPersister.cpp",
"Roster/ContactRosterItem.cpp",
"Roster/GroupRosterItem.cpp",
"Roster/RosterItem.cpp",
"Roster/Roster.cpp",
"Roster/TableRoster.cpp",
"EventWindowController.cpp",
"SoundEventController.cpp",
"SystemTrayController.cpp",
"XMLConsoleController.cpp",
+ "FileTransferListController.cpp",
"StatusTracker.cpp",
"PresenceNotifier.cpp",
"EventNotifier.cpp",
"AdHocManager.cpp",
"XMPPEvents/EventController.cpp",
"UIEvents/UIEvent.cpp",
"UIInterfaces/XMLConsoleWidget.cpp",
"UIInterfaces/ChatListWindow.cpp",
"PreviousStatusStore.cpp",
diff --git a/Swift/Controllers/UIEvents/RequestFileTransferListUIEvent.h b/Swift/Controllers/UIEvents/RequestFileTransferListUIEvent.h
new file mode 100644
index 0000000..aff6909
--- /dev/null
+++ b/Swift/Controllers/UIEvents/RequestFileTransferListUIEvent.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2011 Tobias Markmann
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include <Swift/Controllers/UIEvents/UIEvent.h>
+
+namespace Swift {
+
+class RequestFileTransferListUIEvent : public UIEvent {
+};
+
+}
diff --git a/Swift/Controllers/UIEvents/SendFileUIEvent.h b/Swift/Controllers/UIEvents/SendFileUIEvent.h
new file mode 100644
index 0000000..3bfa69d
--- /dev/null
+++ b/Swift/Controllers/UIEvents/SendFileUIEvent.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2011 Tobias Markmann
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include <string>
+
+#include <Swiften/JID/JID.h>
+#include <Swift/Controllers/UIEvents/UIEvent.h>
+
+namespace Swift {
+ class SendFileUIEvent : public UIEvent {
+ public:
+ typedef boost::shared_ptr<SendFileUIEvent> ref;
+
+ SendFileUIEvent(const JID& jid, const std::string& filename) : jid(jid), filename(filename) {
+ }
+
+ const JID& getJID() const {
+ return jid;
+ }
+
+ const std::string& getFilename() const {
+ return filename;
+ }
+
+ private:
+ JID jid;
+ std::string filename;
+ };
+}
diff --git a/Swift/Controllers/UIInterfaces/ChatWindow.h b/Swift/Controllers/UIInterfaces/ChatWindow.h
index faef5c8..b90efd9 100644
--- a/Swift/Controllers/UIInterfaces/ChatWindow.h
+++ b/Swift/Controllers/UIInterfaces/ChatWindow.h
@@ -18,39 +18,46 @@
#include "Swiften/Elements/ChatState.h"
namespace Swift {
class AvatarManager;
class TreeWidget;
class Roster;
class TabComplete;
class RosterItem;
class ContactRosterItem;
+ class FileTransferController;
class ChatWindow {
public:
enum AckState {Pending, Received, Failed};
enum Tristate {Yes, No, Maybe};
enum OccupantAction {Kick};
+ enum FileTransferState {WaitingForAccept, Negotiating, Transferring, Canceled, Finished, FTFailed};
ChatWindow() {}
virtual ~ChatWindow() {};
/** Add message to window.
* @return id of added message (for acks).
*/
virtual std::string addMessage(const std::string& message, const std::string& senderName, bool senderIsSelf, boost::shared_ptr<SecurityLabel> label, const std::string& avatarPath, const boost::posix_time::ptime& time) = 0;
/** Adds action to window.
* @return id of added message (for acks);
*/
virtual std::string addAction(const std::string& message, const std::string& senderName, bool senderIsSelf, boost::shared_ptr<SecurityLabel> label, const std::string& avatarPath, const boost::posix_time::ptime& time) = 0;
virtual void addSystemMessage(const std::string& message) = 0;
virtual void addPresenceMessage(const std::string& message) = 0;
virtual void addErrorMessage(const std::string& message) = 0;
virtual void replaceMessage(const std::string& message, const std::string& id, const boost::posix_time::ptime& time) = 0;
+
+ // File transfer related stuff
+ virtual std::string addFileTransfer(const std::string& senderName, bool senderIsSelf, const std::string& filename, const boost::uintmax_t sizeInBytes) = 0;
+ virtual void setFileTransferProgress(std::string, const int percentageDone) = 0;
+ virtual void setFileTransferStatus(std::string, const FileTransferState state, const std::string& msg = "") = 0;
virtual void setContactChatState(ChatState::ChatStateType state) = 0;
virtual void setName(const std::string& name) = 0;
virtual void show() = 0;
virtual void activate() = 0;
virtual void setAvailableSecurityLabels(const std::vector<SecurityLabelsCatalog::Item>& labels) = 0;
virtual void setSecurityLabelsEnabled(bool enabled) = 0;
virtual void setCorrectionEnabled(Tristate enabled) = 0;
virtual void setUnreadMessageCount(int count) = 0;
@@ -82,13 +89,19 @@ namespace Swift {
boost::signal<void ()> onClosed;
boost::signal<void ()> onAllMessagesRead;
boost::signal<void (const std::string&, bool isCorrection)> onSendMessageRequest;
boost::signal<void ()> onSendCorrectionMessageRequest;
boost::signal<void ()> onUserTyping;
boost::signal<void ()> onUserCancelsTyping;
boost::signal<void ()> onAlertButtonClicked;
boost::signal<void (ContactRosterItem*)> onOccupantSelectionChanged;
boost::signal<void (ChatWindow::OccupantAction, ContactRosterItem*)> onOccupantActionSelected;
+
+ // File transfer related
+ boost::signal<void (std::string /* id */)> onFileTransferCancel;
+ 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;
};
}
#endif
diff --git a/Swift/Controllers/UIInterfaces/FileTransferListWidget.h b/Swift/Controllers/UIInterfaces/FileTransferListWidget.h
new file mode 100644
index 0000000..01dcfd3
--- /dev/null
+++ b/Swift/Controllers/UIInterfaces/FileTransferListWidget.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2011 Tobias Markmann
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+namespace Swift {
+
+class FileTransferOverview;
+
+class FileTransferListWidget {
+public:
+ virtual ~FileTransferListWidget() {}
+
+ virtual void show() = 0;
+ virtual void activate() = 0;
+
+ virtual void setFileTransferOverview(FileTransferOverview*) = 0;
+};
+
+}
diff --git a/Swift/Controllers/UIInterfaces/FileTransferListWidgetFactory.h b/Swift/Controllers/UIInterfaces/FileTransferListWidgetFactory.h
new file mode 100644
index 0000000..0b08fb3
--- /dev/null
+++ b/Swift/Controllers/UIInterfaces/FileTransferListWidgetFactory.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2011 Tobias Markmann
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include "Swift/Controllers/UIInterfaces/FileTransferListWidget.h"
+
+namespace Swift {
+
+class FileTransferListWidgetFactory {
+public:
+ virtual ~FileTransferListWidgetFactory() {}
+
+ virtual FileTransferListWidget* createFileTransferListWidget() = 0;
+};
+
+}
diff --git a/Swift/Controllers/UIInterfaces/UIFactory.h b/Swift/Controllers/UIInterfaces/UIFactory.h
index 57f55d0..cf89dab 100644
--- a/Swift/Controllers/UIInterfaces/UIFactory.h
+++ b/Swift/Controllers/UIInterfaces/UIFactory.h
@@ -12,28 +12,30 @@
#include <Swift/Controllers/UIInterfaces/LoginWindowFactory.h>
#include <Swift/Controllers/UIInterfaces/MainWindowFactory.h>
#include <Swift/Controllers/UIInterfaces/MUCSearchWindowFactory.h>
#include <Swift/Controllers/UIInterfaces/JoinMUCWindowFactory.h>
#include <Swift/Controllers/UIInterfaces/UserSearchWindowFactory.h>
#include <Swift/Controllers/UIInterfaces/XMLConsoleWidgetFactory.h>
#include <Swift/Controllers/UIInterfaces/ProfileWindowFactory.h>
#include <Swift/Controllers/UIInterfaces/ContactEditWindowFactory.h>
#include <Swift/Controllers/UIInterfaces/AdHocCommandWindowFactory.h>
+#include <Swift/Controllers/UIInterfaces/FileTransferListWidgetFactory.h>
namespace Swift {
class UIFactory :
public ChatListWindowFactory,
public ChatWindowFactory,
public EventWindowFactory,
public LoginWindowFactory,
public MainWindowFactory,
public MUCSearchWindowFactory,
- public XMLConsoleWidgetFactory,
+ public XMLConsoleWidgetFactory,
public UserSearchWindowFactory,
public JoinMUCWindowFactory,
public ProfileWindowFactory,
public ContactEditWindowFactory,
- public AdHocCommandWindowFactory {
+ public AdHocCommandWindowFactory,
+ public FileTransferListWidgetFactory {
public:
virtual ~UIFactory() {}
};
}
diff --git a/Swift/Controllers/UnitTest/MockChatWindow.h b/Swift/Controllers/UnitTest/MockChatWindow.h
index 574248f..b410c69 100644
--- a/Swift/Controllers/UnitTest/MockChatWindow.h
+++ b/Swift/Controllers/UnitTest/MockChatWindow.h
@@ -14,18 +14,23 @@ namespace Swift {
MockChatWindow() : labelsEnabled_(false) {};
virtual ~MockChatWindow();
virtual std::string addMessage(const std::string& message, const std::string& /*senderName*/, bool /*senderIsSelf*/, boost::shared_ptr<SecurityLabel> /*label*/, const std::string& /*avatarPath*/, const boost::posix_time::ptime&) {lastMessageBody_ = message; return "";};
virtual std::string addAction(const std::string& message, const std::string& /*senderName*/, bool /*senderIsSelf*/, boost::shared_ptr<SecurityLabel> /*label*/, const std::string& /*avatarPath*/, const boost::posix_time::ptime&) {lastMessageBody_ = message; return "";};
virtual void addSystemMessage(const std::string& /*message*/) {};
virtual void addErrorMessage(const std::string& /*message*/) {};
virtual void addPresenceMessage(const std::string& /*message*/) {};
+ // File transfer related stuff
+ virtual std::string addFileTransfer(const std::string& /*senderName*/, bool /*senderIsSelf*/,const std::string& /*filename*/, const boost::uintmax_t /*sizeInBytes*/) { return 0; };
+ virtual void setFileTransferProgress(std::string /*id*/, const int /*alreadyTransferedBytes*/) { };
+ virtual void setFileTransferStatus(std::string /*id*/, const FileTransferState /*state*/, const std::string& /*msg*/) { };
+
virtual void setContactChatState(ChatState::ChatStateType /*state*/) {};
virtual void setName(const std::string& name) {name_ = name;};
virtual void show() {};
virtual void activate() {};
virtual void setAvailableSecurityLabels(const std::vector<SecurityLabelsCatalog::Item>& labels) {labels_ = labels;};
virtual void setSecurityLabelsEnabled(bool enabled) {labelsEnabled_ = enabled;};
virtual void setUnreadMessageCount(int /*count*/) {};
virtual void convertToMUC() {};
virtual void setSecurityLabelsError() {};
@@ -34,19 +39,19 @@ namespace Swift {
virtual void setRosterModel(Roster* /*roster*/) {};
virtual void setTabComplete(TabComplete*) {};
virtual void replaceLastMessage(const std::string&) {};
virtual void replaceMessage(const std::string&, const std::string&, const boost::posix_time::ptime&) {};
void setAckState(const std::string& /*id*/, AckState /*state*/) {};
virtual void flash() {};
virtual void setAlert(const std::string& /*alertText*/, const std::string& /*buttonText*/) {};
virtual void cancelAlert() {};
virtual void setCorrectionEnabled(Tristate /*enabled*/) {}
- void setAvailableOccupantActions(const std::vector<OccupantAction>& actions) {}
+ void setAvailableOccupantActions(const std::vector<OccupantAction>&/* actions*/) {}
boost::signal<void ()> onClosed;
boost::signal<void ()> onAllMessagesRead;
boost::signal<void (const std::string&, bool isCorrection)> onSendMessageRequest;
std::string name_;
std::string lastMessageBody_;
std::vector<SecurityLabelsCatalog::Item> labels_;
bool labelsEnabled_;