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(); + } +} + + +} |