diff options
Diffstat (limited to 'Swift/Controllers/Roster/Roster.cpp')
-rw-r--r-- | Swift/Controllers/Roster/Roster.cpp | 388 |
1 files changed, 197 insertions, 191 deletions
diff --git a/Swift/Controllers/Roster/Roster.cpp b/Swift/Controllers/Roster/Roster.cpp index 9b45b63..5b7e454 100644 --- a/Swift/Controllers/Roster/Roster.cpp +++ b/Swift/Controllers/Roster/Roster.cpp @@ -1,261 +1,267 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include "Swift/Controllers/Roster/Roster.h" +#include <Swift/Controllers/Roster/Roster.h> -#include "Swiften/Base/foreach.h" +#include <algorithm> +#include <deque> +#include <memory> +#include <set> #include <string> -#include "Swiften/JID/JID.h" -#include "Swift/Controllers/Roster/ContactRosterItem.h" -#include "Swift/Controllers/Roster/RosterItem.h" -#include "Swift/Controllers/Roster/GroupRosterItem.h" -#include "Swift/Controllers/Roster/RosterItemOperation.h" #include <boost/bind.hpp> -#include <iostream> -#include <set> -#include <deque> +#include <Swiften/JID/JID.h> + +#include <Swift/Controllers/Roster/ContactRosterItem.h> +#include <Swift/Controllers/Roster/GroupRosterItem.h> +#include <Swift/Controllers/Roster/ItemOperations/RosterItemOperation.h> +#include <Swift/Controllers/Roster/RosterItem.h> namespace Swift { -Roster::Roster(bool sortByStatus, bool fullJIDMapping) : blockingSupported_(false) { - sortByStatus_ = sortByStatus; - fullJIDMapping_ = fullJIDMapping; - root_ = new GroupRosterItem("Dummy-Root", NULL, sortByStatus_); - root_->onChildrenChanged.connect(boost::bind(&Roster::handleChildrenChanged, this, root_)); +Roster::Roster(bool sortByStatus, bool fullJIDMapping) : fullJIDMapping_(fullJIDMapping), sortByStatus_(sortByStatus), root_(std::make_unique<GroupRosterItem>("Dummy-Root", nullptr, sortByStatus_)) { + root_->onChildrenChanged.connect(boost::bind(&Roster::handleChildrenChanged, this, root_.get())); } Roster::~Roster() { - std::deque<RosterItem*> queue; - queue.push_back(root_); - while (!queue.empty()) { - RosterItem* item = *queue.begin(); - queue.pop_front(); - GroupRosterItem* group = dynamic_cast<GroupRosterItem*>(item); - if (group) { - queue.insert(queue.begin(), group->getChildren().begin(), group->getChildren().end()); - } - delete item; - } + std::deque<RosterItem*> queue; + while (!queue.empty()) { + RosterItem* item = *queue.begin(); + queue.pop_front(); + GroupRosterItem* group = dynamic_cast<GroupRosterItem*>(item); + if (group) { + queue.insert(queue.begin(), group->getChildren().begin(), group->getChildren().end()); + } + ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(item); + if (contact) { + contact->onVCardRequested.disconnect(boost::bind(boost::ref(onVCardUpdateRequested), contact->getJID())); + } + delete item; + } } -GroupRosterItem* Roster::getRoot() { - return root_; +GroupRosterItem* Roster::getRoot() const { + return root_.get(); } -GroupRosterItem* Roster::getGroup(const std::string& groupName) { - foreach (RosterItem *item, root_->getChildren()) { - GroupRosterItem *group = dynamic_cast<GroupRosterItem*>(item); - if (group && group->getDisplayName() == groupName) { - return group; - } - } - GroupRosterItem* group = new GroupRosterItem(groupName, root_, sortByStatus_); - root_->addChild(group); - group->onChildrenChanged.connect(boost::bind(&Roster::handleChildrenChanged, this, group)); - group->onDataChanged.connect(boost::bind(&Roster::handleDataChanged, this, group)); - return group; +std::set<JID> Roster::getJIDs() const { + std::set<JID> jids; + + std::deque<RosterItem*> queue; + queue.push_back(root_.get()); + while (!queue.empty()) { + RosterItem* item = *queue.begin(); + queue.pop_front(); + GroupRosterItem* group = dynamic_cast<GroupRosterItem*>(item); + ContactRosterItem *contact = dynamic_cast<ContactRosterItem*>(item); + if (contact) { + jids.insert(contact->getJID()); + jids.insert(contact->getDisplayJID()); + } + else if (group) { + queue.insert(queue.begin(), group->getChildren().begin(), group->getChildren().end()); + } + } + + return jids; } -void Roster::setAvailableFeatures(const JID& jid, const std::set<ContactRosterItem::Feature>& features) { - ItemMap::const_iterator i = itemMap_.find(fullJIDMapping_ ? jid : jid.toBare()); - if (i == itemMap_.end()) { - return; - } - foreach(ContactRosterItem* item, i->second) { - item->setSupportedFeatures(features); - } +GroupRosterItem* Roster::getGroup(const std::string& groupName) { + for (auto* item : root_->getChildren()) { + GroupRosterItem *group = dynamic_cast<GroupRosterItem*>(item); + if (group && group->getDisplayName() == groupName) { + return group; + } + } + GroupRosterItem* group = new GroupRosterItem(groupName, root_.get(), sortByStatus_); + root_->addChild(group); + group->onChildrenChanged.connect(boost::bind(&Roster::handleChildrenChanged, this, group)); + group->onDataChanged.connect(boost::bind(&Roster::handleDataChanged, this, group)); + return group; } -void Roster::setBlockedState(const std::vector<JID> &jids, ContactRosterItem::BlockState state) { - if (!blockingSupported_ ) { - foreach(ItemMap::value_type i, itemMap_) { - foreach(ContactRosterItem* item, i.second) { - item->setBlockState(ContactRosterItem::IsUnblocked); - } - } - } - - foreach(const JID& jid, jids) { - ItemMap::const_iterator i = itemMap_.find(fullJIDMapping_ ? jid : jid.toBare()); - if (i == itemMap_.end()) { - continue; - } - foreach(ContactRosterItem* item, i->second) { - item->setBlockState(state); - } - } - - blockingSupported_ = true; +void Roster::setBlockingSupported(bool isSupported) { + if (!blockingSupported_) { + for (auto i : itemMap_) { + for (auto* item : i.second) { + item->setBlockState(ContactRosterItem::IsUnblocked); + } + } + } + blockingSupported_ = isSupported; } void Roster::removeGroup(const std::string& group) { - root_->removeGroupChild(group); + root_->removeGroupChild(group); } void Roster::handleDataChanged(RosterItem* item) { - onDataChanged(item); + onDataChanged(item); } void Roster::handleChildrenChanged(GroupRosterItem* item) { - onChildrenChanged(item); + onChildrenChanged(item); } void Roster::addContact(const JID& jid, const JID& displayJID, const std::string& name, const std::string& groupName, const boost::filesystem::path& avatarPath) { - GroupRosterItem* group(getGroup(groupName)); - ContactRosterItem *item = new ContactRosterItem(jid, displayJID, name, group); - item->setAvatarPath(avatarPath); - if (blockingSupported_) { - item->setBlockState(ContactRosterItem::IsUnblocked); - } - group->addChild(item); - ItemMap::iterator i = itemMap_.insert(std::make_pair(fullJIDMapping_ ? jid : jid.toBare(), std::vector<ContactRosterItem*>())).first; - if (!i->second.empty()) { - foreach (const std::string& existingGroup, i->second[0]->getGroups()) { - item->addGroup(existingGroup); - } - } - i->second.push_back(item); - item->onDataChanged.connect(boost::bind(&Roster::handleDataChanged, this, item)); - filterContact(item, group); - - foreach (ContactRosterItem* item, i->second) { - item->addGroup(groupName); - } + GroupRosterItem* group(getGroup(groupName)); + ContactRosterItem *item = new ContactRosterItem(jid, displayJID, name, group); + item->onVCardRequested.connect(boost::bind(boost::ref(onVCardUpdateRequested), jid)); + item->setAvatarPath(avatarPath); + if (blockingSupported_) { + item->setBlockState(ContactRosterItem::IsUnblocked); + } + group->addChild(item); + ItemMap::iterator i = itemMap_.insert(std::make_pair(fullJIDMapping_ ? jid : jid.toBare(), std::vector<ContactRosterItem*>())).first; + if (!i->second.empty()) { + for (const auto& existingGroup : i->second[0]->getGroups()) { + item->addGroup(existingGroup); + } + } + i->second.push_back(item); + item->onDataChanged.connect(boost::bind(&Roster::handleDataChanged, this, item)); + filterContact(item, group); + + for (auto* item : i->second) { + item->addGroup(groupName); + } } struct JIDEqualsTo { - JIDEqualsTo(const JID& jid) : jid(jid) {} - bool operator()(ContactRosterItem* i) const { return jid == i->getJID(); } - JID jid; + JIDEqualsTo(const JID& jid) : jid(jid) {} + bool operator()(ContactRosterItem* i) const { return jid == i->getJID(); } + JID jid; }; void Roster::removeAll() { - root_->removeAll(); - itemMap_.clear(); - onChildrenChanged(root_); - onDataChanged(root_); + root_->removeAll(); + itemMap_.clear(); + onChildrenChanged(root_.get()); + onDataChanged(root_.get()); } void Roster::removeContact(const JID& jid) { - ItemMap::iterator item = itemMap_.find(fullJIDMapping_ ? jid : jid.toBare()); - if (item != itemMap_.end()) { - std::vector<ContactRosterItem*>& items = item->second; - items.erase(std::remove_if(items.begin(), items.end(), JIDEqualsTo(jid)), items.end()); - if (items.empty()) { - itemMap_.erase(item); - } - } - //Causes the delete - root_->removeChild(jid); + ItemMap::iterator item = itemMap_.find(fullJIDMapping_ ? jid : jid.toBare()); + if (item != itemMap_.end()) { + std::vector<ContactRosterItem*>& items = item->second; + items.erase(std::remove_if(items.begin(), items.end(), JIDEqualsTo(jid)), items.end()); + if (items.empty()) { + itemMap_.erase(item); + } + } + //Causes the delete + root_->removeChild(jid); } void Roster::removeContactFromGroup(const JID& jid, const std::string& groupName) { - std::vector<RosterItem*> children = root_->getChildren(); - std::vector<RosterItem*>::iterator it = children.begin(); - ItemMap::iterator itemIt = itemMap_.find(fullJIDMapping_ ? jid : jid.toBare()); - while (it != children.end()) { - GroupRosterItem* group = dynamic_cast<GroupRosterItem*>(*it); - if (group && group->getDisplayName() == groupName) { - ContactRosterItem* deleted = group->removeChild(jid); - if (itemIt != itemMap_.end()) { - std::vector<ContactRosterItem*>& items = itemIt->second; - items.erase(std::remove(items.begin(), items.end(), deleted), items.end()); - } - } - ++it; - } - - if (itemIt != itemMap_.end()) { - foreach (ContactRosterItem* item, itemIt->second) { - item->removeGroup(groupName); - } - } + std::vector<RosterItem*> children = root_->getChildren(); + std::vector<RosterItem*>::iterator it = children.begin(); + ItemMap::iterator itemIt = itemMap_.find(fullJIDMapping_ ? jid : jid.toBare()); + while (it != children.end()) { + GroupRosterItem* group = dynamic_cast<GroupRosterItem*>(*it); + if (group && group->getDisplayName() == groupName) { + auto deleted = group->removeChild(jid); + if (itemIt != itemMap_.end()) { + std::vector<ContactRosterItem*>& items = itemIt->second; + items.erase(std::remove(items.begin(), items.end(), deleted.get()), items.end()); + } + } + ++it; + } + + if (itemIt != itemMap_.end()) { + for (auto* item : itemIt->second) { + item->removeGroup(groupName); + } + } } void Roster::applyOnItems(const RosterItemOperation& operation) { - if (operation.requiresLookup()) { - applyOnItem(operation, operation.lookupJID()); - } else { - applyOnAllItems(operation); - } + if (operation.requiresLookup()) { + applyOnItem(operation, operation.lookupJID()); + } + else { + applyOnAllItems(operation); + } } void Roster::applyOnItem(const RosterItemOperation& operation, const JID& jid) { - ItemMap::iterator i = itemMap_.find(fullJIDMapping_ ? jid : jid.toBare()); - if (i == itemMap_.end()) { - return; - } - foreach (ContactRosterItem* item, i->second) { - operation(item); - filterContact(item, item->getParent()); - } + ItemMap::iterator i = itemMap_.find(fullJIDMapping_ ? jid : jid.toBare()); + if (i == itemMap_.end()) { + return; + } + for (auto* item : i->second) { + operation(item); + filterContact(item, item->getParent()); + } } void Roster::applyOnAllItems(const RosterItemOperation& operation) { - std::deque<RosterItem*> queue; - queue.push_back(root_); - while (!queue.empty()) { - RosterItem* item = *queue.begin(); - queue.pop_front(); - operation(item); - GroupRosterItem* group = dynamic_cast<GroupRosterItem*>(item); - if (group) { - queue.insert(queue.begin(), group->getChildren().begin(), group->getChildren().end()); - } - } - filterAll(); + std::deque<RosterItem*> queue; + queue.push_back(root_.get()); + while (!queue.empty()) { + RosterItem* item = *queue.begin(); + queue.pop_front(); + operation(item); + GroupRosterItem* group = dynamic_cast<GroupRosterItem*>(item); + if (group) { + queue.insert(queue.begin(), group->getChildren().begin(), group->getChildren().end()); + } + } + filterAll(); +} + +void Roster::addFilter(RosterFilter* filter) { + filters_.push_back(filter); + filterAll(); + onFilterAdded(filter); } -void Roster::removeFilter(RosterFilter *filter) { - for (unsigned int i = 0; i < filters_.size(); i++) { - if (filters_[i] == filter) { - filters_.erase(filters_.begin() + i); - break; - } - } - filterAll(); +void Roster::removeFilter(RosterFilter* filter) { + filters_.erase(std::remove(filters_.begin(), filters_.end(), filter), filters_.end()); + filterAll(); + onFilterRemoved(filter); } void Roster::filterContact(ContactRosterItem* contact, GroupRosterItem* group) { - size_t oldDisplayedSize = group->getDisplayedChildren().size(); - bool hide = true; - foreach (RosterFilter *filter, filters_) { - hide &= (*filter)(contact); - } - group->setDisplayed(contact, filters_.empty() || !hide); - size_t newDisplayedSize = group->getDisplayedChildren().size(); - if (oldDisplayedSize == 0 && newDisplayedSize > 0) { - onGroupAdded(group); - } + size_t oldDisplayedSize = group->getDisplayedChildren().size(); + bool hide = true; + for (auto* filter : filters_) { + hide &= (*filter)(contact); + } + group->setDisplayed(contact, filters_.empty() || !hide); + size_t newDisplayedSize = group->getDisplayedChildren().size(); + if (oldDisplayedSize == 0 && newDisplayedSize > 0) { + onGroupAdded(group); + } } void Roster::filterGroup(GroupRosterItem* group) { - foreach (RosterItem* child, group->getChildren()) { - ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(child); - if (contact) { - filterContact(contact, group); - } - } + for (auto* child : group->getChildren()) { + ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(child); + if (contact) { + filterContact(contact, group); + } + } } void Roster::filterAll() { - std::deque<RosterItem*> queue; - queue.push_back(root_); - while (!queue.empty()) { - RosterItem *item = *queue.begin(); - queue.pop_front(); - GroupRosterItem* group = dynamic_cast<GroupRosterItem*>(item); - if (group) { - queue.insert(queue.begin(), group->getChildren().begin(), group->getChildren().end()); - filterGroup(group); - } - } + std::deque<RosterItem*> queue; + queue.push_back(root_.get()); + while (!queue.empty()) { + RosterItem *item = *queue.begin(); + queue.pop_front(); + GroupRosterItem* group = dynamic_cast<GroupRosterItem*>(item); + if (group) { + queue.insert(queue.begin(), group->getChildren().begin(), group->getChildren().end()); + filterGroup(group); + } + } } } |