/* * Copyright (c) 2012 Catalin Badea * Licensed under the simplified BSD license. * See Documentation/Licenses/BSD-simplified.txt for more information. */ #include #include #include #include #include #include #include #include namespace Swift { HistoryViewController::HistoryViewController( const JID& selfJID, UIEventStream* uiEventStream, HistoryController* historyController, NickResolver* nickResolver, AvatarManager* avatarManager, HistoryWindowFactory* historyWindowFactory) : selfJID_(selfJID), uiEventStream_(uiEventStream), historyController_(historyController), nickResolver_(nickResolver), avatarManager_(avatarManager), historyWindowFactory_(historyWindowFactory), historyWindow_(NULL), selectedItem_(NULL), currentResultDate_(boost::gregorian::not_a_date_time) { uiEventStream_->onUIEvent.connect(boost::bind(&HistoryViewController::handleUIEvent, this, _1)); historyController_->onNewMessage.connect(boost::bind(&HistoryViewController::handleNewMessage, this, _1)); roster_ = new Roster(false, true); } HistoryViewController::~HistoryViewController() { uiEventStream_->onUIEvent.disconnect(boost::bind(&HistoryViewController::handleUIEvent, this, _1)); historyController_->onNewMessage.disconnect(boost::bind(&HistoryViewController::handleNewMessage, this, _1)); if (historyWindow_) { historyWindow_->onSelectedContactChanged.disconnect(boost::bind(&HistoryViewController::handleSelectedContactChanged, this, _1)); historyWindow_->onReturnPressed.disconnect(boost::bind(&HistoryViewController::handleReturnPressed, this, _1)); historyWindow_->onScrollReachedTop.disconnect(boost::bind(&HistoryViewController::handleScrollReachedTop, this, _1)); historyWindow_->onScrollReachedBottom.disconnect(boost::bind(&HistoryViewController::handleScrollReachedBottom, this, _1)); delete historyWindow_; } delete roster_; } 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) { historyWindow_ = historyWindowFactory_->createHistoryWindow(uiEventStream_); historyWindow_->onSelectedContactChanged.connect(boost::bind(&HistoryViewController::handleSelectedContactChanged, this, _1)); historyWindow_->onReturnPressed.connect(boost::bind(&HistoryViewController::handleReturnPressed, this, _1)); historyWindow_->onScrollReachedTop.connect(boost::bind(&HistoryViewController::handleScrollReachedTop, this, _1)); historyWindow_->onScrollReachedBottom.connect(boost::bind(&HistoryViewController::handleScrollReachedBottom, this, _1)); historyWindow_->setRosterModel(roster_); } // populate roster by doing an empty search handleReturnPressed(std::string()); historyWindow_->activate(); } } void HistoryViewController::handleSelectedContactChanged(RosterItem* newContact) { // FIXME: signal is triggerd twice. ContactRosterItem* contact = dynamic_cast(newContact); if (contact && selectedItem_ != contact) { selectedItem_ = contact; historyWindow_->resetConversationView(); } else { return; } JID contactJID = contact->getJID(); std::vector messages; if (roomPrivateContacts_.count(contactJID)) { currentResultDate_ = *roomPrivateContacts_[contactJID].rbegin(); messages = historyController_->getMessagesFromDate(selfJID_, contactJID, HistoryMessage::PrivateMessage, currentResultDate_); currentItemType_ = HistoryMessage::PrivateMessage; } else if (contacts_.count(contactJID)) { currentResultDate_ = *contacts_[contactJID].rbegin(); messages = historyController_->getMessagesFromDate(selfJID_, contactJID, HistoryMessage::Chat, currentResultDate_); currentItemType_ = HistoryMessage::Chat; } else { currentResultDate_ = *rooms_[contactJID].rbegin(); messages = historyController_->getMessagesFromDate(selfJID_, contactJID, HistoryMessage::Groupchat, currentResultDate_); currentItemType_ = HistoryMessage::Groupchat; } historyWindow_->setDate(currentResultDate_); foreach (const HistoryMessage& message, messages) { addNewMessage(message, false); } } void HistoryViewController::handleNewMessage(const HistoryMessage& message) { JID contactJID = message.getFromJID().toBare() == selfJID_ ? message.getToJID() : message.getFromJID(); JID displayJID; if (message.getType() == HistoryMessage::PrivateMessage) { displayJID = contactJID; } else { displayJID = contactJID.toBare(); } // check current conversation if (selectedItem_ && selectedItem_->getJID() == displayJID) { addNewMessage(message, false); } // add new contact else if (message.getType() == HistoryMessage::Groupchat && !rooms_.count(displayJID)) { roster_->addContact(displayJID, displayJID, nickResolver_->jidToNick(displayJID), "MUC", avatarManager_->getAvatarPath(displayJID).string()); // // TODO add message date here rooms_[displayJID] = std::set(); } else if (message.getType() == HistoryMessage::Chat && !contacts_.count(displayJID)) { roster_->addContact(displayJID, displayJID, nickResolver_->jidToNick(displayJID), "Contacts", avatarManager_->getAvatarPath(displayJID).string()); contacts_[displayJID] = std::set(); } else if (message.getType() == HistoryMessage::PrivateMessage && !roomPrivateContacts_.count(displayJID)) { roster_->addContact(displayJID, displayJID, nickResolver_->jidToNick(displayJID), "Contacts", avatarManager_->getAvatarPath(displayJID).string()); roomPrivateContacts_[displayJID] = std::set(); } } void HistoryViewController::addNewMessage(const HistoryMessage& message, bool addAtTheTop) { 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(), addAtTheTop); } void HistoryViewController::handleReturnPressed(const std::string& keyword) { roster_->removeAll(); rooms_.clear(); contacts_.clear(); roomPrivateContacts_.clear(); selectedItem_ = NULL; historyWindow_->resetConversationView(); // MUCs rooms_ = historyController_->getContacts(selfJID_, HistoryMessage::Groupchat, keyword); for (ContactsMap::const_iterator room = rooms_.begin(); room != rooms_.end(); room++) { const JID& jid = room->first; roster_->addContact(jid, jid, nickResolver_->jidToNick(jid), "MUC", avatarManager_->getAvatarPath(jid).string()); } // Contacts contacts_ = historyController_->getContacts(selfJID_, HistoryMessage::Chat, keyword); for (ContactsMap::const_iterator contact = contacts_.begin(); contact != contacts_.end(); contact++) { const JID& jid = contact->first; roster_->addContact(jid, jid, nickResolver_->jidToNick(jid), "Contacts", avatarManager_->getAvatarPath(jid).string()); } // MUC contacts roomPrivateContacts_ = historyController_->getContacts(selfJID_, HistoryMessage::PrivateMessage, keyword); for (ContactsMap::const_iterator contact = roomPrivateContacts_.begin(); contact != roomPrivateContacts_.end(); contact++) { const JID& jid = contact->first; roster_->addContact(jid, jid, nickResolver_->jidToNick(jid), "Contacts", avatarManager_->getAvatarPath(jid).string()); } } void HistoryViewController::handleScrollReachedTop(const boost::gregorian::date& date) { std::vector messages = historyController_->getMessagesFromPreviousDate(selfJID_, selectedItem_->getJID(), currentItemType_, date); reverse_foreach (const HistoryMessage& message, messages) { addNewMessage(message, true); } } void HistoryViewController::handleScrollReachedBottom(const boost::gregorian::date& date) { std::vector messages = historyController_->getMessagesFromNextDate(selfJID_, selectedItem_->getJID(), currentItemType_, date); foreach (const HistoryMessage& message, messages) { addNewMessage(message, true); } } }