summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'Swift/Controllers/Roster/Roster.cpp')
-rw-r--r--Swift/Controllers/Roster/Roster.cpp209
1 files changed, 209 insertions, 0 deletions
diff --git a/Swift/Controllers/Roster/Roster.cpp b/Swift/Controllers/Roster/Roster.cpp
new file mode 100644
index 0000000..7967a38
--- /dev/null
+++ b/Swift/Controllers/Roster/Roster.cpp
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include "Swift/Controllers/Roster/Roster.h"
+
+#include "Swiften/Base/foreach.h"
+#include "Swiften/Base/String.h"
+#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 <deque>
+
+namespace Swift {
+
+Roster::Roster(bool sortByStatus, bool fullJIDMapping) {
+ sortByStatus_ = sortByStatus;
+ fullJIDMapping_ = fullJIDMapping;
+ root_ = new GroupRosterItem("Dummy-Root", NULL, sortByStatus_);
+ root_->onChildrenChanged.connect(boost::bind(&Roster::handleChildrenChanged, this, root_));
+}
+
+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;
+ }
+}
+
+GroupRosterItem* Roster::getRoot() {
+ return root_;
+}
+
+GroupRosterItem* Roster::getGroup(const 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;
+}
+
+void Roster::handleDataChanged(RosterItem* item) {
+ onDataChanged(item);
+}
+
+void Roster::handleChildrenChanged(GroupRosterItem* item) {
+ onChildrenChanged(item);
+}
+
+void Roster::addContact(const JID& jid, const JID& displayJID, const String& name, const String& groupName, const String& avatarPath) {
+ GroupRosterItem* group(getGroup(groupName));
+ ContactRosterItem *item = new ContactRosterItem(jid, displayJID, name, group);
+ item->setAvatarPath(avatarPath);
+ group->addChild(item);
+ if (itemMap_[fullJIDMapping_ ? jid : jid.toBare()].size() > 0) {
+ foreach (String existingGroup, itemMap_[fullJIDMapping_ ? jid : jid.toBare()][0]->getGroups()) {
+ item->addGroup(existingGroup);
+ }
+ }
+ itemMap_[fullJIDMapping_ ? jid : jid.toBare()].push_back(item);
+ item->onDataChanged.connect(boost::bind(&Roster::handleDataChanged, this, item));
+ filterContact(item, group);
+
+ foreach (ContactRosterItem* item, itemMap_[fullJIDMapping_ ? jid : jid.toBare()]) {
+ item->addGroup(groupName);
+ }
+}
+
+struct JIDEqualsTo {
+ 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_);
+}
+
+void Roster::removeContact(const JID& jid) {
+ std::vector<ContactRosterItem*>* items = &itemMap_[fullJIDMapping_ ? jid : jid.toBare()];
+ items->erase(std::remove_if(items->begin(), items->end(), JIDEqualsTo(jid)), items->end());
+ if (items->size() == 0) {
+ itemMap_.erase(fullJIDMapping_ ? jid : jid.toBare());
+ }
+ //Causes the delete
+ root_->removeChild(jid);
+}
+
+void Roster::removeContactFromGroup(const JID& jid, const String& groupName) {
+ std::vector<RosterItem*> children = root_->getChildren();
+ std::vector<RosterItem*>::iterator it = children.begin();
+ while (it != children.end()) {
+ GroupRosterItem* group = dynamic_cast<GroupRosterItem*>(*it);
+ if (group && group->getDisplayName() == groupName) {
+ ContactRosterItem* deleted = group->removeChild(jid);
+ std::vector<ContactRosterItem*>* items = &itemMap_[fullJIDMapping_ ? jid : jid.toBare()];
+ items->erase(std::remove(items->begin(), items->end(), deleted), items->end());
+ }
+ it++;
+ }
+ foreach (ContactRosterItem* item, itemMap_[fullJIDMapping_ ? jid : jid.toBare()]) {
+ item->removeGroup(groupName);
+ }
+}
+
+
+void Roster::applyOnItems(const RosterItemOperation& operation) {
+ if (operation.requiresLookup()) {
+ applyOnItem(operation, operation.lookupJID());
+ } else {
+ applyOnAllItems(operation);
+ }
+}
+
+void Roster::applyOnItem(const RosterItemOperation& operation, const JID& jid) {
+
+ foreach (ContactRosterItem* item, itemMap_[fullJIDMapping_ ? jid : jid.toBare()]) {
+ 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();
+}
+
+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::filterContact(ContactRosterItem* contact, GroupRosterItem* group) {
+ int oldDisplayedSize = group->getDisplayedChildren().size();
+ bool hide = true;
+ foreach (RosterFilter *filter, filters_) {
+ hide &= (*filter)(contact);
+ }
+ group->setDisplayed(contact, filters_.size() == 0 || !hide);
+ int 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);
+ }
+ }
+}
+
+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);
+ }
+ }
+}
+
+}
+