diff options
Diffstat (limited to 'Swift/Controllers/Roster/Roster.cpp')
| -rw-r--r-- | Swift/Controllers/Roster/Roster.cpp | 209 | 
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); +		} +	} +} + +} +  | 
 Swift