From b9b59d265f44e3e5341635baaac160fe57a5685e Mon Sep 17 00:00:00 2001 From: Catalin Badea Date: Tue, 3 Jul 2012 16:17:51 +0300 Subject: Added message type logging. Fixed handling new messages. diff --git a/Swift/Controllers/Chat/ChatController.cpp b/Swift/Controllers/Chat/ChatController.cpp index 632d760..f40f704 100644 --- a/Swift/Controllers/Chat/ChatController.cpp +++ b/Swift/Controllers/Chat/ChatController.cpp @@ -37,8 +37,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, UIEventStream* eventStream, EventController* eventController, TimerFactory* timerFactory, EntityCapsProvider* entityCapsProvider, bool userWantsReceipts, SettingsProvider* settings, HistoryController* historyController) - : ChatControllerBase(self, stanzaChannel, iqRouter, chatWindowFactory, contact, presenceOracle, avatarManager, useDelayForLatency, eventStream, eventController, timerFactory, entityCapsProvider, historyController), eventStream_(eventStream), userWantsReceipts_(userWantsReceipts), settings_(settings) { +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, bool userWantsReceipts, SettingsProvider* settings, HistoryController* historyController, MUCRegistry* mucRegistry) + : ChatControllerBase(self, stanzaChannel, iqRouter, chatWindowFactory, contact, presenceOracle, avatarManager, useDelayForLatency, eventStream, eventController, timerFactory, entityCapsProvider, historyController, mucRegistry), eventStream_(eventStream), userWantsReceipts_(userWantsReceipts), settings_(settings) { isInMUC_ = isInMUC; lastWasPresence_ = false; chatStateNotifier_ = new ChatStateNotifier(stanzaChannel, contact, entityCapsProvider); @@ -354,8 +354,16 @@ boost::optional ChatController::getMessageTimestamp(bo } void ChatController::logMessage(const std::string& message, const JID& fromJID, const JID& toJID, const boost::posix_time::ptime& timeStamp, bool /* isIncoming */) { + HistoryMessage::Type type; + if (mucRegistry_->isMUC(fromJID.toBare()) || mucRegistry_->isMUC(toJID.toBare())) { + type = HistoryMessage::PrivateMessage; + } + else { + type = HistoryMessage::Chat; + } + if (historyController_) { - historyController_->addMessage(message, fromJID, toJID, false, timeStamp); + historyController_->addMessage(message, fromJID, toJID, type, timeStamp); } } diff --git a/Swift/Controllers/Chat/ChatController.h b/Swift/Controllers/Chat/ChatController.h index daf687d..a873ae9 100644 --- a/Swift/Controllers/Chat/ChatController.h +++ b/Swift/Controllers/Chat/ChatController.h @@ -25,7 +25,7 @@ namespace Swift { 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, bool userWantsReceipts, SettingsProvider* settings, HistoryController* historyController); + 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, bool userWantsReceipts, SettingsProvider* settings, HistoryController* historyController, MUCRegistry* mucRegistry); virtual ~ChatController(); virtual void setToJID(const JID& jid); virtual void setOnline(bool online); diff --git a/Swift/Controllers/Chat/ChatControllerBase.cpp b/Swift/Controllers/Chat/ChatControllerBase.cpp index 4dc4006..754401b 100644 --- a/Swift/Controllers/Chat/ChatControllerBase.cpp +++ b/Swift/Controllers/Chat/ChatControllerBase.cpp @@ -33,7 +33,7 @@ namespace Swift { -ChatControllerBase::ChatControllerBase(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &toJID, PresenceOracle* presenceOracle, AvatarManager* avatarManager, bool useDelayForLatency, UIEventStream* eventStream, EventController* eventController, TimerFactory* timerFactory, EntityCapsProvider* entityCapsProvider, HistoryController* historyController) : selfJID_(self), stanzaChannel_(stanzaChannel), iqRouter_(iqRouter), chatWindowFactory_(chatWindowFactory), toJID_(toJID), labelsEnabled_(false), presenceOracle_(presenceOracle), avatarManager_(avatarManager), useDelayForLatency_(useDelayForLatency), eventController_(eventController), timerFactory_(timerFactory), entityCapsProvider_(entityCapsProvider), historyController_(historyController) { +ChatControllerBase::ChatControllerBase(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &toJID, PresenceOracle* presenceOracle, AvatarManager* avatarManager, bool useDelayForLatency, UIEventStream* eventStream, EventController* eventController, TimerFactory* timerFactory, EntityCapsProvider* entityCapsProvider, HistoryController* historyController, MUCRegistry* mucRegistry) : selfJID_(self), stanzaChannel_(stanzaChannel), iqRouter_(iqRouter), chatWindowFactory_(chatWindowFactory), toJID_(toJID), labelsEnabled_(false), presenceOracle_(presenceOracle), avatarManager_(avatarManager), useDelayForLatency_(useDelayForLatency), eventController_(eventController), timerFactory_(timerFactory), entityCapsProvider_(entityCapsProvider), historyController_(historyController), mucRegistry_(mucRegistry) { chatWindow_ = chatWindowFactory_->createChatWindow(toJID, eventStream); chatWindow_->onAllMessagesRead.connect(boost::bind(&ChatControllerBase::handleAllMessagesRead, this)); chatWindow_->onSendMessageRequest.connect(boost::bind(&ChatControllerBase::handleSendMessageRequest, this, _1, _2)); diff --git a/Swift/Controllers/Chat/ChatControllerBase.h b/Swift/Controllers/Chat/ChatControllerBase.h index 4e7a1da..b26af02 100644 --- a/Swift/Controllers/Chat/ChatControllerBase.h +++ b/Swift/Controllers/Chat/ChatControllerBase.h @@ -28,6 +28,7 @@ #include "Swiften/Queries/IQRouter.h" #include "Swiften/Base/IDGenerator.h" #include +#include namespace Swift { class IQRouter; @@ -59,7 +60,7 @@ namespace Swift { void handleCapsChanged(const JID& jid); protected: - ChatControllerBase(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &toJID, PresenceOracle* presenceOracle, AvatarManager* avatarManager, bool useDelayForLatency, UIEventStream* eventStream, EventController* eventController, TimerFactory* timerFactory, EntityCapsProvider* entityCapsProvider, HistoryController* historyController); + ChatControllerBase(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &toJID, PresenceOracle* presenceOracle, AvatarManager* avatarManager, bool useDelayForLatency, UIEventStream* eventStream, EventController* eventController, TimerFactory* timerFactory, EntityCapsProvider* entityCapsProvider, HistoryController* historyController, MUCRegistry* mucRegistry); /** * Pass the Message appended, and the stanza used to send it. @@ -114,5 +115,6 @@ namespace Swift { EntityCapsProvider* entityCapsProvider_; SecurityLabelsCatalog::Item lastLabel_; HistoryController* historyController_; + MUCRegistry* mucRegistry_; }; } diff --git a/Swift/Controllers/Chat/ChatsManager.cpp b/Swift/Controllers/Chat/ChatsManager.cpp index 3817a41..6b51df6 100644 --- a/Swift/Controllers/Chat/ChatsManager.cpp +++ b/Swift/Controllers/Chat/ChatsManager.cpp @@ -514,7 +514,7 @@ ChatController* ChatsManager::getChatControllerOrFindAnother(const JID &contact) ChatController* ChatsManager::createNewChatController(const JID& contact) { assert(chatControllers_.find(contact) == chatControllers_.end()); - ChatController* controller = new ChatController(jid_, stanzaChannel_, iqRouter_, chatWindowFactory_, contact, nickResolver_, presenceOracle_, avatarManager_, mucRegistry_->isMUC(contact.toBare()), useDelayForLatency_, uiEventStream_, eventController_, timerFactory_, entityCapsProvider_, userWantsReceipts_, settings_, historyController_); + ChatController* controller = new ChatController(jid_, stanzaChannel_, iqRouter_, chatWindowFactory_, contact, nickResolver_, presenceOracle_, avatarManager_, mucRegistry_->isMUC(contact.toBare()), useDelayForLatency_, uiEventStream_, eventController_, timerFactory_, entityCapsProvider_, userWantsReceipts_, settings_, historyController_, mucRegistry_); chatControllers_[contact] = controller; controller->setAvailableServerFeatures(serverDiscoInfo_); controller->onActivity.connect(boost::bind(&ChatsManager::handleChatActivity, this, contact, _1, false)); @@ -587,7 +587,7 @@ void ChatsManager::handleJoinMUCRequest(const JID &mucJID, const boost::optional if (createAsReservedIfNew) { muc->setCreateAsReservedIfNew(); } - MUCController* controller = new MUCController(jid_, muc, password, nick, stanzaChannel_, iqRouter_, chatWindowFactory_, presenceOracle_, avatarManager_, uiEventStream_, false, timerFactory_, eventController_, entityCapsProvider_, roster_, historyController_); + MUCController* controller = new MUCController(jid_, muc, password, nick, stanzaChannel_, iqRouter_, chatWindowFactory_, presenceOracle_, avatarManager_, uiEventStream_, false, timerFactory_, eventController_, entityCapsProvider_, roster_, historyController_, mucRegistry_); mucControllers_[mucJID] = controller; controller->setAvailableServerFeatures(serverDiscoInfo_); controller->onUserLeft.connect(boost::bind(&ChatsManager::handleUserLeftMUC, this, controller)); diff --git a/Swift/Controllers/Chat/MUCController.cpp b/Swift/Controllers/Chat/MUCController.cpp index f86c726..bdc9b20 100644 --- a/Swift/Controllers/Chat/MUCController.cpp +++ b/Swift/Controllers/Chat/MUCController.cpp @@ -60,8 +60,9 @@ MUCController::MUCController ( EventController* eventController, EntityCapsProvider* entityCapsProvider, XMPPRoster* roster, - HistoryController* historyController) : - ChatControllerBase(self, stanzaChannel, iqRouter, chatWindowFactory, muc->getJID(), presenceOracle, avatarManager, useDelayForLatency, uiEventStream, eventController, timerFactory, entityCapsProvider, historyController), muc_(muc), nick_(nick), desiredNick_(nick), password_(password) { + HistoryController* historyController, + MUCRegistry* mucRegistry) : + ChatControllerBase(self, stanzaChannel, iqRouter, chatWindowFactory, muc->getJID(), presenceOracle, avatarManager, useDelayForLatency, uiEventStream, eventController, timerFactory, entityCapsProvider, historyController, mucRegistry), muc_(muc), nick_(nick), desiredNick_(nick), password_(password) { parting_ = true; joined_ = false; lastWasPresence_ = false; @@ -783,7 +784,7 @@ void MUCController::handleAffiliationListReceived(MUCOccupant::Affiliation affil void MUCController::logMessage(const std::string& message, const JID& fromJID, const JID& toJID, const boost::posix_time::ptime& timeStamp, bool isIncoming) { // log only incoming messages if (isIncoming && historyController_) { - historyController_->addMessage(message, fromJID, toJID, true, timeStamp); + historyController_->addMessage(message, fromJID, toJID, HistoryMessage::Groupchat, timeStamp); } } diff --git a/Swift/Controllers/Chat/MUCController.h b/Swift/Controllers/Chat/MUCController.h index 41393cd..0c6cfa4 100644 --- a/Swift/Controllers/Chat/MUCController.h +++ b/Swift/Controllers/Chat/MUCController.h @@ -44,7 +44,7 @@ namespace Swift { class MUCController : public ChatControllerBase { public: - MUCController(const JID& self, MUC::ref muc, const boost::optional& password, const std::string &nick, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, PresenceOracle* presenceOracle, AvatarManager* avatarManager, UIEventStream* events, bool useDelayForLatency, TimerFactory* timerFactory, EventController* eventController, EntityCapsProvider* entityCapsProvider, XMPPRoster* roster, HistoryController* historyController); + MUCController(const JID& self, MUC::ref muc, const boost::optional& password, const std::string &nick, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, PresenceOracle* presenceOracle, AvatarManager* avatarManager, UIEventStream* events, bool useDelayForLatency, TimerFactory* timerFactory, EventController* eventController, EntityCapsProvider* entityCapsProvider, XMPPRoster* roster, HistoryController* historyController, MUCRegistry* mucRegistry); ~MUCController(); boost::signal onUserLeft; boost::signal onUserJoined; diff --git a/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp b/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp index cb069a4..4f37229 100644 --- a/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp +++ b/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp @@ -64,7 +64,7 @@ public: entityCapsProvider_ = new DummyEntityCapsProvider(); muc_ = boost::make_shared(stanzaChannel_, iqRouter_, directedPresenceSender_, mucJID_, mucRegistry_); mocks_->ExpectCall(chatWindowFactory_, ChatWindowFactory::createChatWindow).With(muc_->getJID(), uiEventStream_).Return(window_); - controller_ = new MUCController (self_, muc_, boost::optional(), nick_, stanzaChannel_, iqRouter_, chatWindowFactory_, presenceOracle_, avatarManager_, uiEventStream_, false, timerFactory, eventController_, entityCapsProvider_, NULL, NULL); + controller_ = new MUCController (self_, muc_, boost::optional(), nick_, stanzaChannel_, iqRouter_, chatWindowFactory_, presenceOracle_, avatarManager_, uiEventStream_, false, timerFactory, eventController_, entityCapsProvider_, NULL, NULL, mucRegistry_); }; void tearDown() { diff --git a/Swift/Controllers/HistoryController.cpp b/Swift/Controllers/HistoryController.cpp index 5bd4ffa..fe54e79 100644 --- a/Swift/Controllers/HistoryController.cpp +++ b/Swift/Controllers/HistoryController.cpp @@ -19,18 +19,18 @@ HistoryController::~HistoryController() { delete localHistory_; } -void HistoryController::addMessage(const std::string& message, const JID& fromJID, const JID& toJID, bool isGroupChat, const boost::posix_time::ptime& timeStamp) { - HistoryMessage historyMessage(message, fromJID, toJID, isGroupChat, timeStamp); +void HistoryController::addMessage(const std::string& message, const JID& fromJID, const JID& toJID, HistoryMessage::Type type, const boost::posix_time::ptime& timeStamp) { + HistoryMessage historyMessage(message, fromJID, toJID, type, timeStamp); localHistory_->addMessage(historyMessage); onNewMessage(historyMessage); } -std::vector HistoryController::getMessages(const JID& selfJID, const JID& contactJID, bool isGroupChat) const { - return localHistory_->getMessages(selfJID, contactJID, isGroupChat); +std::vector HistoryController::getMessages(const JID& selfJID, const JID& contactJID, HistoryMessage::Type type) const { + return localHistory_->getMessages(selfJID, contactJID, type); } -void HistoryController::getAllContacts(const JID& selfJID, std::set& mucs, std::set& contacts) const { - return localHistory_->getAllContacts(selfJID, mucs, contacts); +std::set HistoryController::getContacts(const JID& selfJID, HistoryMessage::Type type) const { + return localHistory_->getContacts(selfJID, type); } } diff --git a/Swift/Controllers/HistoryController.h b/Swift/Controllers/HistoryController.h index babda8a..c08e112 100644 --- a/Swift/Controllers/HistoryController.h +++ b/Swift/Controllers/HistoryController.h @@ -11,10 +11,10 @@ #include #include #include +#include namespace Swift { class HistoryManager; - class HistoryMessage; class JID; class HistoryController { @@ -22,9 +22,9 @@ namespace Swift { HistoryController(); ~HistoryController(); - void addMessage(const std::string& message, const JID& fromJID, const JID& toJID, bool isGroupChat, const boost::posix_time::ptime& timeStamp); - std::vector getMessages(const JID& selfJID, const JID& contactJID, bool isGroupChat) const; - void getAllContacts(const JID& selfJID, std::set& mucs, std::set& contacts) const; + void addMessage(const std::string& message, const JID& fromJID, const JID& toJID, HistoryMessage::Type type, const boost::posix_time::ptime& timeStamp); + std::vector getMessages(const JID& selfJID, const JID& contactJID, HistoryMessage::Type type) const; + std::set getContacts(const JID& selfJID, HistoryMessage::Type type) const; boost::signal onNewMessage; diff --git a/Swift/Controllers/HistoryViewController.cpp b/Swift/Controllers/HistoryViewController.cpp index a67f6cd..18e27bd 100644 --- a/Swift/Controllers/HistoryViewController.cpp +++ b/Swift/Controllers/HistoryViewController.cpp @@ -48,6 +48,7 @@ HistoryViewController::~HistoryViewController() { } void HistoryViewController::handleUIEvent(boost::shared_ptr rawEvent) { + // TODO: add new nick manager boost::shared_ptr event = boost::dynamic_pointer_cast(rawEvent); if (event != NULL) { if (historyWindow_ == NULL) { @@ -56,13 +57,31 @@ void HistoryViewController::handleUIEvent(boost::shared_ptr rawEvent) { historyWindow_->setRosterModel(roster_); - historyController_->getAllContacts(selfJID_, rooms_, contacts_); + // MUCs + std::set rooms = historyController_->getContacts(selfJID_, HistoryMessage::Groupchat); + foreach (const JID& room, rooms) { + if ( !rooms_.count(room)) { + roster_->addContact(room, room, nickResolver_->jidToNick(room), "MUC", avatarManager_->getAvatarPath(room).string()); + rooms_.insert(room); + } + } - foreach (const JID& muc, rooms_) { - roster_->addContact(muc, muc, nickResolver_->jidToNick(muc), "MUC", byteArrayToString(avatarManager_->getAvatar(muc))); + // Contacts + std::set contacts = historyController_->getContacts(selfJID_, HistoryMessage::Chat); + foreach (const JID& contact, contacts) { + if (!contacts_.count(contact)) { + roster_->addContact(contact, contact, nickResolver_->jidToNick(contact), "Contacts", avatarManager_->getAvatarPath(contact).string()); + contacts_.insert(contact); + } } - foreach (const JID& contact, contacts_) { - roster_->addContact(contact, contact, nickResolver_->jidToNick(contact), "Contacts", byteArrayToString(avatarManager_->getAvatar(contact))); + + // MUC contacts + std::set roomPrivateContacts = historyController_->getContacts(selfJID_, HistoryMessage::PrivateMessage); + foreach (const JID& contact, roomPrivateContacts) { + if ( !roomPrivateContacts_.count(contact)) { + roster_->addContact(contact, contact, nickResolver_->jidToNick(contact), "Contacts", avatarManager_->getAvatarPath(contact).string()); + roomPrivateContacts_.insert(contact); + } } } @@ -72,38 +91,68 @@ void HistoryViewController::handleUIEvent(boost::shared_ptr rawEvent) { void HistoryViewController::handleSelectedContactChanged(RosterItem* newContact) { // FIXME: signal is triggerd twice. - selectedItem_ = dynamic_cast(newContact); + ContactRosterItem* contact = dynamic_cast(newContact); - if (newContact == NULL) { + if (contact && selectedItem_ != contact) { + selectedItem_ = contact; + historyWindow_->resetConversationView(); + } + else { return; } - ContactRosterItem* contact = dynamic_cast(newContact); JID contactJID = contact->getJID(); - bool isRoom = rooms_.count(contactJID); - std::vector messages = historyController_->getMessages(selfJID_, contactJID, isRoom); + std::vector messages; + if (roomPrivateContacts_.count(contactJID)) { + messages = historyController_->getMessages(selfJID_, contactJID, HistoryMessage::PrivateMessage); + } + else if (contacts_.count(contactJID)) { + messages = historyController_->getMessages(selfJID_, contactJID, HistoryMessage::Chat); + } + else { + messages = historyController_->getMessages(selfJID_, contactJID, HistoryMessage::Groupchat); + } + foreach (const HistoryMessage& message, messages) { - bool senderIsSelf = message.getFromJID() == selfJID_; - std::string avatarPath = byteArrayToString(avatarManager_->getAvatar(message.getFromJID())); - historyWindow_->addMessage(message.getMessage(), nickResolver_->jidToNick(message.getFromJID()), senderIsSelf, avatarPath, message.getTime()); + addNewMessage(message); } } void HistoryViewController::handleNewMessage(const HistoryMessage& message) { JID contactJID = message.getFromJID().toBare() == selfJID_ ? message.getToJID() : message.getFromJID(); - if (selectedItem_ && selectedItem_->getJID().toBare() == contactJID) { - bool senderIsSelf = message.getFromJID().toBare() == selfJID_; - std::string avatarPath = byteArrayToString(avatarManager_->getAvatar(message.getFromJID())); - historyWindow_->addMessage(message.getMessage(), nickResolver_->jidToNick(message.getFromJID()), senderIsSelf, avatarPath, message.getTime()); + JID displayJID; + if (message.getType() == HistoryMessage::PrivateMessage) { + displayJID = contactJID; + } + else { + displayJID = contactJID.toBare(); + } + + // check current conversation + if (selectedItem_ && selectedItem_->getJID() == displayJID) { + addNewMessage(message); } - else if (!rooms_.count(contactJID.toBare()) && message.isGroupChat()) { - roster_->addContact(contactJID.toBare(), contactJID.toBare(), nickResolver_->jidToNick(contactJID.toBare()), "MUC", byteArrayToString(avatarManager_->getAvatar(contactJID.toBare()))); + // add new contact + else if (message.getType() == HistoryMessage::Groupchat && !rooms_.count(displayJID)) { + roster_->addContact(displayJID, displayJID, nickResolver_->jidToNick(displayJID), "MUC", avatarManager_->getAvatarPath(displayJID).string()); + rooms_.insert(displayJID); } - else if (!contacts_.count(contactJID) && !message.isGroupChat()) { - roster_->addContact(contactJID, contactJID, nickResolver_->jidToNick(contactJID), "Contacts", byteArrayToString(avatarManager_->getAvatar(contactJID))); + else if (message.getType() == HistoryMessage::Chat && !contacts_.count(displayJID)) { + roster_->addContact(displayJID, displayJID, nickResolver_->jidToNick(displayJID), "Contacts", avatarManager_->getAvatarPath(displayJID).string()); + contacts_.insert(displayJID); } + else if (message.getType() == HistoryMessage::PrivateMessage && !roomPrivateContacts_.count(displayJID)) { + roster_->addContact(displayJID, displayJID, nickResolver_->jidToNick(displayJID), "Contacts", avatarManager_->getAvatarPath(displayJID).string()); + roomPrivateContacts_.insert(displayJID); + } +} + +void HistoryViewController::addNewMessage(const HistoryMessage& message) { + bool senderIsSelf = message.getFromJID().toBare() == selfJID_; + std::string avatarPath = avatarManager_->getAvatarPath(message.getFromJID()).string(); + historyWindow_->addMessage(message.getMessage(), nickResolver_->jidToNick(message.getFromJID()), senderIsSelf, avatarPath, message.getTime()); } } diff --git a/Swift/Controllers/HistoryViewController.h b/Swift/Controllers/HistoryViewController.h index 4f43f47..4957e37 100644 --- a/Swift/Controllers/HistoryViewController.h +++ b/Swift/Controllers/HistoryViewController.h @@ -34,6 +34,7 @@ namespace Swift { void handleUIEvent(boost::shared_ptr event); void handleSelectedContactChanged(RosterItem* item); void handleNewMessage(const HistoryMessage& message); + void addNewMessage(const HistoryMessage& message); private: JID selfJID_; @@ -45,8 +46,9 @@ namespace Swift { HistoryWindow* historyWindow_; Roster* roster_; - std::set rooms_; std::set contacts_; + std::set rooms_; + std::set roomPrivateContacts_; ContactRosterItem* selectedItem_; }; } diff --git a/Swift/Controllers/UIInterfaces/HistoryWindow.h b/Swift/Controllers/UIInterfaces/HistoryWindow.h index d51b65d..cd232f1 100644 --- a/Swift/Controllers/UIInterfaces/HistoryWindow.h +++ b/Swift/Controllers/UIInterfaces/HistoryWindow.h @@ -16,6 +16,7 @@ namespace Swift { virtual void activate() = 0; virtual void setRosterModel(Roster*) = 0; virtual void addMessage(const std::string &message, const std::string &senderName, bool senderIsSelf, const std::string& avatarPath, const boost::posix_time::ptime& time) = 0; + virtual void resetConversationView() = 0; boost::signal onSelectedContactChanged; }; diff --git a/Swift/QtUI/QtHistoryWindow.cpp b/Swift/QtUI/QtHistoryWindow.cpp index 122655a..50fd66e 100644 --- a/Swift/QtUI/QtHistoryWindow.cpp +++ b/Swift/QtUI/QtHistoryWindow.cpp @@ -89,8 +89,11 @@ void QtHistoryWindow::addMessage(const std::string &message, const std::string & void QtHistoryWindow::handleSomethingSelectedChanged(RosterItem* item) { - conversation_->resetView(); onSelectedContactChanged(item); } +void QtHistoryWindow::resetConversationView() { + conversation_->resetView(); +} + } diff --git a/Swift/QtUI/QtHistoryWindow.h b/Swift/QtUI/QtHistoryWindow.h index 965abf7..279657d 100644 --- a/Swift/QtUI/QtHistoryWindow.h +++ b/Swift/QtUI/QtHistoryWindow.h @@ -22,6 +22,7 @@ namespace Swift { void activate(); void setRosterModel(Roster*); void addMessage(const std::string &message, const std::string &senderName, bool senderIsSelf, const std::string& avatarPath, const boost::posix_time::ptime& time); + void resetConversationView(); private: virtual void closeEvent(QCloseEvent* event); diff --git a/Swiften/History/HistoryManager.h b/Swiften/History/HistoryManager.h index a10bb41..bc1680b 100644 --- a/Swiften/History/HistoryManager.h +++ b/Swiften/History/HistoryManager.h @@ -18,7 +18,7 @@ namespace Swift { virtual void addMessage(const HistoryMessage& message) = 0; - virtual std::vector getMessages(const JID& selfJID, const JID& contactJID, bool isGroupChat) const = 0; - virtual void getAllContacts(const JID& selfJID, std::set& mucs, std::set& contacts) const = 0; + virtual std::vector getMessages(const JID& selfJID, const JID& contactJID, HistoryMessage::Type type) const = 0; + virtual std::set getContacts(const JID& selfJID, HistoryMessage::Type type) const = 0; }; } diff --git a/Swiften/History/HistoryMessage.h b/Swiften/History/HistoryMessage.h index 021d6b9..d35474f 100644 --- a/Swiften/History/HistoryMessage.h +++ b/Swiften/History/HistoryMessage.h @@ -12,16 +12,22 @@ namespace Swift { class HistoryMessage { public: + enum Type { + Chat = 0, + Groupchat = 1, + PrivateMessage = 2 + }; + HistoryMessage( const std::string& message, const JID& fromJID, const JID& toJID, - bool isGroupChat, + Type type, const boost::posix_time::ptime& time) : message_(message), fromJID_(fromJID), toJID_(toJID), - isGroupChat_(isGroupChat), + type_(type), time_(time) { } @@ -37,8 +43,8 @@ namespace Swift { return toJID_; } - bool isGroupChat() const { - return isGroupChat_; + Type getType() const { + return type_; } boost::posix_time::ptime getTime() const { @@ -46,14 +52,14 @@ namespace Swift { } bool operator==(const HistoryMessage& o) const { - return message_ == o.message_ && fromJID_ == o.fromJID_ && toJID_ == o.toJID_ && isGroupChat_ == o.isGroupChat_ && time_ == o.time_; + return message_ == o.message_ && fromJID_ == o.fromJID_ && toJID_ == o.toJID_ && type_ == o.type_ && time_ == o.time_; } private: std::string message_; JID fromJID_; JID toJID_; - bool isGroupChat_; // TODO: <- maybe use Message::Type ? + Type type_; boost::posix_time::ptime time_; }; } diff --git a/Swiften/History/SQLiteHistoryManager.cpp b/Swiften/History/SQLiteHistoryManager.cpp index af09b66..3304a07 100644 --- a/Swiften/History/SQLiteHistoryManager.cpp +++ b/Swiften/History/SQLiteHistoryManager.cpp @@ -30,7 +30,7 @@ SQLiteHistoryManager::SQLiteHistoryManager(const std::string& file) : db_(0) { } char* errorMessage; - int result = sqlite3_exec(db_, "CREATE TABLE IF NOT EXISTS messages('message' STRING, 'fromBare' INTEGER, 'fromResource' STRING, 'toBare' INTEGER, 'toResource' STRING, 'groupChat' INTEGER, 'time' INTEGER)", 0, 0, &errorMessage); + int result = sqlite3_exec(db_, "CREATE TABLE IF NOT EXISTS messages('message' STRING, 'fromBare' INTEGER, 'fromResource' STRING, 'toBare' INTEGER, 'toResource' STRING, 'type' INTEGER, 'time' INTEGER)", 0, 0, &errorMessage); if (result != SQLITE_OK) { std::cerr << "SQL Error: " << errorMessage << std::endl; sqlite3_free(errorMessage); @@ -50,13 +50,13 @@ SQLiteHistoryManager::~SQLiteHistoryManager() { void SQLiteHistoryManager::addMessage(const HistoryMessage& message) { int secondsSinceEpoch = (message.getTime() - boost::posix_time::ptime(boost::gregorian::date(1970, 1, 1))).total_seconds(); - std::string statement = std::string("INSERT INTO messages('message', 'fromBare', 'fromResource', 'toBare', 'toResource', 'groupChat', 'time') VALUES(") + + std::string statement = std::string("INSERT INTO messages('message', 'fromBare', 'fromResource', 'toBare', 'toResource', 'type', 'time') VALUES(") + "'" + getEscapedString(message.getMessage()) + "', " + boost::lexical_cast(getIDForJID(message.getFromJID().toBare())) + ", '" + getEscapedString(message.getFromJID().getResource()) + "', " + boost::lexical_cast(getIDForJID(message.getToJID().toBare())) + ", '" + getEscapedString(message.getToJID().getResource()) + "', " + - boost::lexical_cast(message.isGroupChat()) + ", " + + boost::lexical_cast(message.getType()) + ", " + boost::lexical_cast(secondsSinceEpoch) + ")"; char* errorMessage; int result = sqlite3_exec(db_, statement.c_str(), 0, 0, &errorMessage); @@ -66,7 +66,7 @@ void SQLiteHistoryManager::addMessage(const HistoryMessage& message) { } } -std::vector SQLiteHistoryManager::getMessages(const JID& selfJID, const JID& contactJID, bool isGroupChat) const { +std::vector SQLiteHistoryManager::getMessages(const JID& selfJID, const JID& contactJID, HistoryMessage::Type type) const { sqlite3_stmt* selectStatement; boost::optional selfID = getIDFromJID(selfJID.toBare()); @@ -77,7 +77,7 @@ std::vector SQLiteHistoryManager::getMessages(const JID& selfJID return std::vector(); } - std::string selectQuery = "SELECT * FROM messages WHERE groupChat=" + boost::lexical_cast(isGroupChat); + std::string selectQuery = "SELECT * FROM messages WHERE type=" + boost::lexical_cast(type); if (contactJID.isBare()) { // match only bare jid selectQuery += " AND ((fromBare=" + boost::lexical_cast(*selfID) + " AND toBare=" + @@ -120,13 +120,13 @@ std::vector SQLiteHistoryManager::getMessages(const JID& selfJID } // message type - bool isGroupChat = sqlite3_column_int(selectStatement, 5); + HistoryMessage::Type type = static_cast(sqlite3_column_int(selectStatement, 5)); // timestamp int secondsSinceEpoch(sqlite3_column_int(selectStatement, 6)); boost::posix_time::ptime time(boost::gregorian::date(1970, 1, 1), boost::posix_time::seconds(secondsSinceEpoch)); - result.push_back(HistoryMessage(message, (fromJID ? *fromJID : JID()), (toJID ? *toJID : JID()), isGroupChat, time)); + result.push_back(HistoryMessage(message, (fromJID ? *fromJID : JID()), (toJID ? *toJID : JID()), type, time)); r = sqlite3_step(selectStatement); } if (r != SQLITE_DONE) { @@ -190,42 +190,22 @@ boost::optional SQLiteHistoryManager::getIDFromJID(const JID& jid) const { return result; } -void SQLiteHistoryManager::getAllContacts(const JID& selfJID, std::set& mucs, std::set& contacts) const { +std::set SQLiteHistoryManager::getContacts(const JID& selfJID, HistoryMessage::Type type) const { + std::set result; + sqlite3_stmt* selectStatement; + // get id boost::optional id = getIDFromJID(selfJID); if (!id) { - return; + return result; } - // get all MUCs - std::string query = "SELECT DISTINCT messages.'fromBare' FROM messages WHERE groupChat=1 AND toBare=" + boost::lexical_cast(*id); - sqlite3_stmt* selectStatement; - - int r = sqlite3_prepare(db_, query.c_str(), query.size(), &selectStatement, NULL); - if (r != SQLITE_OK) { - std::cout << "Error: " << sqlite3_errmsg(db_) << std::endl; - } - - r = sqlite3_step(selectStatement); - while (r == SQLITE_ROW) { - boost::optional contactJID(getJIDFromID(sqlite3_column_int(selectStatement, 0))); - if (contactJID) { - mucs.insert(*contactJID); - } - - r = sqlite3_step(selectStatement); - } - - if (r != SQLITE_DONE) { - std::cout << "Error: " << sqlite3_errmsg(db_) << std::endl; - } - sqlite3_finalize(selectStatement); - - // get all contacts - query = "SELECT DISTINCT messages.'fromBare', messages.'fromResource', messages.'toBare', messages.'toResource' FROM messages WHERE groupChat=0 AND (toBare=" + // get contacts + std::string query = "SELECT DISTINCT messages.'fromBare', messages.'fromResource', messages.'toBare', messages.'toResource' FROM messages WHERE type=" + + boost::lexical_cast(type) + " AND (toBare=" + boost::lexical_cast(*id) + " OR fromBare=" + boost::lexical_cast(*id) + ")"; - r = sqlite3_prepare(db_, query.c_str(), query.size(), &selectStatement, NULL); + int r = sqlite3_prepare(db_, query.c_str(), query.size(), &selectStatement, NULL); if (r != SQLITE_OK) { std::cout << "Error: " << sqlite3_errmsg(db_) << std::endl; } @@ -250,12 +230,12 @@ void SQLiteHistoryManager::getAllContacts(const JID& selfJID, std::set& muc } // check if it is a MUC contact (from a private conversation) - if (contactJID && mucs.count(*contactJID)) { + if (type == HistoryMessage::PrivateMessage) { contactJID = boost::optional(JID(contactJID->getNode(), contactJID->getDomain(), resource)); } if (contactJID) { - contacts.insert(*contactJID); + result.insert(*contactJID); } r = sqlite3_step(selectStatement); @@ -265,6 +245,8 @@ void SQLiteHistoryManager::getAllContacts(const JID& selfJID, std::set& muc std::cout << "Error: " << sqlite3_errmsg(db_) << std::endl; } sqlite3_finalize(selectStatement); + + return result; } } diff --git a/Swiften/History/SQLiteHistoryManager.h b/Swiften/History/SQLiteHistoryManager.h index 480d570..fce30f8 100644 --- a/Swiften/History/SQLiteHistoryManager.h +++ b/Swiften/History/SQLiteHistoryManager.h @@ -19,8 +19,8 @@ namespace Swift { ~SQLiteHistoryManager(); void addMessage(const HistoryMessage& message); - std::vector getMessages(const JID& selfJID, const JID& contactJID, bool isGroupChat) const; - void getAllContacts(const JID& selfJID, std::set& mucs, std::set& contacts) const; + std::vector getMessages(const JID& selfJID, const JID& contactJID, HistoryMessage::Type type) const; + std::set getContacts(const JID& selfJID, HistoryMessage::Type type) const; private: int getIDForJID(const JID&); -- cgit v0.10.2-6-g49f6