diff options
Diffstat (limited to 'Swift')
46 files changed, 448 insertions, 412 deletions
diff --git a/Swift/Controllers/Chat/ChatController.cpp b/Swift/Controllers/Chat/ChatController.cpp index 6056fc5..2e1b1c8 100644 --- a/Swift/Controllers/Chat/ChatController.cpp +++ b/Swift/Controllers/Chat/ChatController.cpp @@ -21,8 +21,8 @@ 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) - : ChatControllerBase(self, stanzaChannel, iqRouter, chatWindowFactory, contact, presenceOracle, avatarManager, useDelayForLatency) { +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) + : ChatControllerBase(self, stanzaChannel, iqRouter, chatWindowFactory, contact, presenceOracle, avatarManager, useDelayForLatency, eventStream) { isInMUC_ = isInMUC; chatStateNotifier_ = new ChatStateNotifier(); chatStateMessageSender_ = new ChatStateMessageSender(chatStateNotifier_, stanzaChannel, contact); diff --git a/Swift/Controllers/Chat/ChatController.h b/Swift/Controllers/Chat/ChatController.h index 3821a6e..7d2072d 100644 --- a/Swift/Controllers/Chat/ChatController.h +++ b/Swift/Controllers/Chat/ChatController.h @@ -17,7 +17,7 @@ namespace Swift { class NickResolver; 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); + 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); virtual void setToJID(const JID& jid); private: diff --git a/Swift/Controllers/Chat/ChatControllerBase.cpp b/Swift/Controllers/Chat/ChatControllerBase.cpp index f3e6bbe..5f27efb 100644 --- a/Swift/Controllers/Chat/ChatControllerBase.cpp +++ b/Swift/Controllers/Chat/ChatControllerBase.cpp @@ -22,8 +22,8 @@ namespace Swift { -ChatControllerBase::ChatControllerBase(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &toJID, PresenceOracle* presenceOracle, AvatarManager* avatarManager, bool useDelayForLatency) : selfJID_(self), stanzaChannel_(stanzaChannel), iqRouter_(iqRouter), chatWindowFactory_(chatWindowFactory), toJID_(toJID), labelsEnabled_(false), presenceOracle_(presenceOracle), avatarManager_(avatarManager), useDelayForLatency_(useDelayForLatency) { - chatWindow_ = chatWindowFactory_->createChatWindow(toJID); +ChatControllerBase::ChatControllerBase(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &toJID, PresenceOracle* presenceOracle, AvatarManager* avatarManager, bool useDelayForLatency, UIEventStream* eventStream) : selfJID_(self), stanzaChannel_(stanzaChannel), iqRouter_(iqRouter), chatWindowFactory_(chatWindowFactory), toJID_(toJID), labelsEnabled_(false), presenceOracle_(presenceOracle), avatarManager_(avatarManager), useDelayForLatency_(useDelayForLatency) { + chatWindow_ = chatWindowFactory_->createChatWindow(toJID, eventStream); chatWindow_->onAllMessagesRead.connect(boost::bind(&ChatControllerBase::handleAllMessagesRead, this)); chatWindow_->onSendMessageRequest.connect(boost::bind(&ChatControllerBase::handleSendMessageRequest, this, _1)); setEnabled(stanzaChannel->isAvailable() && iqRouter->isAvailable()); diff --git a/Swift/Controllers/Chat/ChatControllerBase.h b/Swift/Controllers/Chat/ChatControllerBase.h index 8317da8..f7cf087 100644 --- a/Swift/Controllers/Chat/ChatControllerBase.h +++ b/Swift/Controllers/Chat/ChatControllerBase.h @@ -28,6 +28,7 @@ namespace Swift { class ChatWindow; class ChatWindowFactory; class AvatarManager; + class UIEventStream; class ChatControllerBase { public: @@ -40,7 +41,7 @@ namespace Swift { void setEnabled(bool enabled); virtual void setToJID(const JID& jid) {toJID_ = jid;}; protected: - ChatControllerBase(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &toJID, PresenceOracle* presenceOracle, AvatarManager* avatarManager, bool useDelayForLatency); + ChatControllerBase(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &toJID, PresenceOracle* presenceOracle, AvatarManager* avatarManager, bool useDelayForLatency, UIEventStream* eventStream); virtual void postSendMessage(const String&) {}; virtual String senderDisplayNameFromMessage(const JID& from) = 0; diff --git a/Swift/Controllers/Chat/ChatsManager.cpp b/Swift/Controllers/Chat/ChatsManager.cpp index d0b4716..312af76 100644 --- a/Swift/Controllers/Chat/ChatsManager.cpp +++ b/Swift/Controllers/Chat/ChatsManager.cpp @@ -28,12 +28,11 @@ namespace Swift { typedef std::pair<JID, ChatController*> JIDChatControllerPair; typedef std::pair<JID, MUCController*> JIDMUCControllerPair; -ChatsManager::ChatsManager(JID jid, StanzaChannel* stanzaChannel, IQRouter* iqRouter, EventController* eventController, ChatWindowFactory* chatWindowFactory, TreeWidgetFactory* treeWidgetFactory, NickResolver* nickResolver, PresenceOracle* presenceOracle, boost::shared_ptr<DiscoInfo> serverDiscoInfo, PresenceSender* presenceSender, UIEventStream* uiEventStream, ChatListWindowFactory* chatListWindowFactory, bool useDelayForLatency) : jid_(jid), useDelayForLatency_(useDelayForLatency) { +ChatsManager::ChatsManager(JID jid, StanzaChannel* stanzaChannel, IQRouter* iqRouter, EventController* eventController, ChatWindowFactory* chatWindowFactory, NickResolver* nickResolver, PresenceOracle* presenceOracle, boost::shared_ptr<DiscoInfo> serverDiscoInfo, PresenceSender* presenceSender, UIEventStream* uiEventStream, ChatListWindowFactory* chatListWindowFactory, bool useDelayForLatency) : jid_(jid), useDelayForLatency_(useDelayForLatency) { eventController_ = eventController; stanzaChannel_ = stanzaChannel; iqRouter_ = iqRouter; chatWindowFactory_ = chatWindowFactory; - treeWidgetFactory_ = treeWidgetFactory; nickResolver_ = nickResolver; presenceOracle_ = presenceOracle; avatarManager_ = NULL; @@ -185,7 +184,7 @@ ChatController* ChatsManager::getChatControllerOrFindAnother(const JID &contact) } ChatController* ChatsManager::createNewChatController(const JID& contact) { - ChatController* controller = new ChatController(jid_, stanzaChannel_, iqRouter_, chatWindowFactory_, contact, nickResolver_, presenceOracle_, avatarManager_, isMUC(contact.toBare()), useDelayForLatency_); + ChatController* controller = new ChatController(jid_, stanzaChannel_, iqRouter_, chatWindowFactory_, contact, nickResolver_, presenceOracle_, avatarManager_, isMUC(contact.toBare()), useDelayForLatency_, uiEventStream_); chatControllers_[contact] = controller; controller->setAvailableServerFeatures(serverDiscoInfo_); return controller; @@ -221,7 +220,7 @@ void ChatsManager::handleJoinMUCRequest(const JID &muc, const boost::optional<St //FIXME: What's correct behaviour here? } else { String nick = nickMaybe ? nickMaybe.get() : "Swift user"; - MUCController* controller = new MUCController(jid_, muc, nick, stanzaChannel_, presenceSender_, iqRouter_, chatWindowFactory_, treeWidgetFactory_, presenceOracle_, avatarManager_, uiEventStream_, false); + MUCController* controller = new MUCController(jid_, muc, nick, stanzaChannel_, presenceSender_, iqRouter_, chatWindowFactory_, presenceOracle_, avatarManager_, uiEventStream_, false); mucControllers_[muc] = controller; controller->setAvailableServerFeatures(serverDiscoInfo_); controller->onUserLeft.connect(boost::bind(&ChatsManager::handleUserLeftMUC, this, controller)); diff --git a/Swift/Controllers/Chat/ChatsManager.h b/Swift/Controllers/Chat/ChatsManager.h index d45d81d..59d4ec3 100644 --- a/Swift/Controllers/Chat/ChatsManager.h +++ b/Swift/Controllers/Chat/ChatsManager.h @@ -24,7 +24,6 @@ namespace Swift { class ChatController; class MUCController; class ChatWindowFactory; - class TreeWidgetFactory; class NickResolver; class PresenceOracle; class AvatarManager; @@ -37,14 +36,14 @@ namespace Swift { class ChatsManager : public MUCRegistry { public: - ChatsManager(JID jid, StanzaChannel* stanzaChannel, IQRouter* iqRouter, EventController* eventController, ChatWindowFactory* chatWindowFactory, TreeWidgetFactory* treeWidgetFactory, NickResolver* nickResolver, PresenceOracle* presenceOracle, boost::shared_ptr<DiscoInfo> serverDiscoInfo, PresenceSender* presenceSender, UIEventStream* uiEventStream, ChatListWindowFactory* chatListWindowFactory, bool useDelayForLatency); + ChatsManager(JID jid, StanzaChannel* stanzaChannel, IQRouter* iqRouter, EventController* eventController, ChatWindowFactory* chatWindowFactory, NickResolver* nickResolver, PresenceOracle* presenceOracle, boost::shared_ptr<DiscoInfo> serverDiscoInfo, PresenceSender* presenceSender, UIEventStream* uiEventStream, ChatListWindowFactory* chatListWindowFactory, bool useDelayForLatency); ~ChatsManager(); void setAvatarManager(AvatarManager* avatarManager); void setEnabled(bool enabled); void setServerDiscoInfo(boost::shared_ptr<DiscoInfo> info); void handleIncomingMessage(boost::shared_ptr<Message> message); - void handleChatRequest(const String& contact); private: + void handleChatRequest(const String& contact); void handleJoinMUCRequest(const JID& muc, const boost::optional<String>& nick); void rebindControllerJID(const JID& from, const JID& to); void handlePresenceChange(boost::shared_ptr<Presence> newPresence, boost::shared_ptr<Presence> lastPresence); @@ -65,7 +64,6 @@ namespace Swift { StanzaChannel* stanzaChannel_; IQRouter* iqRouter_;; ChatWindowFactory* chatWindowFactory_; - TreeWidgetFactory* treeWidgetFactory_; NickResolver* nickResolver_; PresenceOracle* presenceOracle_; AvatarManager* avatarManager_; diff --git a/Swift/Controllers/Chat/MUCController.cpp b/Swift/Controllers/Chat/MUCController.cpp index 737ad82..7e9a9ea 100644 --- a/Swift/Controllers/Chat/MUCController.cpp +++ b/Swift/Controllers/Chat/MUCController.cpp @@ -17,10 +17,8 @@ #include "Swiften/MUC/MUC.h" #include "Swiften/Client/StanzaChannel.h" #include "Swiften/Roster/Roster.h" -#include "Swiften/Roster/OpenChatRosterAction.h" #include "Swiften/Roster/SetAvatar.h" #include "Swiften/Roster/SetPresence.h" -#include "Swiften/Roster/TreeWidgetFactory.h" namespace Swift { @@ -35,19 +33,17 @@ MUCController::MUCController ( PresenceSender* presenceSender, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, - TreeWidgetFactory *treeWidgetFactory, PresenceOracle* presenceOracle, AvatarManager* avatarManager, UIEventStream* uiEventStream, bool useDelayForLatency) : - ChatControllerBase(self, stanzaChannel, iqRouter, chatWindowFactory, muc, presenceOracle, avatarManager, useDelayForLatency), + ChatControllerBase(self, stanzaChannel, iqRouter, chatWindowFactory, muc, presenceOracle, avatarManager, useDelayForLatency, uiEventStream), muc_(new MUC(stanzaChannel, presenceSender, muc)), - nick_(nick), - treeWidgetFactory_(treeWidgetFactory) { + nick_(nick) { parting_ = false; events_ = uiEventStream; - roster_ = new Roster(chatWindow_->getTreeWidget(), treeWidgetFactory_); - roster_->onUserAction.connect(boost::bind(&MUCController::handleUserAction, this, _1)); + roster_ = new Roster(); + chatWindow_->setRosterModel(roster_); chatWindow_->onClosed.connect(boost::bind(&MUCController::handleWindowClosed, this)); muc_->joinAs(nick); muc_->onOccupantJoined.connect(boost::bind(&MUCController::handleOccupantJoined, this, _1)); @@ -61,19 +57,10 @@ MUCController::MUCController ( MUCController::~MUCController() { delete muc_; + chatWindow_->setRosterModel(NULL); delete roster_; } -void MUCController::handleUserAction(boost::shared_ptr<UserRosterAction> action) { - boost::shared_ptr<OpenChatRosterAction> chatAction = boost::dynamic_pointer_cast<OpenChatRosterAction>(action); - if (chatAction.get() != NULL) { - ContactRosterItem *contactItem = dynamic_cast<ContactRosterItem*>(chatAction->getRosterItem()); - assert(contactItem); - events_->send(boost::shared_ptr<RequestChatUIEvent>(new RequestChatUIEvent(contactItem->getJID()))); - return; - } -} - void MUCController::handleAvatarChanged(const JID& jid, const String&) { if (parting_) { return; diff --git a/Swift/Controllers/Chat/MUCController.h b/Swift/Controllers/Chat/MUCController.h index 2252357..8e6e01b 100644 --- a/Swift/Controllers/Chat/MUCController.h +++ b/Swift/Controllers/Chat/MUCController.h @@ -15,7 +15,6 @@ #include "Swift/Controllers/Chat/ChatControllerBase.h" #include "Swiften/Elements/Message.h" #include "Swiften/Elements/DiscoInfo.h" -#include "Swiften/Roster/UserRosterAction.h" #include "Swiften/JID/JID.h" #include "Swiften/MUC/MUC.h" #include "Swiften/MUC/MUCOccupant.h" @@ -26,13 +25,12 @@ namespace Swift { class ChatWindow; class ChatWindowFactory; class Roster; - class TreeWidgetFactory; class AvatarManager; class UIEventStream; class MUCController : public ChatControllerBase { public: - MUCController(const JID& self, const JID &muc, const String &nick, StanzaChannel* stanzaChannel, PresenceSender* presenceSender, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, TreeWidgetFactory *treeWidgetFactory, PresenceOracle* presenceOracle, AvatarManager* avatarManager, UIEventStream* events, bool useDelayForLatency); + MUCController(const JID& self, const JID &muc, const String &nick, StanzaChannel* stanzaChannel, PresenceSender* presenceSender, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, PresenceOracle* presenceOracle, AvatarManager* avatarManager, UIEventStream* events, bool useDelayForLatency); ~MUCController(); boost::signal<void ()> onUserLeft; @@ -47,13 +45,11 @@ namespace Swift { void handleOccupantJoined(const MUCOccupant& occupant); void handleOccupantLeft(const MUCOccupant& occupant, MUC::LeavingType type, const String& reason); void handleOccupantPresenceChange(boost::shared_ptr<Presence> presence); - void handleUserAction(boost::shared_ptr<UserRosterAction> action); private: MUC* muc_; UIEventStream* events_; String nick_; - TreeWidgetFactory* treeWidgetFactory_; Roster* roster_; bool parting_; boost::bsignals::scoped_connection avatarChangedConnection_; diff --git a/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp b/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp index 5caedab..f671fb1 100644 --- a/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp +++ b/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp @@ -13,7 +13,6 @@ #include "Swift/Controllers/UIInterfaces/ChatWindow.h" #include "Swift/Controllers/UIInterfaces/ChatWindowFactory.h" #include "Swift/Controllers/UIInterfaces/ChatListWindowFactory.h" -#include "Swiften/Roster/TreeWidgetFactory.h" #include "Swiften/Client/Client.h" #include "Swift/Controllers/Chat/ChatController.h" #include "Swift/Controllers/EventController.h" @@ -26,6 +25,7 @@ #include "Swiften/Client/DummyStanzaChannel.h" #include "Swiften/Queries/DummyIQChannel.h" #include "Swiften/Presence/PresenceOracle.h" +#include "Swift/Controllers/UIEvents/RequestChatUIEvent.h" #include "Swift/Controllers/UIEvents/UIEventStream.h" @@ -54,7 +54,6 @@ public: iqRouter_ = new IQRouter(iqChannel_); eventController_ = new EventController(); chatWindowFactory_ = mocks_->InterfaceMock<ChatWindowFactory>(); - treeWidgetFactory_ = NULL; xmppRoster_ = boost::shared_ptr<XMPPRoster>(new XMPPRoster()); nickResolver_ = new NickResolver(xmppRoster_); presenceOracle_ = new PresenceOracle(stanzaChannel_); @@ -63,7 +62,7 @@ public: uiEventStream_ = new UIEventStream(); chatListWindowFactory_ = mocks_->InterfaceMock<ChatListWindowFactory>(); mocks_->ExpectCall(chatListWindowFactory_, ChatListWindowFactory::createWindow).With(uiEventStream_).Return(NULL); - manager_ = new ChatsManager(jid_, stanzaChannel_, iqRouter_, eventController_, chatWindowFactory_, treeWidgetFactory_, nickResolver_, presenceOracle_, serverDiscoInfo_, presenceSender_, uiEventStream_, chatListWindowFactory_, true); + manager_ = new ChatsManager(jid_, stanzaChannel_, iqRouter_, eventController_, chatWindowFactory_, nickResolver_, presenceOracle_, serverDiscoInfo_, presenceSender_, uiEventStream_, chatListWindowFactory_, true); avatarManager_ = new MockAvatarManager(); manager_->setAvatarManager(avatarManager_); }; @@ -74,7 +73,6 @@ public: delete presenceSender_; delete presenceOracle_; delete nickResolver_; - delete treeWidgetFactory_; delete stanzaChannel_; delete eventController_; delete iqChannel_; @@ -87,7 +85,7 @@ public: JID messageJID("testling@test.com/resource1"); MockChatWindow* window = new MockChatWindow();//mocks_->InterfaceMock<ChatWindow>(); - mocks_->ExpectCall(chatWindowFactory_, ChatWindowFactory::createChatWindow).With(messageJID).Return(window); + mocks_->ExpectCall(chatWindowFactory_, ChatWindowFactory::createChatWindow).With(messageJID, uiEventStream_).Return(window); boost::shared_ptr<Message> message(new Message()); message->setFrom(messageJID); @@ -101,7 +99,7 @@ public: JID messageJID1("testling@test.com/resource1"); MockChatWindow* window1 = new MockChatWindow();//mocks_->InterfaceMock<ChatWindow>(); - mocks_->ExpectCall(chatWindowFactory_, ChatWindowFactory::createChatWindow).With(messageJID1).Return(window1); + mocks_->ExpectCall(chatWindowFactory_, ChatWindowFactory::createChatWindow).With(messageJID1, uiEventStream_).Return(window1); boost::shared_ptr<Message> message1(new Message()); message1->setFrom(messageJID1); @@ -113,7 +111,7 @@ public: JID messageJID2("testling@test.com/resource2"); MockChatWindow* window2 = new MockChatWindow();//mocks_->InterfaceMock<ChatWindow>(); - mocks_->ExpectCall(chatWindowFactory_, ChatWindowFactory::createChatWindow).With(messageJID2).Return(window2); + mocks_->ExpectCall(chatWindowFactory_, ChatWindowFactory::createChatWindow).With(messageJID2, uiEventStream_).Return(window2); boost::shared_ptr<Message> message2(new Message()); message2->setFrom(messageJID2); @@ -127,9 +125,9 @@ public: String messageJIDString("testling@test.com"); ChatWindow* window = new MockChatWindow();//mocks_->InterfaceMock<ChatWindow>(); - mocks_->ExpectCall(chatWindowFactory_, ChatWindowFactory::createChatWindow).With(JID(messageJIDString)).Return(window); - - manager_->handleChatRequest(messageJIDString); + mocks_->ExpectCall(chatWindowFactory_, ChatWindowFactory::createChatWindow).With(JID(messageJIDString), uiEventStream_).Return(window); + + uiEventStream_->send(boost::shared_ptr<UIEvent>(new RequestChatUIEvent(JID(messageJIDString)))); } @@ -138,8 +136,8 @@ public: String fullJIDString("testling@test.com/resource1"); MockChatWindow* window = new MockChatWindow();//mocks_->InterfaceMock<ChatWindow>(); - mocks_->ExpectCall(chatWindowFactory_, ChatWindowFactory::createChatWindow).With(JID(bareJIDString)).Return(window); - manager_->handleChatRequest(bareJIDString); + mocks_->ExpectCall(chatWindowFactory_, ChatWindowFactory::createChatWindow).With(JID(bareJIDString), uiEventStream_).Return(window); + uiEventStream_->send(boost::shared_ptr<UIEvent>(new RequestChatUIEvent(JID(bareJIDString)))); boost::shared_ptr<Message> message(new Message()); message->setFrom(JID(fullJIDString)); @@ -152,14 +150,14 @@ public: void testSecondWindow() { String messageJIDString1("testling1@test.com"); ChatWindow* window1 = new MockChatWindow();//mocks_->InterfaceMock<ChatWindow>(); - mocks_->ExpectCall(chatWindowFactory_, ChatWindowFactory::createChatWindow).With(JID(messageJIDString1)).Return(window1); - manager_->handleChatRequest(messageJIDString1); + mocks_->ExpectCall(chatWindowFactory_, ChatWindowFactory::createChatWindow).With(JID(messageJIDString1), uiEventStream_).Return(window1); + uiEventStream_->send(boost::shared_ptr<UIEvent>(new RequestChatUIEvent(JID(messageJIDString1)))); String messageJIDString2("testling2@test.com"); ChatWindow* window2 = new MockChatWindow();//mocks_->InterfaceMock<ChatWindow>(); - mocks_->ExpectCall(chatWindowFactory_, ChatWindowFactory::createChatWindow).With(JID(messageJIDString2)).Return(window2); + mocks_->ExpectCall(chatWindowFactory_, ChatWindowFactory::createChatWindow).With(JID(messageJIDString2), uiEventStream_).Return(window2); - manager_->handleChatRequest(messageJIDString2); + uiEventStream_->send(boost::shared_ptr<UIEvent>(new RequestChatUIEvent(JID(messageJIDString2)))); } /** Complete cycle. @@ -174,8 +172,8 @@ public: String fullJIDString2("testling@test.com/resource2"); MockChatWindow* window = new MockChatWindow();//mocks_->InterfaceMock<ChatWindow>(); - mocks_->ExpectCall(chatWindowFactory_, ChatWindowFactory::createChatWindow).With(JID(bareJIDString)).Return(window); - manager_->handleChatRequest(bareJIDString); + mocks_->ExpectCall(chatWindowFactory_, ChatWindowFactory::createChatWindow).With(JID(bareJIDString), uiEventStream_).Return(window); + uiEventStream_->send(boost::shared_ptr<UIEvent>(new RequestChatUIEvent(JID(bareJIDString)))); boost::shared_ptr<Message> message1(new Message()); message1->setFrom(JID(fullJIDString1)); @@ -212,7 +210,7 @@ public: JID messageJID1("testling@test.com/resource1"); MockChatWindow* window1 = new MockChatWindow();//mocks_->InterfaceMock<ChatWindow>(); - mocks_->ExpectCall(chatWindowFactory_, ChatWindowFactory::createChatWindow).With(messageJID1).Return(window1); + mocks_->ExpectCall(chatWindowFactory_, ChatWindowFactory::createChatWindow).With(messageJID1, uiEventStream_).Return(window1); boost::shared_ptr<Message> message1(new Message()); message1->setFrom(messageJID1); @@ -222,7 +220,7 @@ public: JID messageJID2("testling@test.com/resource2"); MockChatWindow* window2 = new MockChatWindow();//mocks_->InterfaceMock<ChatWindow>(); - mocks_->ExpectCall(chatWindowFactory_, ChatWindowFactory::createChatWindow).With(messageJID2).Return(window2); + mocks_->ExpectCall(chatWindowFactory_, ChatWindowFactory::createChatWindow).With(messageJID2, uiEventStream_).Return(window2); boost::shared_ptr<Message> message2(new Message()); message2->setFrom(messageJID2); @@ -268,7 +266,6 @@ private: IQRouter* iqRouter_; EventController* eventController_; ChatWindowFactory* chatWindowFactory_; - TreeWidgetFactory* treeWidgetFactory_; NickResolver* nickResolver_; PresenceOracle* presenceOracle_; AvatarManager* avatarManager_; diff --git a/Swift/Controllers/MainController.cpp b/Swift/Controllers/MainController.cpp index 3656de3..e6dfe47 100644 --- a/Swift/Controllers/MainController.cpp +++ b/Swift/Controllers/MainController.cpp @@ -42,7 +42,6 @@ #include "Swiften/Elements/Presence.h" #include "Swiften/Elements/VCardUpdate.h" #include "Swiften/Queries/Responders/SoftwareVersionResponder.h" -#include "Swiften/Roster/TreeWidgetFactory.h" #include "Swiften/Settings/SettingsProvider.h" #include "Swiften/Elements/DiscoInfo.h" #include "Swiften/Queries/Responders/DiscoInfoResponder.h" @@ -61,8 +60,8 @@ static const String CLIENT_VERSION = "0.3"; static const String CLIENT_NODE = "http://swift.im"; -MainController::MainController(ChatWindowFactory* chatWindowFactory, MainWindowFactory *mainWindowFactory, LoginWindowFactory *loginWindowFactory, TreeWidgetFactory *treeWidgetFactory, EventWindowFactory* eventWindowFactory, SettingsProvider *settings, Application* application, SystemTray* systemTray, SoundPlayer* soundPlayer, XMLConsoleWidgetFactory* xmlConsoleWidgetFactory, ChatListWindowFactory* chatListWindowFactory, bool useDelayForLatency) - : timerFactory_(&boostIOServiceThread_.getIOService()), idleDetector_(&idleQuerier_, &timerFactory_, 100), chatWindowFactory_(chatWindowFactory), mainWindowFactory_(mainWindowFactory), loginWindowFactory_(loginWindowFactory), treeWidgetFactory_(treeWidgetFactory), settings_(settings), loginWindow_(NULL), useDelayForLatency_(useDelayForLatency) { +MainController::MainController(ChatWindowFactory* chatWindowFactory, MainWindowFactory *mainWindowFactory, LoginWindowFactory *loginWindowFactory, EventWindowFactory* eventWindowFactory, SettingsProvider *settings, Application* application, SystemTray* systemTray, SoundPlayer* soundPlayer, XMLConsoleWidgetFactory* xmlConsoleWidgetFactory, ChatListWindowFactory* chatListWindowFactory, bool useDelayForLatency) + : timerFactory_(&boostIOServiceThread_.getIOService()), idleDetector_(&idleQuerier_, &timerFactory_, 100), chatWindowFactory_(chatWindowFactory), mainWindowFactory_(mainWindowFactory), loginWindowFactory_(loginWindowFactory), settings_(settings), loginWindow_(NULL), useDelayForLatency_(useDelayForLatency) { application_ = application; presenceOracle_ = NULL; avatarManager_ = NULL; @@ -176,15 +175,14 @@ void MainController::handleConnected() { avatarManager_ = new AvatarManager(client_, client_, avatarStorage_); - rosterController_ = new RosterController(jid_, xmppRoster_, avatarManager_, mainWindowFactory_, treeWidgetFactory_, nickResolver_, presenceOracle_, eventController_, uiEventStream_, client_); + rosterController_ = new RosterController(jid_, xmppRoster_, avatarManager_, mainWindowFactory_, nickResolver_, presenceOracle_, eventController_, uiEventStream_, client_); rosterController_->onChangeStatusRequest.connect(boost::bind(&MainController::handleChangeStatusRequest, this, _1, _2)); rosterController_->onSignOutRequest.connect(boost::bind(&MainController::signOut, this)); - chatsManager_ = new ChatsManager(jid_, client_, client_, eventController_, chatWindowFactory_, treeWidgetFactory_, nickResolver_, presenceOracle_, serverDiscoInfo_, presenceSender_, uiEventStream_, chatListWindowFactory_, useDelayForLatency_); + chatsManager_ = new ChatsManager(jid_, client_, client_, eventController_, chatWindowFactory_, nickResolver_, presenceOracle_, serverDiscoInfo_, presenceSender_, uiEventStream_, chatListWindowFactory_, useDelayForLatency_); nickResolver_->setMUCRegistry(chatsManager_); client_->onMessageReceived.connect(boost::bind(&ChatsManager::handleIncomingMessage, chatsManager_, _1)); chatsManager_->setAvatarManager(avatarManager_); - rosterController_->onStartChatRequest.connect(boost::bind(&ChatsManager::handleChatRequest, chatsManager_, _1)); avatarManager_->setMUCRegistry(chatsManager_); diff --git a/Swift/Controllers/MainController.h b/Swift/Controllers/MainController.h index 2ed922c..5d3f998 100644 --- a/Swift/Controllers/MainController.h +++ b/Swift/Controllers/MainController.h @@ -47,7 +47,6 @@ namespace Swift { class EventLoop; class SoftwareVersionResponder; class LoginWindowFactory; - class TreeWidgetFactory; class MUCController; class PresenceOracle; class SystemTray; @@ -62,7 +61,7 @@ namespace Swift { class MainController { public: - MainController(ChatWindowFactory* chatWindowFactory, MainWindowFactory *mainWindowFactory, LoginWindowFactory *loginWindowFactory, TreeWidgetFactory* treeWidgetFactory, EventWindowFactory* eventWindowFactory, SettingsProvider *settings, Application* application, SystemTray* systemTray, SoundPlayer* soundPlayer, XMLConsoleWidgetFactory* xmlConsoleWidgetFactory, ChatListWindowFactory* chatListWindowFactory_, bool useDelayForLatency); + MainController(ChatWindowFactory* chatWindowFactory, MainWindowFactory *mainWindowFactory, LoginWindowFactory *loginWindowFactory, EventWindowFactory* eventWindowFactory, SettingsProvider *settings, Application* application, SystemTray* systemTray, SoundPlayer* soundPlayer, XMLConsoleWidgetFactory* xmlConsoleWidgetFactory, ChatListWindowFactory* chatListWindowFactory_, bool useDelayForLatency); ~MainController(); @@ -94,7 +93,6 @@ namespace Swift { ChatWindowFactory* chatWindowFactory_; MainWindowFactory* mainWindowFactory_; LoginWindowFactory* loginWindowFactory_; - TreeWidgetFactory* treeWidgetFactory_; EventWindowFactory* eventWindowFactory_; SettingsProvider *settings_; Application* application_; diff --git a/Swift/Controllers/RosterController.cpp b/Swift/Controllers/RosterController.cpp index 3bbc9f8..4738d76 100644 --- a/Swift/Controllers/RosterController.cpp +++ b/Swift/Controllers/RosterController.cpp @@ -25,11 +25,9 @@ #include "Swiften/Roster/SetAvatar.h" #include "Swiften/Roster/SetName.h" #include "Swiften/Roster/OfflineRosterFilter.h" -#include "Swiften/Roster/OpenChatRosterAction.h" -#include "Swiften/Roster/TreeWidgetFactory.h" #include "Swiften/Roster/XMPPRoster.h" #include "Swift/Controllers/UIEvents/AddContactUIEvent.h" -#include "Swift/Controllers/UIEvents/RemoveItemRosterAction.h" +#include "Swift/Controllers/UIEvents/RemoveRosterItemUIEvent.h" namespace Swift { @@ -37,17 +35,17 @@ namespace Swift { /** * The controller does not gain ownership of these parameters. */ -RosterController::RosterController(const JID& jid, boost::shared_ptr<XMPPRoster> xmppRoster, AvatarManager* avatarManager, MainWindowFactory* mainWindowFactory, TreeWidgetFactory* treeWidgetFactory, NickResolver* nickResolver, PresenceOracle* presenceOracle, EventController* eventController, UIEventStream* uiEventStream, IQRouter* iqRouter) - : myJID_(jid), xmppRoster_(xmppRoster), mainWindowFactory_(mainWindowFactory), treeWidgetFactory_(treeWidgetFactory), mainWindow_(mainWindowFactory_->createMainWindow(uiEventStream)), roster_(new Roster(mainWindow_->getTreeWidget(), treeWidgetFactory_)), offlineFilter_(new OfflineRosterFilter()) { +RosterController::RosterController(const JID& jid, boost::shared_ptr<XMPPRoster> xmppRoster, AvatarManager* avatarManager, MainWindowFactory* mainWindowFactory, NickResolver* nickResolver, PresenceOracle* presenceOracle, EventController* eventController, UIEventStream* uiEventStream, IQRouter* iqRouter) + : myJID_(jid), xmppRoster_(xmppRoster), mainWindowFactory_(mainWindowFactory), mainWindow_(mainWindowFactory_->createMainWindow(uiEventStream)), roster_(new Roster()), offlineFilter_(new OfflineRosterFilter()) { iqRouter_ = iqRouter; presenceOracle_ = presenceOracle; eventController_ = eventController; roster_->addFilter(offlineFilter_); + mainWindow_->setRosterModel(roster_); changeStatusConnection_ = mainWindow_->onChangeStatusRequest.connect(boost::bind(&RosterController::handleChangeStatusRequest, this, _1, _2)); showOfflineConnection_ = mainWindow_->onShowOfflineToggled.connect(boost::bind(&RosterController::handleShowOfflineToggled, this, _1)); signOutConnection_ = mainWindow_->onSignOutRequest.connect(boost::bind(boost::ref(onSignOutRequest))); - roster_->onUserAction.connect(boost::bind(&RosterController::handleUserAction, this, _1)); xmppRoster_->onJIDAdded.connect(boost::bind(&RosterController::handleOnJIDAdded, this, _1)); xmppRoster_->onJIDUpdated.connect(boost::bind(&RosterController::handleOnJIDUpdated, this, _1, _2, _3)); xmppRoster_->onJIDRemoved.connect(boost::bind(&RosterController::handleOnJIDRemoved, this, _1)); @@ -101,31 +99,6 @@ void RosterController::handleChangeStatusRequest(StatusShow::Type show, const St onChangeStatusRequest(show, statusText); } -void RosterController::handleUserAction(boost::shared_ptr<UserRosterAction> action) { - boost::shared_ptr<OpenChatRosterAction> chatAction = boost::dynamic_pointer_cast<OpenChatRosterAction>(action); - if (chatAction) { - ContactRosterItem *contactItem = dynamic_cast<ContactRosterItem*>(chatAction->getRosterItem()); - assert(contactItem); - onStartChatRequest(contactItem->getJID().toBare()); - return; - } - - boost::shared_ptr<RemoveItemRosterAction> removeAction = boost::dynamic_pointer_cast<RemoveItemRosterAction>(action); - if (removeAction) { - ContactRosterItem *contactItem = dynamic_cast<ContactRosterItem*>(removeAction->getRosterItem()); - assert(contactItem); - - RosterItemPayload item(contactItem->getJID(), "", RosterItemPayload::Remove); - boost::shared_ptr<RosterPayload> roster(new RosterPayload()); - roster->addItem(item); - boost::shared_ptr<SetRosterRequest> request(new SetRosterRequest(roster, iqRouter_)); - request->onResponse.connect(boost::bind(&RosterController::handleRosterSetError, this, _1, roster)); - request->send(); - - return; - } -} - void RosterController::handleOnJIDAdded(const JID& jid) { std::vector<String> groups = xmppRoster_->getGroupsForJID(jid); String name = xmppRoster_->getNameForJID(jid); @@ -182,7 +155,20 @@ void RosterController::handleUIEvent(boost::shared_ptr<UIEvent> event) { request->onResponse.connect(boost::bind(&RosterController::handleRosterSetError, this, _1, roster)); request->send(); presenceOracle_->requestSubscription(addContactEvent->getJID()); + return; } + boost::shared_ptr<RemoveRosterItemUIEvent> removeEvent = boost::dynamic_pointer_cast<RemoveRosterItemUIEvent>(event); + if (removeEvent) { + RosterItemPayload item(removeEvent->getJID(), "", RosterItemPayload::Remove); + boost::shared_ptr<RosterPayload> roster(new RosterPayload()); + roster->addItem(item); + boost::shared_ptr<SetRosterRequest> request(new SetRosterRequest(roster, iqRouter_)); + request->onResponse.connect(boost::bind(&RosterController::handleRosterSetError, this, _1, roster)); + request->send(); + + return; + } + } void RosterController::handleRosterSetError(boost::optional<ErrorPayload> error, boost::shared_ptr<RosterPayload> rosterPayload) { diff --git a/Swift/Controllers/RosterController.h b/Swift/Controllers/RosterController.h index e9561bb..eca4e33 100644 --- a/Swift/Controllers/RosterController.h +++ b/Swift/Controllers/RosterController.h @@ -11,7 +11,6 @@ #include "Swiften/Base/String.h" #include "Swiften/Elements/Presence.h" #include "Swiften/Elements/RosterPayload.h" -#include "Swiften/Roster/UserRosterAction.h" #include "Swiften/Avatars/AvatarManager.h" #include "Swift/Controllers/UIEvents/UIEvent.h" @@ -24,7 +23,6 @@ namespace Swift { class XMPPRoster; class MainWindow; class MainWindowFactory; - class TreeWidgetFactory; class OfflineRosterFilter; class NickResolver; class PresenceOracle; @@ -35,13 +33,12 @@ namespace Swift { class RosterController { public: - RosterController(const JID& jid, boost::shared_ptr<XMPPRoster> xmppRoster, AvatarManager* avatarManager, MainWindowFactory* mainWindowFactory, TreeWidgetFactory* treeWidgetFactory, NickResolver* nickResolver, PresenceOracle* presenceOracle, EventController* eventController, UIEventStream* uiEventStream, IQRouter* iqRouter_); + RosterController(const JID& jid, boost::shared_ptr<XMPPRoster> xmppRoster, AvatarManager* avatarManager, MainWindowFactory* mainWindowFactory, NickResolver* nickResolver, PresenceOracle* presenceOracle, EventController* eventController, UIEventStream* uiEventStream, IQRouter* iqRouter_); ~RosterController(); void showRosterWindow(); MainWindow* getWindow() {return mainWindow_;}; void setAvatarManager(AvatarManager* avatarManager); void setNickResolver(NickResolver* nickResolver); - boost::signal<void (const JID&)> onStartChatRequest; boost::signal<void (StatusShow::Type, const String&)> onChangeStatusRequest; boost::signal<void ()> onSignOutRequest; void handleAvatarChanged(const JID& jid, const String& hash); @@ -51,7 +48,6 @@ namespace Swift { void handleOnJIDRemoved(const JID &jid); void handleOnJIDUpdated(const JID &jid, const String& oldName, const std::vector<String> oldGroups); void handleStartChatRequest(const JID& contact); - void handleUserAction(boost::shared_ptr<UserRosterAction> action); void handleChangeStatusRequest(StatusShow::Type show, const String &statusText); void handleShowOfflineToggled(bool state); void handleIncomingPresence(boost::shared_ptr<Presence> newPresence, boost::shared_ptr<Presence> oldPresence); @@ -63,7 +59,6 @@ namespace Swift { JID myJID_; boost::shared_ptr<XMPPRoster> xmppRoster_; MainWindowFactory* mainWindowFactory_; - TreeWidgetFactory* treeWidgetFactory_; MainWindow* mainWindow_; Roster* roster_; OfflineRosterFilter* offlineFilter_; diff --git a/Swift/Controllers/UIEvents/RemoveItemRosterAction.h b/Swift/Controllers/UIEvents/RemoveItemRosterAction.h deleted file mode 100644 index 751e248..0000000 --- a/Swift/Controllers/UIEvents/RemoveItemRosterAction.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * 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/Roster/UserRosterAction.h" - -namespace Swift { -class RosterItem; -class TreeWidgetItem; - -class RemoveItemRosterAction : public UserRosterAction { - public: - virtual ~RemoveItemRosterAction() {}; - -}; - -} diff --git a/Swift/Controllers/UIEvents/RemoveRosterItemUIEvent.h b/Swift/Controllers/UIEvents/RemoveRosterItemUIEvent.h new file mode 100644 index 0000000..7e5236a --- /dev/null +++ b/Swift/Controllers/UIEvents/RemoveRosterItemUIEvent.h @@ -0,0 +1,24 @@ +/* + * 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 "Swift/Controllers/UIEvents/UIEvent.h" + +namespace Swift { + +class RemoveRosterItemUIEvent : public UIEvent { + public: + RemoveRosterItemUIEvent(const JID& jid) : jid_(jid) {}; + virtual ~RemoveRosterItemUIEvent() {}; + JID getJID() {return jid_;}; + private: + JID jid_; + +}; + +} diff --git a/Swift/Controllers/UIInterfaces/ChatWindow.h b/Swift/Controllers/UIInterfaces/ChatWindow.h index 0463508..33133f3 100644 --- a/Swift/Controllers/UIInterfaces/ChatWindow.h +++ b/Swift/Controllers/UIInterfaces/ChatWindow.h @@ -19,6 +19,7 @@ namespace Swift { class AvatarManager; class TreeWidget; + class Roster; class ChatWindow { public: @@ -38,10 +39,11 @@ namespace Swift { virtual void setSecurityLabelsEnabled(bool enabled) = 0; virtual void setUnreadMessageCount(int count) = 0; virtual void convertToMUC() = 0; - virtual TreeWidget *getTreeWidget() = 0; +// virtual TreeWidget *getTreeWidget() = 0; virtual void setSecurityLabelsError() = 0; virtual SecurityLabel getSelectedSecurityLabel() = 0; virtual void setInputEnabled(bool enabled) = 0; + virtual void setRosterModel(Roster* model) = 0; boost::signal<void ()> onClosed; boost::signal<void ()> onAllMessagesRead; diff --git a/Swift/Controllers/UIInterfaces/ChatWindowFactory.h b/Swift/Controllers/UIInterfaces/ChatWindowFactory.h index 3ea2416..b7b4479 100644 --- a/Swift/Controllers/UIInterfaces/ChatWindowFactory.h +++ b/Swift/Controllers/UIInterfaces/ChatWindowFactory.h @@ -11,14 +11,14 @@ namespace Swift { class ChatWindow; - + class UIEventStream; class ChatWindowFactory { public: virtual ~ChatWindowFactory() {}; /** * Transfers ownership of result. */ - virtual ChatWindow* createChatWindow(const JID &contact) = 0; + virtual ChatWindow* createChatWindow(const JID &contact, UIEventStream* eventStream) = 0; }; } diff --git a/Swift/Controllers/UIInterfaces/MainWindow.h b/Swift/Controllers/UIInterfaces/MainWindow.h index ce8b877..6d6e980 100644 --- a/Swift/Controllers/UIInterfaces/MainWindow.h +++ b/Swift/Controllers/UIInterfaces/MainWindow.h @@ -15,16 +15,16 @@ #include <boost/shared_ptr.hpp> namespace Swift { - class TreeWidget; + class Roster; class MainWindow { public: virtual ~MainWindow() {}; - virtual TreeWidget* getTreeWidget() = 0; virtual void setMyName(const String& name) = 0; virtual void setMyAvatarPath(const String& path) = 0; virtual void setMyStatusText(const String& status) = 0; virtual void setMyStatusType(StatusShow::Type type) = 0; + virtual void setRosterModel(Roster* roster) = 0; boost::signal<void (const JID&)> onStartChatRequest; boost::signal<void (StatusShow::Type, const String&)> onChangeStatusRequest; diff --git a/Swift/Controllers/UnitTest/MockChatWindow.h b/Swift/Controllers/UnitTest/MockChatWindow.h index fecd665..1ce87ff 100644 --- a/Swift/Controllers/UnitTest/MockChatWindow.h +++ b/Swift/Controllers/UnitTest/MockChatWindow.h @@ -27,10 +27,10 @@ namespace Swift { virtual void setSecurityLabelsEnabled(bool enabled) {labelsEnabled_ = enabled;}; virtual void setUnreadMessageCount(int /*count*/) {}; virtual void convertToMUC() {}; - virtual TreeWidget *getTreeWidget() {return NULL;}; virtual void setSecurityLabelsError() {}; virtual SecurityLabel getSelectedSecurityLabel() {return SecurityLabel();}; virtual void setInputEnabled(bool /*enabled*/) {}; + virtual void setRosterModel(Roster* /*roster*/) {}; boost::signal<void ()> onClosed; boost::signal<void ()> onAllMessagesRead; diff --git a/Swift/Controllers/UnitTest/MockMainWindow.h b/Swift/Controllers/UnitTest/MockMainWindow.h index f6134da..4d0c67a 100644 --- a/Swift/Controllers/UnitTest/MockMainWindow.h +++ b/Swift/Controllers/UnitTest/MockMainWindow.h @@ -7,20 +7,19 @@ #pragma once #include "Swift/Controllers/UIInterfaces/MainWindow.h" -#include "Swiften/Roster/TreeWidget.h" namespace Swift { + class Roster; class MockMainWindow : public MainWindow { public: - MockMainWindow(TreeWidget* treeWidget) {treeWidget_ = treeWidget;}; + MockMainWindow() {}; virtual ~MockMainWindow() {}; - virtual TreeWidget* getTreeWidget() {return treeWidget_;}; + virtual void setRosterModel(Roster* roster) {this->roster = roster;}; virtual void setMyName(const String& /*name*/) {};; virtual void setMyAvatarPath(const String& /*path*/) {}; virtual void setMyStatusText(const String& /*status*/) {}; virtual void setMyStatusType(StatusShow::Type /*type*/) {}; - - private: - TreeWidget* treeWidget_; + Roster* roster; + }; } diff --git a/Swift/Controllers/UnitTest/MockMainWindowFactory.h b/Swift/Controllers/UnitTest/MockMainWindowFactory.h index 2f0559b..8a35d1a 100644 --- a/Swift/Controllers/UnitTest/MockMainWindowFactory.h +++ b/Swift/Controllers/UnitTest/MockMainWindowFactory.h @@ -7,21 +7,19 @@ #pragma once #include "Swift/Controllers/UIInterfaces/MainWindowFactory.h" -#include "Swiften/Roster/TreeWidgetFactory.h" #include "Swift/Controllers/UnitTest/MockMainWindow.h" namespace Swift { class MockMainWindowFactory : public MainWindowFactory { public: - MockMainWindowFactory(TreeWidgetFactory* treeWidgetFactory) {factory_ = treeWidgetFactory;}; + MockMainWindowFactory() {}; virtual ~MockMainWindowFactory() {}; /** * Transfers ownership of result. */ - virtual MainWindow* createMainWindow(UIEventStream*) {return new MockMainWindow(factory_->createTreeWidget());}; - private: - TreeWidgetFactory* factory_; + virtual MainWindow* createMainWindow(UIEventStream*) {last = new MockMainWindow();return last;}; + MockMainWindow* last; }; } diff --git a/Swift/Controllers/UnitTest/RosterControllerTest.cpp b/Swift/Controllers/UnitTest/RosterControllerTest.cpp index 1177bd7..4bb3a08 100644 --- a/Swift/Controllers/UnitTest/RosterControllerTest.cpp +++ b/Swift/Controllers/UnitTest/RosterControllerTest.cpp @@ -10,7 +10,6 @@ #include "Swift/Controllers/RosterController.h" #include "Swift/Controllers/UnitTest/MockMainWindowFactory.h" -#include "Swiften/Roster/UnitTest/MockTreeWidgetFactory.h" // #include "Swiften/Elements/Payload.h" // #include "Swiften/Elements/RosterItemPayload.h" // #include "Swiften/Elements/RosterPayload.h" @@ -18,6 +17,9 @@ #include "Swiften/Client/DummyStanzaChannel.h" #include "Swiften/Queries/IQRouter.h" #include "Swiften/Roster/XMPPRoster.h" +#include "Swiften/Roster/Roster.h" +#include "Swiften/Roster/GroupRosterItem.h" +#include "Swiften/Roster/ContactRosterItem.h" #include "Swift/Controllers/EventController.h" #include "Swiften/Presence/PresenceOracle.h" #include "Swift/Controllers/NickResolver.h" @@ -25,6 +27,7 @@ using namespace Swift; +#define CHILDREN mainWindow_->roster->getRoot()->getChildren() class RosterControllerTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(RosterControllerTest); @@ -40,8 +43,7 @@ class RosterControllerTest : public CppUnit::TestFixture jid_ = JID("testjid@swift.im/swift"); xmppRoster_ = boost::shared_ptr<XMPPRoster>(new XMPPRoster()); avatarManager_ = NULL;//new AvatarManager(); - treeWidgetFactory_ = new MockTreeWidgetFactory(); - mainWindowFactory_ = new MockMainWindowFactory(treeWidgetFactory_); + mainWindowFactory_ = new MockMainWindowFactory(); nickResolver_ = new NickResolver(xmppRoster_); channel_ = new DummyIQChannel(); router_ = new IQRouter(channel_); @@ -49,9 +51,8 @@ class RosterControllerTest : public CppUnit::TestFixture presenceOracle_ = new PresenceOracle(stanzaChannel_); eventController_ = new EventController(); uiEventStream_ = new UIEventStream(); - rosterController_ = new RosterController(jid_, xmppRoster_, avatarManager_, mainWindowFactory_, treeWidgetFactory_, nickResolver_, presenceOracle_, eventController_, uiEventStream_, router_); - - + rosterController_ = new RosterController(jid_, xmppRoster_, avatarManager_, mainWindowFactory_, nickResolver_, presenceOracle_, eventController_, uiEventStream_, router_); + mainWindow_ = mainWindowFactory_->last; }; void tearDown() { @@ -65,16 +66,19 @@ class RosterControllerTest : public CppUnit::TestFixture delete presenceOracle_; delete stanzaChannel_; delete uiEventStream_; - delete treeWidgetFactory_; }; + GroupRosterItem* groupChild(size_t i) { + return dynamic_cast<GroupRosterItem*>(CHILDREN[i]); + } + void testAdd() { std::vector<String> groups; groups.push_back("testGroup1"); groups.push_back("testGroup2"); xmppRoster_->addContact(JID("test@testdomain.com/bob"), "name", groups, RosterItemPayload::Both); - CPPUNIT_ASSERT_EQUAL(2, (int)treeWidgetFactory_->getGroups().size()); + CPPUNIT_ASSERT_EQUAL(2, (int)CHILDREN.size()); //CPPUNIT_ASSERT_EQUAL(String("Bob"), xmppRoster_->getNameForJID(JID("foo@bar.com"))); }; @@ -83,15 +87,15 @@ class RosterControllerTest : public CppUnit::TestFixture JID jid("test@testdomain.com"); xmppRoster_->addContact(jid, "name", groups, RosterItemPayload::None); - CPPUNIT_ASSERT_EQUAL(1, (int)treeWidgetFactory_->getGroups().size()); - CPPUNIT_ASSERT_EQUAL(1, (int)treeWidgetFactory_->getGroupMembers("Contacts").size()); + CPPUNIT_ASSERT_EQUAL(1, (int)CHILDREN.size()); + CPPUNIT_ASSERT_EQUAL(1, (int)groupChild(0)->getChildren().size()); xmppRoster_->addContact(jid, "name", groups, RosterItemPayload::To); - CPPUNIT_ASSERT_EQUAL(1, (int)treeWidgetFactory_->getGroups().size()); - CPPUNIT_ASSERT_EQUAL(1, (int)treeWidgetFactory_->getGroupMembers("Contacts").size()); + CPPUNIT_ASSERT_EQUAL(1, (int)CHILDREN.size()); + CPPUNIT_ASSERT_EQUAL(1, (int)groupChild(0)->getChildren().size()); xmppRoster_->addContact(jid, "name", groups, RosterItemPayload::Both); - CPPUNIT_ASSERT_EQUAL(1, (int)treeWidgetFactory_->getGroups().size()); - CPPUNIT_ASSERT_EQUAL(1, (int)treeWidgetFactory_->getGroupMembers("Contacts").size()); + CPPUNIT_ASSERT_EQUAL(1, (int)CHILDREN.size()); + CPPUNIT_ASSERT_EQUAL(1, (int)groupChild(0)->getChildren().size()); }; @@ -100,20 +104,20 @@ class RosterControllerTest : public CppUnit::TestFixture JID jid("test@testdomain.com"); xmppRoster_->addContact(jid, "name", groups, RosterItemPayload::Both); - CPPUNIT_ASSERT_EQUAL(1, (int)treeWidgetFactory_->getGroups().size()); - CPPUNIT_ASSERT_EQUAL(1, (int)treeWidgetFactory_->getGroupMembers("Contacts").size()); + CPPUNIT_ASSERT_EQUAL(1, (int)CHILDREN.size()); + CPPUNIT_ASSERT_EQUAL(1, (int)groupChild(0)->getChildren().size()); + CPPUNIT_ASSERT_EQUAL(String("name"), groupChild(0)->getChildren()[0]->getDisplayName()); xmppRoster_->addContact(jid, "NewName", groups, RosterItemPayload::Both); - CPPUNIT_ASSERT_EQUAL(1, (int)treeWidgetFactory_->getGroups().size()); - CPPUNIT_ASSERT_EQUAL(1, (int)treeWidgetFactory_->getGroupMembers("Contacts").size()); - CPPUNIT_ASSERT_EQUAL(String("NewName"), treeWidgetFactory_->getGroupMembers("Contacts")[0]->getText()); + CPPUNIT_ASSERT_EQUAL(1, (int)CHILDREN.size()); + CPPUNIT_ASSERT_EQUAL(1, (int)groupChild(0)->getChildren().size()); + CPPUNIT_ASSERT_EQUAL(String("NewName"), groupChild(0)->getChildren()[0]->getDisplayName()); }; private: JID jid_; boost::shared_ptr<XMPPRoster> xmppRoster_; AvatarManager* avatarManager_; - MainWindowFactory* mainWindowFactory_; - MockTreeWidgetFactory* treeWidgetFactory_; + MockMainWindowFactory* mainWindowFactory_; NickResolver* nickResolver_; RosterController* rosterController_; DummyIQChannel* channel_; @@ -122,6 +126,8 @@ class RosterControllerTest : public CppUnit::TestFixture PresenceOracle* presenceOracle_; EventController* eventController_; UIEventStream* uiEventStream_; + MockMainWindow* mainWindow_; }; +#undef children CPPUNIT_TEST_SUITE_REGISTRATION(RosterControllerTest); diff --git a/Swift/Controllers/XMPPRosterController.cpp b/Swift/Controllers/XMPPRosterController.cpp index a7e634a..de5ff8c 100644 --- a/Swift/Controllers/XMPPRosterController.cpp +++ b/Swift/Controllers/XMPPRosterController.cpp @@ -16,8 +16,6 @@ #include "Swiften/Roster/Roster.h" #include "Swiften/Roster/SetPresence.h" #include "Swiften/Roster/OfflineRosterFilter.h" -#include "Swiften/Roster/OpenChatRosterAction.h" -#include "Swiften/Roster/TreeWidgetFactory.h" #include "Swiften/Roster/XMPPRoster.h" namespace Swift { diff --git a/Swift/QtUI/ChatList/QtChatListWindow.cpp b/Swift/QtUI/ChatList/QtChatListWindow.cpp index 7d307f9..9b70881 100644 --- a/Swift/QtUI/ChatList/QtChatListWindow.cpp +++ b/Swift/QtUI/ChatList/QtChatListWindow.cpp @@ -29,6 +29,7 @@ QtChatListWindow::QtChatListWindow(UIEventStream *uiEventStream, QWidget* parent #ifdef SWIFT_PLATFORM_MACOSX setAlternatingRowColors(true); #endif + expandAll(); setAnimated(true); setIndentation(0); setRootIsDecorated(true); diff --git a/Swift/QtUI/ContextMenus/QtContextMenu.h b/Swift/QtUI/ContextMenus/QtContextMenu.h index baa0180..9e73ef9 100644 --- a/Swift/QtUI/ContextMenus/QtContextMenu.h +++ b/Swift/QtUI/ContextMenus/QtContextMenu.h @@ -7,11 +7,11 @@ #pragma once namespace Swift { - class QtTreeWidgetItem; + class RosterItem; class QtContextMenu { public: virtual ~QtContextMenu(); - virtual void show(QtTreeWidgetItem* item) = 0; + virtual void show(RosterItem* item) = 0; }; } diff --git a/Swift/QtUI/ContextMenus/QtRosterContextMenu.cpp b/Swift/QtUI/ContextMenus/QtRosterContextMenu.cpp index 10e0b56..e6b5ae5 100644 --- a/Swift/QtUI/ContextMenus/QtRosterContextMenu.cpp +++ b/Swift/QtUI/ContextMenus/QtRosterContextMenu.cpp @@ -11,9 +11,10 @@ #include <boost/shared_ptr.hpp> +#include "Swiften/Roster/ContactRosterItem.h" #include "Swiften/Base/String.h" -#include "Swift/Controllers/UIEvents/RemoveItemRosterAction.h" -#include "Swift/QtUI/Roster/QtTreeWidgetItem.h" +#include "Swift/Controllers/UIEvents/UIEvent.h" +#include "Swift/Controllers/UIEvents/RemoveRosterItemUIEvent.h" #include "Swift/QtUI/QtSwiftUtil.h" namespace Swift { @@ -22,8 +23,9 @@ QtRosterContextMenu::QtRosterContextMenu(UIEventStream* eventStream) { eventStream_ = eventStream; } -void QtRosterContextMenu::show(QtTreeWidgetItem* item) { - if (!item->isContact()) { +void QtRosterContextMenu::show(RosterItem* item) { + ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(item); + if (!contact) { return; } item_ = item; @@ -33,7 +35,9 @@ void QtRosterContextMenu::show(QtTreeWidgetItem* item) { } void QtRosterContextMenu::handleRemove() { - item_->performUserAction(boost::shared_ptr<UserRosterAction>(new RemoveItemRosterAction())); + ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(item_); + assert(contact); + eventStream_->send(boost::shared_ptr<UIEvent>(new RemoveRosterItemUIEvent(contact->getJID()))); } } diff --git a/Swift/QtUI/ContextMenus/QtRosterContextMenu.h b/Swift/QtUI/ContextMenus/QtRosterContextMenu.h index ffa8ba6..51556e4 100644 --- a/Swift/QtUI/ContextMenus/QtRosterContextMenu.h +++ b/Swift/QtUI/ContextMenus/QtRosterContextMenu.h @@ -12,17 +12,18 @@ #include "Swift/Controllers/UIEvents/UIEventStream.h" namespace Swift { + class RosterItem; class QtRosterContextMenu : public QObject, public QtContextMenu { Q_OBJECT public: QtRosterContextMenu(UIEventStream* eventStream); - void show(QtTreeWidgetItem* item); + void show(RosterItem* item); private slots: void handleRemove(); private: - QtTreeWidgetItem* item_; + RosterItem* item_; UIEventStream* eventStream_; }; } diff --git a/Swift/QtUI/QtChatWindow.cpp b/Swift/QtUI/QtChatWindow.cpp index 5bedc22..d1b3194 100644 --- a/Swift/QtUI/QtChatWindow.cpp +++ b/Swift/QtUI/QtChatWindow.cpp @@ -6,8 +6,8 @@ #include "QtChatWindow.h" #include "QtSwiftUtil.h" +#include "Swiften/Roster/Roster.h" #include "Roster/QtTreeWidget.h" -#include "Roster/QtTreeWidgetFactory.h" #include "SwifTools/Linkify.h" #include "QtChatView.h" #include "MessageSnippet.h" @@ -26,7 +26,7 @@ #include <QUrl> namespace Swift { -QtChatWindow::QtChatWindow(const QString &contact, QtTreeWidgetFactory *treeWidgetFactory) : QtTabbable(), contact_(contact), previousMessageWasSelf_(false), previousMessageWasSystem_(false) { +QtChatWindow::QtChatWindow(const QString &contact, UIEventStream* eventStream) : QtTabbable(), contact_(contact), previousMessageWasSelf_(false), previousMessageWasSystem_(false), eventStream_(eventStream) { unreadCount_ = 0; updateTitleWithUnreadCount(); @@ -42,7 +42,7 @@ QtChatWindow::QtChatWindow(const QString &contact, QtTreeWidgetFactory *treeWidg messageLog_->setFocusPolicy(Qt::NoFocus); logRosterSplitter->addWidget(messageLog_); - treeWidget_ = dynamic_cast<QtTreeWidget*>(treeWidgetFactory->createTreeWidget()); + treeWidget_ = new QtTreeWidget(eventStream_); treeWidget_->hide(); logRosterSplitter->addWidget(treeWidget_); @@ -79,8 +79,8 @@ QtChatWindow::~QtChatWindow() { } -TreeWidget* QtChatWindow::getTreeWidget() { - return treeWidget_; +void QtChatWindow::setRosterModel(Roster* roster) { + treeWidget_->setRosterModel(roster); } void QtChatWindow::setAvailableSecurityLabels(const std::vector<SecurityLabel>& labels) { diff --git a/Swift/QtUI/QtChatWindow.h b/Swift/QtUI/QtChatWindow.h index f9b401c..0b22ea1 100644 --- a/Swift/QtUI/QtChatWindow.h +++ b/Swift/QtUI/QtChatWindow.h @@ -21,10 +21,11 @@ namespace Swift { class QtTreeWidgetFactory; class TreeWidget; class QtTextEdit; + class UIEventStream; class QtChatWindow : public QtTabbable, public ChatWindow { Q_OBJECT public: - QtChatWindow(const QString &contact, QtTreeWidgetFactory* treeWidgetFactory); + QtChatWindow(const QString &contact, UIEventStream* eventStream); ~QtChatWindow(); void addMessage(const String &message, const String &senderName, bool senderIsSelf, const boost::optional<SecurityLabel>& label, const String& avatarPath); void addAction(const String &message, const String &senderName, bool senderIsSelf, const boost::optional<SecurityLabel>& label, const String& avatarPath); @@ -34,7 +35,7 @@ namespace Swift { void activate(); void setUnreadMessageCount(int count); void convertToMUC(); - TreeWidget *getTreeWidget(); +// TreeWidget *getTreeWidget(); void setAvailableSecurityLabels(const std::vector<SecurityLabel>& labels); void setSecurityLabelsEnabled(bool enabled); void setSecurityLabelsError(); @@ -43,6 +44,7 @@ namespace Swift { void setInputEnabled(bool enabled); QtTabbable::AlertType getWidgetAlertState(); void setContactChatState(ChatState::ChatStateType state); + void setRosterModel(Roster* roster); protected slots: void qAppFocusChanged(QWidget* old, QWidget* now); @@ -70,6 +72,7 @@ namespace Swift { bool previousMessageWasSystem_; QString previousSenderName_; bool inputClearing_; + UIEventStream* eventStream_; }; } diff --git a/Swift/QtUI/QtChatWindowFactory.cpp b/Swift/QtUI/QtChatWindowFactory.cpp index d96fa2b..5029324 100644 --- a/Swift/QtUI/QtChatWindowFactory.cpp +++ b/Swift/QtUI/QtChatWindowFactory.cpp @@ -11,11 +11,10 @@ #include "QtChatTabs.h" #include "QtChatWindow.h" #include "QtSwiftUtil.h" -#include "Roster/QtTreeWidgetFactory.h" namespace Swift { -QtChatWindowFactory::QtChatWindowFactory(QtTreeWidgetFactory *treeWidgetFactory, QSplitter* splitter, QtSettingsProvider* settings, QtChatTabs* tabs) : treeWidgetFactory_(treeWidgetFactory) { +QtChatWindowFactory::QtChatWindowFactory(QSplitter* splitter, QtSettingsProvider* settings, QtChatTabs* tabs) { settings_ = settings; tabs_ = tabs; if (splitter) { @@ -29,10 +28,9 @@ QtChatWindowFactory::QtChatWindowFactory(QtTreeWidgetFactory *treeWidgetFactory, } } -ChatWindow* QtChatWindowFactory::createChatWindow(const JID &contact) { - QtChatWindow *chatWindow = new QtChatWindow(P2QSTRING(contact.toString()), treeWidgetFactory_); +ChatWindow* QtChatWindowFactory::createChatWindow(const JID &contact,UIEventStream* eventStream) { + QtChatWindow *chatWindow = new QtChatWindow(P2QSTRING(contact.toString()), eventStream); tabs_->addTab(chatWindow); - //chatWindow->show(); return chatWindow; } diff --git a/Swift/QtUI/QtChatWindowFactory.h b/Swift/QtUI/QtChatWindowFactory.h index dc43146..4ffac88 100644 --- a/Swift/QtUI/QtChatWindowFactory.h +++ b/Swift/QtUI/QtChatWindowFactory.h @@ -4,8 +4,7 @@ * See Documentation/Licenses/GPLv3.txt for more information. */ -#ifndef SWIFT_QtChatWindowFactory_H -#define SWIFT_QtChatWindowFactory_H +#pragma once #include "Swift/Controllers/UIInterfaces/ChatWindowFactory.h" #include "Swiften/JID/JID.h" @@ -14,20 +13,18 @@ #include <QObject> #include <QSplitter> namespace Swift { - class QtTreeWidgetFactory; class QtChatTabs; + class UIEventStream; class QtChatWindowFactory : public QObject, public ChatWindowFactory { Q_OBJECT public: - QtChatWindowFactory(QtTreeWidgetFactory *treeWidgetFactory, QSplitter* splitter, QtSettingsProvider* settings, QtChatTabs* tabs); - ChatWindow* createChatWindow(const JID &contact); + QtChatWindowFactory(QSplitter* splitter, QtSettingsProvider* settings, QtChatTabs* tabs); + ChatWindow* createChatWindow(const JID &contact, UIEventStream* eventStream); private slots: void handleWindowGeometryChanged(); private: - QtTreeWidgetFactory* treeWidgetFactory_; QtSettingsProvider* settings_; QtChatTabs* tabs_; }; } -#endif diff --git a/Swift/QtUI/QtMainWindow.cpp b/Swift/QtUI/QtMainWindow.cpp index fe4b179..0381d9e 100644 --- a/Swift/QtUI/QtMainWindow.cpp +++ b/Swift/QtUI/QtMainWindow.cpp @@ -23,14 +23,13 @@ #include "QtJoinMUCDialog.h" #include "QtSwiftUtil.h" #include "QtTabWidget.h" -#include "Roster/QtTreeWidgetFactory.h" #include "Roster/QtTreeWidget.h" #include "Swift/Controllers/UIEvents/AddContactUIEvent.h" #include "Swift/Controllers/UIEvents/JoinMUCUIEvent.h" namespace Swift { -QtMainWindow::QtMainWindow(UIEventStream* uiEventStream, QtTreeWidgetFactory *treeWidgetFactory) : QWidget() { +QtMainWindow::QtMainWindow(UIEventStream* uiEventStream) : QWidget() { uiEventStream_ = uiEventStream; setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding)); QBoxLayout *mainLayout = new QBoxLayout(QBoxLayout::TopToBottom, this); @@ -53,7 +52,7 @@ QtMainWindow::QtMainWindow(UIEventStream* uiEventStream, QtTreeWidgetFactory *tr contactTabLayout->setSpacing(0); contactTabLayout->setContentsMargins(0, 0, 0, 0); - treeWidget_ = dynamic_cast<QtTreeWidget*>(treeWidgetFactory->createTreeWidget()); + treeWidget_ = new QtTreeWidget(uiEventStream_); contextMenu_ = new QtRosterContextMenu(uiEventStream_); treeWidget_->setContextMenu(contextMenu_); treeWidget_->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); @@ -104,6 +103,10 @@ QtChatListWindow* QtMainWindow::getChatListWindow() { return chatListWindow_; } +void QtMainWindow::setRosterModel(Roster* roster) { + treeWidget_->setRosterModel(roster); +} + void QtMainWindow::handleEventCountUpdated(int count) { QColor eventTabColor = (count == 0) ? QColor(-1, -1, -1) : QColor(255, 0, 0); // invalid resets to default int eventIndex = 1; @@ -131,10 +134,6 @@ void QtMainWindow::handleAddContactDialogComplete(const JID& contact, const QStr uiEventStream_->send(event); } -TreeWidget* QtMainWindow::getTreeWidget() { - return treeWidget_; -} - void QtMainWindow::handleJoinMUCAction() { QtJoinMUCDialog* joinMUC = new QtJoinMUCDialog("jabber@conference.jabber.org", "SwiftUser", this); connect(joinMUC, SIGNAL(onJoinCommand(const JID&, const QString&)), SLOT(handleJoinMUCDialogComplete(const JID&, const QString&))); diff --git a/Swift/QtUI/QtMainWindow.h b/Swift/QtUI/QtMainWindow.h index 45dbda6..3c20d66 100644 --- a/Swift/QtUI/QtMainWindow.h +++ b/Swift/QtUI/QtMainWindow.h @@ -35,9 +35,8 @@ namespace Swift { class QtMainWindow : public QWidget, public MainWindow { Q_OBJECT public: - QtMainWindow(UIEventStream* eventStream, QtTreeWidgetFactory *treeWidgetFactory); + QtMainWindow(UIEventStream* eventStream); ~QtMainWindow(); - TreeWidget* getTreeWidget(); std::vector<QMenu*> getMenus() {return menus_;} void setMyName(const String& name); void setMyAvatarPath(const String& path); @@ -45,6 +44,7 @@ namespace Swift { void setMyStatusType(const StatusShow::Type type); QtEventWindow* getEventWindow(); QtChatListWindow* getChatListWindow(); + void setRosterModel(Roster* roster); private slots: void handleStatusChanged(StatusShow::Type showType, const QString &statusMessage); void handleShowOfflineToggled(bool); diff --git a/Swift/QtUI/QtMainWindowFactory.cpp b/Swift/QtUI/QtMainWindowFactory.cpp index 12e3532..4405239 100644 --- a/Swift/QtUI/QtMainWindowFactory.cpp +++ b/Swift/QtUI/QtMainWindowFactory.cpp @@ -6,16 +6,15 @@ #include "QtMainWindowFactory.h" #include "QtMainWindow.h" -#include "Roster/QtTreeWidgetFactory.h" namespace Swift { -QtMainWindowFactory::QtMainWindowFactory(QtTreeWidgetFactory *treeWidgetFactory) : treeWidgetFactory_(treeWidgetFactory) { +QtMainWindowFactory::QtMainWindowFactory() { lastWindow_ = NULL; } MainWindow* QtMainWindowFactory::createMainWindow(UIEventStream* eventStream) { - lastWindow_ = new QtMainWindow(eventStream, treeWidgetFactory_); + lastWindow_ = new QtMainWindow(eventStream); return lastWindow_; } diff --git a/Swift/QtUI/QtMainWindowFactory.h b/Swift/QtUI/QtMainWindowFactory.h index c16d229..17eb53c 100644 --- a/Swift/QtUI/QtMainWindowFactory.h +++ b/Swift/QtUI/QtMainWindowFactory.h @@ -13,11 +13,10 @@ namespace Swift { class QtTreeWidgetFactory; class QtMainWindowFactory : public MainWindowFactory{ public: - QtMainWindowFactory(QtTreeWidgetFactory *treeWidgetFactory); + QtMainWindowFactory(); MainWindow* createMainWindow(UIEventStream* eventStream); MainWindow* getLastCreatedWindow(); private: - QtTreeWidgetFactory *treeWidgetFactory_; MainWindow* lastWindow_; }; } diff --git a/Swift/QtUI/QtSwift.cpp b/Swift/QtUI/QtSwift.cpp index fc5f4cb..534697b 100644 --- a/Swift/QtUI/QtSwift.cpp +++ b/Swift/QtUI/QtSwift.cpp @@ -11,7 +11,6 @@ #include "QtLoginWindow.h" #include "QtChatTabs.h" #include "QtMainWindowFactory.h" -#include "Roster/QtTreeWidgetFactory.h" #include "QtSystemTray.h" #include "QtSoundPlayer.h" #include "QtXMLConsoleWidgetFactory.h" @@ -65,11 +64,10 @@ QtSwift::QtSwift(po::variables_map options) : autoUpdater_(NULL) { tabs_ = new QtChatTabs(); settings_ = new QtSettingsProvider(); application_ = new PlatformApplication(SWIFT_APPLICATION_NAME); - treeWidgetFactory_ = new QtTreeWidgetFactory(); systemTray_ = new QtSystemTray(); loginWindowFactory_ = new QtLoginWindowFactory(splitter_, systemTray_, settings_); - chatWindowFactory_ = new QtChatWindowFactory(treeWidgetFactory_, splitter_, settings_, tabs_); - rosterWindowFactory_ = new QtMainWindowFactory(treeWidgetFactory_); + chatWindowFactory_ = new QtChatWindowFactory(splitter_, settings_, tabs_); + rosterWindowFactory_ = new QtMainWindowFactory(); eventWindowFactory_ = new QtEventWindowFactory(rosterWindowFactory_); xmlConsoleWidgetFactory_ = new QtXMLConsoleWidgetFactory(tabs_); chatListWindowFactory_ = new QtChatListWindowFactory(rosterWindowFactory_); @@ -77,7 +75,7 @@ QtSwift::QtSwift(po::variables_map options) : autoUpdater_(NULL) { if (splitter_) { splitter_->show(); } - mainController_ = new MainController(chatWindowFactory_, rosterWindowFactory_, loginWindowFactory_, treeWidgetFactory_, eventWindowFactory_, settings_, application_, systemTray_, soundPlayer_, xmlConsoleWidgetFactory_, chatListWindowFactory_, options.count("latency-debug") > 0); + mainController_ = new MainController(chatWindowFactory_, rosterWindowFactory_, loginWindowFactory_, eventWindowFactory_, settings_, application_, systemTray_, soundPlayer_, xmlConsoleWidgetFactory_, chatListWindowFactory_, options.count("latency-debug") > 0); PlatformAutoUpdaterFactory autoUpdaterFactory; if (autoUpdaterFactory.isSupported()) { @@ -91,7 +89,6 @@ QtSwift::~QtSwift() { delete chatWindowFactory_; delete rosterWindowFactory_; delete loginWindowFactory_; - delete treeWidgetFactory_; delete mainController_; delete settings_; delete application_; diff --git a/Swift/QtUI/QtSwift.h b/Swift/QtUI/QtSwift.h index 72343d8..d0141b2 100644 --- a/Swift/QtUI/QtSwift.h +++ b/Swift/QtUI/QtSwift.h @@ -28,7 +28,6 @@ namespace Swift { class QtChatWindowFactory; class QtMainWindowFactory; class QtLoginWindowFactory; - class QtTreeWidgetFactory; class QtXMLConsoleWidgetFactory; class QtSystemTray; class QtSoundPlayer; @@ -43,7 +42,6 @@ namespace Swift { ~QtSwift(); private: MainController *mainController_; - QtTreeWidgetFactory *treeWidgetFactory_; QtChatWindowFactory *chatWindowFactory_; QtChatListWindowFactory *chatListWindowFactory_; QtMainWindowFactory *rosterWindowFactory_; diff --git a/Swift/QtUI/Roster/QtTreeWidget.cpp b/Swift/QtUI/Roster/QtTreeWidget.cpp index 9dabc81..97b055b 100644 --- a/Swift/QtUI/Roster/QtTreeWidget.cpp +++ b/Swift/QtUI/Roster/QtTreeWidget.cpp @@ -7,7 +7,9 @@ #include "Roster/QtTreeWidget.h" #include "Swiften/Base/Platform.h" -#include "Swiften/Roster/OpenChatRosterAction.h" +#include "Swiften/Roster/ContactRosterItem.h" +#include "Swift/Controllers/UIEvents/UIEventStream.h" +#include "Swift/Controllers/UIEvents/RequestChatUIEvent.h" #include <qdebug.h> #include <QMenu> @@ -15,26 +17,26 @@ namespace Swift { -QtTreeWidget::QtTreeWidget(QWidget* parent) : QTreeView(parent) { - treeRoot_ = new QtTreeWidgetItem(NULL); - model_ = new RosterModel(); - model_->setRoot(treeRoot_); +QtTreeWidget::QtTreeWidget(UIEventStream* eventStream, QWidget* parent) : QTreeView(parent) { + eventStream_ = eventStream; + model_ = new RosterModel(this); setModel(model_); - delegate_ = new RosterDelegate(); + delegate_ = new RosterDelegate(this); setItemDelegate(delegate_); setHeaderHidden(true); contextMenu_ = NULL; #ifdef SWIFT_PLATFORM_MACOSX setAlternatingRowColors(true); #endif + expandAll(); setAnimated(true); setIndentation(0); setRootIsDecorated(true); connect(this, SIGNAL(activated(const QModelIndex&)), this, SLOT(handleItemActivated(const QModelIndex&))); - connect(model_, SIGNAL(itemExpanded(const QModelIndex&, bool)), this, SLOT(handleModelItemExpanded(const QModelIndex&, bool))); - connect(model_, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&)), this, SLOT(handleDataChanged(const QModelIndex&, const QModelIndex&))); - connect(this, SIGNAL(expanded(const QModelIndex&)), this, SLOT(handleExpanded(const QModelIndex&))); - connect(this, SIGNAL(collapsed(const QModelIndex&)), this, SLOT(handleCollapsed(const QModelIndex&))); +// connect(model_, SIGNAL(itemExpanded(const QModelIndex&, bool)), this, SLOT(handleModelItemExpanded(const QModelIndex&, bool))); +// connect(model_, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&)), this, SLOT(handleDataChanged(const QModelIndex&, const QModelIndex&))); +// connect(this, SIGNAL(expanded(const QModelIndex&)), this, SLOT(handleExpanded(const QModelIndex&))); +// connect(this, SIGNAL(collapsed(const QModelIndex&)), this, SLOT(handleCollapsed(const QModelIndex&))); } QtTreeWidget::~QtTreeWidget() { @@ -42,6 +44,11 @@ QtTreeWidget::~QtTreeWidget() { delete delegate_; } +void QtTreeWidget::setRosterModel(Roster* roster) { + model_->setRoster(roster); + expandAll(); +} + void QtTreeWidget::setContextMenu(QtContextMenu* contextMenu) { contextMenu_ = contextMenu; } @@ -51,9 +58,10 @@ QtTreeWidgetItem* QtTreeWidget::getRoot() { } void QtTreeWidget::handleItemActivated(const QModelIndex& index) { - QtTreeWidgetItem* qtItem = static_cast<QtTreeWidgetItem*>(index.internalPointer()); - if (qtItem) { - qtItem->performUserAction(boost::shared_ptr<UserRosterAction>(new OpenChatRosterAction())); + RosterItem* item = static_cast<RosterItem*>(index.internalPointer()); + ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(item); + if (contact) { + eventStream_->send(boost::shared_ptr<UIEvent>(new RequestChatUIEvent(contact->getJID()))); } } @@ -62,53 +70,52 @@ void QtTreeWidget::contextMenuEvent(QContextMenuEvent* event) { return; } QModelIndex index = indexAt(event->pos()); - QtTreeWidgetItem* qtItem = index.isValid() ? static_cast<QtTreeWidgetItem*>(index.internalPointer()) : NULL; - if (qtItem) { - contextMenu_->show(qtItem); - } -} - -void QtTreeWidget::handleExpanded(const QModelIndex& index) { - QtTreeWidgetItem* qtItem = static_cast<QtTreeWidgetItem*>(index.internalPointer()); - if (qtItem) { - qtItem->setExpanded(true); - } -} - -void QtTreeWidget::handleCollapsed(const QModelIndex& index) { - QtTreeWidgetItem* qtItem = static_cast<QtTreeWidgetItem*>(index.internalPointer()); - if (qtItem) { - qtItem->setExpanded(false); - } -} - -void QtTreeWidget::handleModelItemExpanded(const QModelIndex& index, bool shouldExpand) { - if (this->isExpanded(index) == shouldExpand) { - return; - } - //setExpanded(index, shouldExpand); - if (shouldExpand) { - expand(index); - emit expanded(index); - } else { - collapse(index); - emit collapsed(index); + RosterItem* item = index.isValid() ? static_cast<RosterItem*>(index.internalPointer()) : NULL; + if (item) { + contextMenu_->show(item); } } -void QtTreeWidget::handleDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight) { - Q_UNUSED(bottomRight); - //in our model, this is only thrown with topLeft == bottomRight - if (!topLeft.isValid()) { - return; - } - QtTreeWidgetItem* qtItem = static_cast<QtTreeWidgetItem*>(topLeft.internalPointer()); - if (qtItem) { - setExpanded(topLeft, qtItem->isExpanded()); - //qDebug() << "Item changed, passing expanded state to view: " << qtItem->isExpanded() << " giving an expanded state of " << isExpanded(topLeft); - } - -} +//void QtTreeWidget::handleExpanded(const QModelIndex& index) { +// QtTreeWidgetItem* qtItem = static_cast<QtTreeWidgetItem*>(index.internalPointer()); +// if (qtItem) { +// qtItem->setExpanded(true); +// } +//} + +//void QtTreeWidget::handleCollapsed(const QModelIndex& index) { +// QtTreeWidgetItem* qtItem = static_cast<QtTreeWidgetItem*>(index.internalPointer()); +// if (qtItem) { +// qtItem->setExpanded(false); +// } +//} + +//void QtTreeWidget::handleModelItemExpanded(const QModelIndex& index, bool shouldExpand) { +// if (this->isExpanded(index) == shouldExpand) { +// return; +// } +// //setExpanded(index, shouldExpand); +// if (shouldExpand) { +// expand(index); +// emit expanded(index); +// } else { +// collapse(index); +// emit collapsed(index); +// } +//} + +// void QtTreeWidget::handleDataChanged(const QModelIndex& topLeft, const QModelIndex& /*bottomRight*/) { +// //in our model, this is only thrown with topLeft == bottomRight +// if (!topLeft.isValid()) { +// return; +// } +// QtTreeWidgetItem* qtItem = static_cast<QtTreeWidgetItem*>(topLeft.internalPointer()); +// if (qtItem) { +// setExpanded(topLeft, qtItem->isExpanded()); +// //qDebug() << "Item changed, passing expanded state to view: " << qtItem->isExpanded() << " giving an expanded state of " << isExpanded(topLeft); +// } + +// } void QtTreeWidget::drawBranches(QPainter*, const QRect&, const QModelIndex&) const { } diff --git a/Swift/QtUI/Roster/QtTreeWidget.h b/Swift/QtUI/Roster/QtTreeWidget.h index d6e6038..c03f2e2 100644 --- a/Swift/QtUI/Roster/QtTreeWidget.h +++ b/Swift/QtUI/Roster/QtTreeWidget.h @@ -9,31 +9,29 @@ #include <QTreeView> #include <QModelIndex> -#include "Swiften/Roster/TreeWidgetFactory.h" -#include "Swiften/Roster/TreeWidget.h" -#include "Swiften/Roster/TreeWidgetItem.h" -#include "Swift/QtUI/Roster/QtTreeWidgetItem.h" #include "Swift/QtUI/Roster/QtTreeWidget.h" #include "Swift/QtUI/Roster/RosterModel.h" #include "Swift/QtUI/Roster/RosterDelegate.h" #include "Swift/QtUI/ContextMenus/QtContextMenu.h" namespace Swift { +class UIEventStream; -class QtTreeWidget : public QTreeView, public TreeWidget { +class QtTreeWidget : public QTreeView{ Q_OBJECT public: - QtTreeWidget(QWidget* parent = 0); + QtTreeWidget(UIEventStream* eventStream, QWidget* parent = 0); ~QtTreeWidget(); void show(); QtTreeWidgetItem* getRoot(); void setContextMenu(QtContextMenu* contextMenu); + void setRosterModel(Roster* roster); private slots: void handleItemActivated(const QModelIndex&); - void handleModelItemExpanded(const QModelIndex&, bool expanded); - void handleExpanded(const QModelIndex&); - void handleCollapsed(const QModelIndex&); - void handleDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight); +// void handleModelItemExpanded(const QModelIndex&, bool expanded); +// void handleExpanded(const QModelIndex&); +// void handleCollapsed(const QModelIndex&); +// void handleDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight); protected: void contextMenuEvent(QContextMenuEvent* event); @@ -43,6 +41,7 @@ class QtTreeWidget : public QTreeView, public TreeWidget { RosterDelegate* delegate_; QtTreeWidgetItem* treeRoot_; QtContextMenu* contextMenu_; + UIEventStream* eventStream_; }; } diff --git a/Swift/QtUI/Roster/QtTreeWidgetFactory.cpp b/Swift/QtUI/Roster/QtTreeWidgetFactory.cpp deleted file mode 100644 index d4a8e4b..0000000 --- a/Swift/QtUI/Roster/QtTreeWidgetFactory.cpp +++ /dev/null @@ -1,6 +0,0 @@ -/* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. - */ - diff --git a/Swift/QtUI/Roster/QtTreeWidgetFactory.h b/Swift/QtUI/Roster/QtTreeWidgetFactory.h deleted file mode 100644 index b72a508..0000000 --- a/Swift/QtUI/Roster/QtTreeWidgetFactory.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. - */ - -#ifndef SWIFT_QtTreeWidgetFactory_H -#define SWIFT_QtTreeWidgetFactory_H - -#include "Swiften/Roster/TreeWidgetFactory.h" -#include "Swiften/Roster/TreeWidget.h" -#include "Swiften/Roster/TreeWidgetItem.h" -#include "Swift/QtUI/Roster/QtTreeWidgetItem.h" -#include "Swift/QtUI/Roster/QtTreeWidget.h" - -namespace Swift { - -class QtTreeWidgetFactory : public TreeWidgetFactory { - public: - QtTreeWidgetFactory() { - } - - TreeWidget* createTreeWidget() { - return new QtTreeWidget(); - } - - TreeWidgetItem* createTreeWidgetItem(TreeWidgetItem* item) { - QtTreeWidgetItem* qtItem = dynamic_cast<QtTreeWidgetItem*>(item); - assert(qtItem); - QtTreeWidgetItem* newItem = new QtTreeWidgetItem(qtItem); - qtItem->addChild(newItem); - return newItem; - } - - TreeWidgetItem* createTreeWidgetItem(TreeWidget* item) { - QtTreeWidget* treeItem = dynamic_cast<QtTreeWidget*>(item); - assert(treeItem); - QtTreeWidgetItem* qtItem = treeItem->getRoot(); - QtTreeWidgetItem* newItem = new QtTreeWidgetItem(qtItem); - //qtItem->setItemWidget(newItem, 0, newItem->getCollapsedRosterWidget()); - qtItem->addChild(newItem); - newItem->setExpanded(true); - return newItem; - } -}; - -} -#endif - diff --git a/Swift/QtUI/Roster/RosterDelegate.cpp b/Swift/QtUI/Roster/RosterDelegate.cpp index 0c12d6e..b7ba71b 100644 --- a/Swift/QtUI/Roster/RosterDelegate.cpp +++ b/Swift/QtUI/Roster/RosterDelegate.cpp @@ -15,11 +15,16 @@ #include <QPolygon> #include <qdebug.h> -#include "QtTreeWidgetItem.h" +#include "Swiften/Roster/ContactRosterItem.h" +#include "Swiften/Roster/GroupRosterItem.h" + +#include "QtTreeWidget.h" +#include "RosterModel.h" namespace Swift { -RosterDelegate::RosterDelegate() { +RosterDelegate::RosterDelegate(QtTreeWidget* tree) { + tree_ = tree; groupDelegate_ = new GroupItemDelegate(); } @@ -28,16 +33,14 @@ RosterDelegate::~RosterDelegate() { } QSize RosterDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index ) const { - QtTreeWidgetItem* item = static_cast<QtTreeWidgetItem*>(index.internalPointer()); - if (!item || !item->isContact()) { + RosterItem* item = static_cast<RosterItem*>(index.internalPointer()); + if (dynamic_cast<GroupRosterItem*>(item)) { return groupDelegate_->sizeHint(option, index); } return contactSizeHint(option, index); } -QSize RosterDelegate::contactSizeHint(const QStyleOptionViewItem& option, const QModelIndex& index ) const { - Q_UNUSED(option); - Q_UNUSED(index); +QSize RosterDelegate::contactSizeHint(const QStyleOptionViewItem& /*option*/, const QModelIndex& /*index*/ ) const { int heightByAvatar = avatarSize_ + common_.verticalMargin * 2; QFontMetrics nameMetrics(common_.nameFont); QFontMetrics statusMetrics(common_.detailFont); @@ -49,8 +52,8 @@ QSize RosterDelegate::contactSizeHint(const QStyleOptionViewItem& option, const } void RosterDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { - QtTreeWidgetItem* item = static_cast<QtTreeWidgetItem*>(index.internalPointer()); - if (item && !item->isContact()) { + RosterItem* item = static_cast<RosterItem*>(index.internalPointer()); + if (dynamic_cast<GroupRosterItem*>(item)) { paintGroup(painter, option, index); } else { paintContact(painter, option, index); @@ -58,15 +61,11 @@ void RosterDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option } void RosterDelegate::paintGroup(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { - QtTreeWidgetItem* item = index.isValid() ? static_cast<QtTreeWidgetItem*>(index.internalPointer()) : NULL; - if (item) { - groupDelegate_->paint(painter, option, index.data(Qt::DisplayRole).toString(), item->rowCount(), item->isExpanded()); + if (index.isValid()) { + groupDelegate_->paint(painter, option, index.data(Qt::DisplayRole).toString(), index.data(ChildCountRole).toInt(), tree_->isExpanded(index)); } } - - - void RosterDelegate::paintContact(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { //qDebug() << "painting" << index.data(Qt::DisplayRole).toString(); painter->save(); diff --git a/Swift/QtUI/Roster/RosterDelegate.h b/Swift/QtUI/Roster/RosterDelegate.h index 696ea03..e6a16f2 100644 --- a/Swift/QtUI/Roster/RosterDelegate.h +++ b/Swift/QtUI/Roster/RosterDelegate.h @@ -14,10 +14,10 @@ #include "DelegateCommons.h" namespace Swift { - class QtTreeWidgetItem; + class QtTreeWidget; class RosterDelegate : public QStyledItemDelegate { public: - RosterDelegate(); + RosterDelegate(QtTreeWidget* tree); ~RosterDelegate(); QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const; void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const; @@ -27,6 +27,7 @@ namespace Swift { void paintContact(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const; DelegateCommons common_; GroupItemDelegate* groupDelegate_; + QtTreeWidget* tree_; static const int avatarSize_; static const int presenceIconHeight_; static const int presenceIconWidth_; diff --git a/Swift/QtUI/Roster/RosterModel.cpp b/Swift/QtUI/Roster/RosterModel.cpp index c4cf57e..408cc3e 100644 --- a/Swift/QtUI/Roster/RosterModel.cpp +++ b/Swift/QtUI/Roster/RosterModel.cpp @@ -6,74 +6,184 @@ #include "RosterModel.h" +#include <boost/bind.hpp> + +#include <QColor> +#include <QIcon> +#include <qdebug.h> + +#include "Swiften/Elements/StatusShow.h" +#include "Swiften/Roster/ContactRosterItem.h" +#include "Swiften/Roster/GroupRosterItem.h" + +#include "QtSwiftUtil.h" +#include "Swift/QtUI/Roster/QtTreeWidget.h" + namespace Swift { -RosterModel::RosterModel() { +RosterModel::RosterModel(QtTreeWidget* view) : view_(view) { + roster_ = NULL; } RosterModel::~RosterModel() { - delete tree_; } -void RosterModel::setRoot(QtTreeWidgetItem* root) { - tree_ = root; - connect(tree_, SIGNAL(changed(QtTreeWidgetItem*)), this, SLOT(handleItemChanged(QtTreeWidgetItem*))); +void RosterModel::setRoster(Roster* roster) { + roster_ = roster; + if (!roster_) return; + roster->onChildrenChanged.connect(boost::bind(&RosterModel::handleChildrenChanged, this, _1)); + roster->onDataChanged.connect(boost::bind(&RosterModel::handleDataChanged, this, _1)); + roster->onGroupAdded.connect(boost::bind(&RosterModel::handleGroupAdded, this, _1)); + emit layoutChanged(); } - -void RosterModel::handleItemChanged(QtTreeWidgetItem* item) { - if (!item->isShown()) { - return; - } +void RosterModel::handleGroupAdded(GroupRosterItem* group) { + view_->setExpanded(index(group), true); +} + +void RosterModel::handleChildrenChanged(GroupRosterItem* /*group*/) { + emit layoutChanged(); +} + +void RosterModel::handleDataChanged(RosterItem* item) { Q_ASSERT(item); QModelIndex modelIndex = index(item); - Q_ASSERT(modelIndex.isValid()); - emit itemExpanded(modelIndex, item->isExpanded()); - emit dataChanged(modelIndex, modelIndex); - emit dataChanged(parent(modelIndex), parent(modelIndex)); - emit layoutChanged(); + if (modelIndex.isValid()) { + //emit itemExpanded(modelIndex, item->isExpanded()); + emit dataChanged(modelIndex, modelIndex); + } } -int RosterModel::columnCount(const QModelIndex& parent) const { - Q_UNUSED(parent); +int RosterModel::columnCount(const QModelIndex& /*parent*/) const { return 1; } +RosterItem* RosterModel::getItem(const QModelIndex& index) const { + return index.isValid() ? static_cast<RosterItem*>(index.internalPointer()) : NULL; +} + QVariant RosterModel::data(const QModelIndex& index, int role) const { - QtTreeWidgetItem* item = index.isValid() ? static_cast<QtTreeWidgetItem*>(index.internalPointer()) : NULL; - return item ? item->data(role) : QVariant(); + RosterItem* item = getItem(index); + if (!item) return QVariant(); + + switch (role) { + case Qt::DisplayRole: return P2QSTRING(item->getDisplayName()); + case Qt::TextColorRole: return getTextColor(item); + case Qt::BackgroundColorRole: return getBackgroundColor(item); + case Qt::ToolTipRole: return getToolTip(item); + case StatusTextRole: return getStatusText(item); + case AvatarRole: return getAvatar(item); + case PresenceIconRole: return getPresenceIcon(item); + case ChildCountRole: return getChildCount(item); + default: return QVariant(); + } } -QModelIndex RosterModel::index(int row, int column, const QModelIndex& parent) const { - QtTreeWidgetItem* parentItem = parent.isValid() ? static_cast<QtTreeWidgetItem*>(parent.internalPointer()) : tree_; - Q_ASSERT(parentItem); - - return row < parentItem->rowCount() ? createIndex(row, column, parentItem->getItem(row)) : QModelIndex(); +int RosterModel::getChildCount(RosterItem* item) const { + GroupRosterItem* group = dynamic_cast<GroupRosterItem*>(item); + return group ? group->getDisplayedChildren().size() : 0; } -QModelIndex RosterModel::index(QtTreeWidgetItem* item) const { - return createIndex(item->row(), 0, item); +QColor RosterModel::intToColor(int color) const { + return QColor( + ((color & 0xFF0000)>>16), + ((color & 0xFF00)>>8), + (color & 0xFF)); } -QModelIndex RosterModel::parent(const QModelIndex& index) const { - if (!index.isValid()) { - return QModelIndex(); +QColor RosterModel::getTextColor(RosterItem* item) const { + ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(item); + int color = 0; + if (contact) { + switch (contact->getStatusShow()) { + case StatusShow::Online: color = 0x000000; break; + case StatusShow::Away: color = 0x336699; break; + case StatusShow::XA: color = 0x336699; break; + case StatusShow::FFC: color = 0x000000; break; + case StatusShow::DND: color = 0x990000; break; + case StatusShow::None: color = 0x7F7F7F;break; + } } + return intToColor(color); +} + +QColor RosterModel::getBackgroundColor(RosterItem* item) const { + return dynamic_cast<ContactRosterItem*>(item) ? intToColor(0xFFFFFF) : intToColor(0x969696); +} + +QString RosterModel::getToolTip(RosterItem* item) const { + return dynamic_cast<ContactRosterItem*>(item) ? P2QSTRING(item->getDisplayName()) + "\n" + getStatusText(item) : P2QSTRING(item->getDisplayName()); +} + +QIcon RosterModel::getAvatar(RosterItem* item) const { + ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(item); + if (!contact) return QIcon(); + String path = contact->getAvatarPath(); - QtTreeWidgetItem* item = static_cast<QtTreeWidgetItem*>(index.internalPointer()); - Q_ASSERT(item); + return path.isEmpty() ? QIcon() : QIcon(P2QSTRING(path)); +} - QtTreeWidgetItem* parentItem = item->getParentItem(); - /* parentItem_ == NULL can happen during destruction.*/ - return parentItem == tree_ || parentItem == NULL ? QModelIndex() : createIndex(parentItem->row(), 0, parentItem); +QString RosterModel::getStatusText(RosterItem* item) const { + ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(item); + if (!contact) return ""; + return P2QSTRING(contact->getStatusText()); +} +QIcon RosterModel::getPresenceIcon(RosterItem* item) const { + ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(item); + if (!contact) return QIcon(); + QString iconString; + switch (contact->getStatusShow()) { + case StatusShow::Online: iconString = "online";break; + case StatusShow::Away: iconString = "away";break; + case StatusShow::XA: iconString = "away";break; + case StatusShow::FFC: iconString = "online";break; + case StatusShow::DND: iconString = "dnd";break; + case StatusShow::None: iconString = "offline";break; + } + return QIcon(":/icons/" + iconString + ".png"); +} + + +QModelIndex RosterModel::index(int row, int column, const QModelIndex& parent) const { + GroupRosterItem* parentItem; + if (!parent.isValid()) { + //top level + parentItem = roster_->getRoot(); + } else { + parentItem = dynamic_cast<GroupRosterItem*>(getItem(parent)); + if (!parentItem) return QModelIndex(); + } + return (size_t)row < parentItem->getDisplayedChildren().size() ? createIndex(row, column, parentItem->getDisplayedChildren()[row]) : QModelIndex(); +} + +QModelIndex RosterModel::index(RosterItem* item) const { + GroupRosterItem* parent = item->getParent(); + for (size_t i = 0; i < parent->getDisplayedChildren().size(); i++) { + if (parent->getDisplayedChildren()[i] == item) { + return createIndex(i, 0, item); + } + } + return QModelIndex(); +} + +QModelIndex RosterModel::parent(const QModelIndex& child) const { + if (!child.isValid()) { + return QModelIndex(); + } + + GroupRosterItem* parent = getItem(child)->getParent(); + return (parent != roster_->getRoot()) ? index(parent) : QModelIndex(); } int RosterModel::rowCount(const QModelIndex& parent) const { - QtTreeWidgetItem* item = parent.isValid() ? static_cast<QtTreeWidgetItem*>(parent.internalPointer()) : tree_; + if (!roster_) return 0; + RosterItem* item = parent.isValid() ? static_cast<RosterItem*>(parent.internalPointer()) : roster_->getRoot(); Q_ASSERT(item); - - return item->rowCount(); + GroupRosterItem* group = dynamic_cast<GroupRosterItem*>(item); + int count = group ? group->getDisplayedChildren().size() : 0; + qDebug() << "rowCount = " << count << " where parent.isValid() == " << parent.isValid() << ", group == " << (group ? P2QSTRING(group->getDisplayName()) : "*contact*"); + return count; } } diff --git a/Swift/QtUI/Roster/RosterModel.h b/Swift/QtUI/Roster/RosterModel.h index 998f879..17fdd3e 100644 --- a/Swift/QtUI/Roster/RosterModel.h +++ b/Swift/QtUI/Roster/RosterModel.h @@ -6,30 +6,48 @@ #pragma once -#include "Swift/QtUI/Roster/QtTreeWidgetItem.h" +#include "Swiften/Roster/Roster.h" #include <QAbstractItemModel> #include <QList> namespace Swift { -class RosterModel : public QAbstractItemModel { -Q_OBJECT -public: - RosterModel(); - ~RosterModel(); - void setRoot(QtTreeWidgetItem* tree); - int columnCount(const QModelIndex& parent = QModelIndex()) const; - QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; - QModelIndex index(int row, int column, const QModelIndex & parent = QModelIndex()) const; - QModelIndex index(QtTreeWidgetItem* item) const; - QModelIndex parent(const QModelIndex& index) const; - int rowCount(const QModelIndex& parent = QModelIndex()) const; -signals: - void itemExpanded(const QModelIndex& item, bool expanded); -private slots: - void handleItemChanged(QtTreeWidgetItem* item); -private: - QtTreeWidgetItem* tree_; -}; + enum RosterRoles { + StatusTextRole = Qt::UserRole, + AvatarRole = Qt::UserRole + 1, + PresenceIconRole = Qt::UserRole + 2, + StatusShowTypeRole = Qt::UserRole + 3, + ChildCountRole = Qt::UserRole + 4, + }; + class QtTreeWidget; + + class RosterModel : public QAbstractItemModel { + Q_OBJECT + public: + RosterModel(QtTreeWidget* view); + ~RosterModel(); + void setRoster(Roster* swiftRoster); + int columnCount(const QModelIndex& parent = QModelIndex()) const; + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; + QModelIndex index(int row, int column, const QModelIndex & parent = QModelIndex()) const; + QModelIndex index(RosterItem* item) const; + QModelIndex parent(const QModelIndex& index) const; + int rowCount(const QModelIndex& parent = QModelIndex()) const; + private: + void handleDataChanged(RosterItem* item); + void handleChildrenChanged(GroupRosterItem* item); + void handleGroupAdded(GroupRosterItem* group); + RosterItem* getItem(const QModelIndex& index) const; + QColor intToColor(int color) const; + QColor getTextColor(RosterItem* item) const; + QColor getBackgroundColor(RosterItem* item) const; + QString getToolTip(RosterItem* item) const; + QIcon getAvatar(RosterItem* item) const; + QString getStatusText(RosterItem* item) const; + QIcon getPresenceIcon(RosterItem* item) const; + int getChildCount(RosterItem* item) const; + Roster* roster_; + QtTreeWidget* view_; + }; } diff --git a/Swift/QtUI/SConscript b/Swift/QtUI/SConscript index b4f8f64..4311623 100644 --- a/Swift/QtUI/SConscript +++ b/Swift/QtUI/SConscript @@ -80,7 +80,7 @@ sources = [ "SystemMessageSnippet.cpp", "Roster/RosterModel.cpp", "Roster/QtTreeWidget.cpp", - "Roster/QtTreeWidgetItem.cpp", +# "Roster/QtTreeWidgetItem.cpp", "Roster/RosterDelegate.cpp", "Roster/GroupItemDelegate.cpp", "Roster/DelegateCommons.cpp", |