diff options
Diffstat (limited to 'Swift/Controllers/Roster/GroupRosterItem.cpp')
| -rw-r--r-- | Swift/Controllers/Roster/GroupRosterItem.cpp | 201 | 
1 files changed, 201 insertions, 0 deletions
diff --git a/Swift/Controllers/Roster/GroupRosterItem.cpp b/Swift/Controllers/Roster/GroupRosterItem.cpp new file mode 100644 index 0000000..c473ae7 --- /dev/null +++ b/Swift/Controllers/Roster/GroupRosterItem.cpp @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2010 Kevin Smith + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include "Swift/Controllers/Roster/GroupRosterItem.h" + +#include <boost/bind.hpp> +//#include <boost/algorithm.hpp> +#include <iostream> + +namespace Swift { + +GroupRosterItem::GroupRosterItem(const String& name, GroupRosterItem* parent, bool sortByStatus) : RosterItem(name, parent), sortByStatus_(sortByStatus) { +	expanded_ = true; +} + +GroupRosterItem::~GroupRosterItem() { + +} + +bool GroupRosterItem::isExpanded() const { +	return expanded_; +} + +/** +	This has no effect, and is only used by the UI. +	If reTransmit is specified, dataChanged will be emitted on a change - +	This may be undesireable if called from the UI, so you can use reTransmit=false +	to avoid a loop in this case. + */ +void GroupRosterItem::setExpanded(bool expanded) { +	bool old = expanded_; +	expanded_ = expanded; +	if (expanded != old) { +		onExpandedChanged(expanded); +	} +} + +const std::vector<RosterItem*>& GroupRosterItem::getChildren() const { +	return children_; +} + +const std::vector<RosterItem*>& GroupRosterItem::getDisplayedChildren() const { +	return displayedChildren_; +} + +void GroupRosterItem::addChild(RosterItem* item) { +	children_.push_back(item); +	GroupRosterItem* group = dynamic_cast<GroupRosterItem*>(item); +	if (group) { +		group->onChildrenChanged.connect(boost::bind(&GroupRosterItem::handleChildrenChanged, this, group)); +	} else { +		item->onDataChanged.connect(boost::bind(&GroupRosterItem::handleDataChanged, this, item)); +	} +	onChildrenChanged(); +	onDataChanged(); +} + +/** + * Does not emit a changed signal. + */ +void GroupRosterItem::removeAll() { +	std::vector<RosterItem*>::iterator it = children_.begin(); +	displayedChildren_.clear(); +	while (it != children_.end()) { +		ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(*it); +		if (contact) { +			delete contact; +		} else { +			GroupRosterItem* group = dynamic_cast<GroupRosterItem*>(*it); +			if (group) { +				group->removeAll(); +				delete group; +			} +		} +		it++; +	} +	children_.clear(); +} + +/** + * Returns the removed item - but only if it's the only one, otherwise + * the return result is undefined. + */ +ContactRosterItem* GroupRosterItem::removeChild(const JID& jid) { +	std::vector<RosterItem*>::iterator it = children_.begin(); +	ContactRosterItem* removed = NULL; +	while (it != children_.end()) { +		ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(*it); +		if (contact && contact->getJID() == jid) { +			displayedChildren_.erase(std::remove(displayedChildren_.begin(), displayedChildren_.end(), contact), displayedChildren_.end()); +			removed = contact; +			delete contact; +			it = children_.erase(it); +			continue; +		}  +		GroupRosterItem* group = dynamic_cast<GroupRosterItem*>(*it); +		if (group) { +			ContactRosterItem* groupRemoved = group->removeChild(jid); +			if (groupRemoved) { +				removed = groupRemoved; +			} +		} +		it++; +	} +	onChildrenChanged(); +	onDataChanged(); +	return removed; +} + +/** + * Returns false if the list didn't need a resort + */ +bool GroupRosterItem::sortDisplayed() { +	/* Not doing this until we import boost::algorithm*/ +//	if (boost::is_sorted(displayedChildren_begin(), displayedChildren_.end(), itemLessThan)) { +//		return false; +//	} +	//Sholudn't need stable_sort here +	std::sort(displayedChildren_.begin(), displayedChildren_.end(), sortByStatus_? itemLessThanWithStatus : itemLessThanWithoutStatus); +	return true; +} + +bool GroupRosterItem::itemLessThanWithoutStatus(const RosterItem* left, const RosterItem* right) { +	return left->getSortableDisplayName() < right->getSortableDisplayName(); +} + +bool GroupRosterItem::itemLessThanWithStatus(const RosterItem* left, const RosterItem* right) { +	const ContactRosterItem* leftContact = dynamic_cast<const ContactRosterItem*>(left); +	const ContactRosterItem* rightContact = dynamic_cast<const ContactRosterItem*>(right); +	if (leftContact) { +		if (!rightContact) { +			return false; +		} +		StatusShow::Type leftType = leftContact->getSimplifiedStatusShow(); +		StatusShow::Type rightType = rightContact->getSimplifiedStatusShow(); +		if (leftType == rightType) { +			return left->getSortableDisplayName() < right->getSortableDisplayName(); +		} else { +			return leftType < rightType; +		} +	} else { +		if (rightContact) { +			return true; +		} +		return left->getSortableDisplayName() < right->getSortableDisplayName(); +	} +} + +void GroupRosterItem::setDisplayed(RosterItem* item, bool displayed) { +	bool found = false; +	for (size_t i = 0; i < displayedChildren_.size(); i++) { +		if (displayedChildren_[i] == item) { +			found = true; +		} +	} +	if (found == displayed) { +		return; +	} +	if (displayed) { +		displayedChildren_.push_back(item); +		sortDisplayed(); +	} else { +		displayedChildren_.erase(std::remove(displayedChildren_.begin(), displayedChildren_.end(), item), displayedChildren_.end()); +	} +	onChildrenChanged(); +	onDataChanged(); +} + +void GroupRosterItem::handleDataChanged(RosterItem* /*item*/) { +	if (sortDisplayed()) { +		onChildrenChanged(); +	} +} + +void GroupRosterItem::handleChildrenChanged(GroupRosterItem* group) { +	size_t oldSize = getDisplayedChildren().size(); +	if (group->getDisplayedChildren().size() > 0) { +		bool found = false; +		for (size_t i = 0; i < displayedChildren_.size(); i++) { +			if (displayedChildren_[i] == group) { +				found = true; +			} +		} +		if (!found) { +			displayedChildren_.push_back(group); +			sortDisplayed(); +		} +	} else { +		displayedChildren_.erase(std::remove(displayedChildren_.begin(), displayedChildren_.end(), group), displayedChildren_.end()); +	} +	if (oldSize != getDisplayedChildren().size()) { +		onChildrenChanged(); +		onDataChanged(); +	} +} + + +}  | 
 Swift