diff options
Diffstat (limited to 'Swift/Controllers/Roster')
33 files changed, 2446 insertions, 2312 deletions
diff --git a/Swift/Controllers/Roster/ContactRosterItem.cpp b/Swift/Controllers/Roster/ContactRosterItem.cpp index 3258fb5..8fdf183 100644 --- a/Swift/Controllers/Roster/ContactRosterItem.cpp +++ b/Swift/Controllers/Roster/ContactRosterItem.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2015 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -9,8 +9,8 @@ #include <boost/date_time/posix_time/posix_time.hpp> #include <Swiften/Base/DateTime.h> -#include <Swiften/Base/foreach.h> #include <Swiften/Elements/Idle.h> +#include <Swiften/Elements/Presence.h> #include <Swift/Controllers/Intl.h> #include <Swift/Controllers/Roster/GroupRosterItem.h> @@ -27,149 +27,168 @@ ContactRosterItem::~ContactRosterItem() { } StatusShow::Type ContactRosterItem::getStatusShow() const { - return presence_ ? presence_->getShow() : StatusShow::None; + return presence_ ? presence_->getShow() : StatusShow::None; } StatusShow::Type ContactRosterItem::getSimplifiedStatusShow() const { - switch (presence_ ? presence_->getShow() : StatusShow::None) { - case StatusShow::Online: return StatusShow::Online; - case StatusShow::Away: return StatusShow::Away; - case StatusShow::XA: return StatusShow::Away; - case StatusShow::FFC: return StatusShow::Online; - case StatusShow::DND: return StatusShow::DND; - case StatusShow::None: return StatusShow::None; - } - assert(false); - return StatusShow::None; + switch (presence_ ? presence_->getShow() : StatusShow::None) { + case StatusShow::Online: return StatusShow::Online; + case StatusShow::Away: return StatusShow::Away; + case StatusShow::XA: return StatusShow::Away; + case StatusShow::FFC: return StatusShow::Online; + case StatusShow::DND: return StatusShow::DND; + case StatusShow::None: return StatusShow::None; + } + assert(false); + return StatusShow::None; } std::string ContactRosterItem::getStatusText() const { - return presence_ ? presence_->getStatus() : ""; + return presence_ ? presence_->getStatus() : ""; } std::string ContactRosterItem::getIdleText() const { - Idle::ref idle = presence_ ? presence_->getPayload<Idle>() : Idle::ref(); - if (!idle || idle->getSince().is_not_a_date_time()) { - return ""; - } else { - return dateTimeToLocalString(idle->getSince()); - } + boost::posix_time::ptime idleTime = getIdle(); + if (idleTime.is_not_a_date_time()) { + return ""; + } else { + return dateTimeToLocalString(idleTime); + } +} + +boost::posix_time::ptime ContactRosterItem::getIdle() const { + Idle::ref idle = presence_ ? presence_->getPayload<Idle>() : Idle::ref(); + if (idle) { + return idle->getSince(); + } + else { + return boost::posix_time::not_a_date_time; + } } std::string ContactRosterItem::getOfflineSinceText() const { - if (presence_ && presence_->getType() == Presence::Unavailable) { - boost::optional<boost::posix_time::ptime> delay = presence_->getTimestamp(); - if (delay) { - return dateTimeToLocalString(*delay); - } - } - return ""; + boost::posix_time::ptime offlineSince = getOfflineSince(); + if (!offlineSince.is_not_a_date_time()) { + return dateTimeToLocalString(offlineSince); + } + return ""; +} + +boost::posix_time::ptime ContactRosterItem::getOfflineSince() const { + boost::posix_time::ptime offlineSince = boost::posix_time::not_a_date_time; + if (presence_ && presence_->getType() == Presence::Unavailable) { + boost::optional<boost::posix_time::ptime> delay = presence_->getTimestamp(); + if (delay) { + offlineSince = delay.get(); + } + } + return offlineSince; } void ContactRosterItem::setAvatarPath(const boost::filesystem::path& path) { - avatarPath_ = path; - onDataChanged(); + avatarPath_ = path; + onDataChanged(); } const boost::filesystem::path& ContactRosterItem::getAvatarPath() const { - return avatarPath_; + return avatarPath_; } const JID& ContactRosterItem::getJID() const { - return jid_; + return jid_; } void ContactRosterItem::setDisplayJID(const JID& jid) { - displayJID_ = jid; + displayJID_ = jid; } const JID& ContactRosterItem::getDisplayJID() const { - return displayJID_; + return displayJID_; } -typedef std::pair<std::string, boost::shared_ptr<Presence> > StringPresencePair; +typedef std::pair<std::string, std::shared_ptr<Presence> > StringPresencePair; void ContactRosterItem::clearPresence() { - presence_.reset(); - onDataChanged(); + presence_.reset(); + onDataChanged(); } -void ContactRosterItem::applyPresence(boost::shared_ptr<Presence> presence) { - presence_ = presence; - onDataChanged(); +void ContactRosterItem::applyPresence(std::shared_ptr<Presence> presence) { + presence_ = presence; + onDataChanged(); } const std::vector<std::string>& ContactRosterItem::getGroups() const { - return groups_; + return groups_; } /** Only used so a contact can know about the groups it's in*/ void ContactRosterItem::addGroup(const std::string& group) { - groups_.push_back(group); + groups_.push_back(group); } void ContactRosterItem::removeGroup(const std::string& group) { - groups_.erase(std::remove(groups_.begin(), groups_.end(), group), groups_.end()); + groups_.erase(std::remove(groups_.begin(), groups_.end(), group), groups_.end()); } MUCOccupant::Role ContactRosterItem::getMUCRole() const { - return mucRole_; + return mucRole_; } void ContactRosterItem::setMUCRole(const MUCOccupant::Role& role) { - mucRole_ = role; + mucRole_ = role; } MUCOccupant::Affiliation ContactRosterItem::getMUCAffiliation() const { - return mucAffiliation_; + return mucAffiliation_; } void ContactRosterItem::setMUCAffiliation(const MUCOccupant::Affiliation& affiliation) { - mucAffiliation_ = affiliation; + mucAffiliation_ = affiliation; } std::string ContactRosterItem::getMUCAffiliationText() const { - std::string affiliationString; - switch (mucAffiliation_) { - case MUCOccupant::Owner: affiliationString = QT_TRANSLATE_NOOP("", "Owner"); break; - case MUCOccupant::Admin: affiliationString = QT_TRANSLATE_NOOP("", "Admin"); break; - case MUCOccupant::Member: affiliationString = QT_TRANSLATE_NOOP("", "Member"); break; - case MUCOccupant::Outcast: affiliationString = QT_TRANSLATE_NOOP("", "Outcast"); break; - case MUCOccupant::NoAffiliation: affiliationString = ""; break; - } + std::string affiliationString; + switch (mucAffiliation_) { + case MUCOccupant::Owner: affiliationString = QT_TRANSLATE_NOOP("", "Owner"); break; + case MUCOccupant::Admin: affiliationString = QT_TRANSLATE_NOOP("", "Admin"); break; + case MUCOccupant::Member: affiliationString = QT_TRANSLATE_NOOP("", "Member"); break; + case MUCOccupant::Outcast: affiliationString = QT_TRANSLATE_NOOP("", "Outcast"); break; + case MUCOccupant::NoAffiliation: affiliationString = ""; break; + } - return affiliationString; + return affiliationString; } void ContactRosterItem::setSupportedFeatures(const std::set<Feature>& features) { - features_ = features; - onDataChanged(); + features_ = features; + onDataChanged(); } bool ContactRosterItem::supportsFeature(const Feature feature) const { - return features_.find(feature) != features_.end(); + return features_.find(feature) != features_.end(); } void ContactRosterItem::setBlockState(BlockState state) { - blockState_ = state; - onDataChanged(); + blockState_ = state; + onDataChanged(); } ContactRosterItem::BlockState ContactRosterItem::blockState() const { - return blockState_; + return blockState_; } VCard::ref ContactRosterItem::getVCard() const { - return vcard_; + return vcard_; } void ContactRosterItem::setVCard(VCard::ref vcard) { - vcard_ = vcard; - onDataChanged(); + vcard_ = vcard; + onDataChanged(); } } diff --git a/Swift/Controllers/Roster/ContactRosterItem.h b/Swift/Controllers/Roster/ContactRosterItem.h index d21935c..37c3840 100644 --- a/Swift/Controllers/Roster/ContactRosterItem.h +++ b/Swift/Controllers/Roster/ContactRosterItem.h @@ -1,11 +1,12 @@ /* - * Copyright (c) 2010-2015 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #pragma once +#include <memory> #include <set> #include <string> #include <vector> @@ -13,11 +14,9 @@ #include <boost/bind.hpp> #include <boost/date_time/posix_time/ptime.hpp> #include <boost/filesystem/path.hpp> -#include <boost/shared_ptr.hpp> +#include <boost/signals2.hpp> -#include <Swiften/Base/boost_bsignals.h> #include <Swiften/Elements/MUCOccupant.h> -#include <Swiften/Elements/Presence.h> #include <Swiften/Elements/StatusShow.h> #include <Swiften/Elements/VCard.h> #include <Swiften/JID/JID.h> @@ -27,70 +26,73 @@ namespace Swift { class GroupRosterItem; +class Presence; + class ContactRosterItem : public RosterItem { - public: - enum Feature { - FileTransferFeature, - WhiteboardFeature - }; - - enum BlockState { - BlockingNotSupported, - IsBlocked, - IsUnblocked, - IsDomainBlocked - }; - - public: - ContactRosterItem(const JID& jid, const JID& displayJID, const std::string& name, GroupRosterItem* parent); - virtual ~ContactRosterItem(); - - StatusShow::Type getStatusShow() const; - StatusShow::Type getSimplifiedStatusShow() const; - std::string getStatusText() const; - std::string getIdleText() const; - std::string getOfflineSinceText() const; - void setAvatarPath(const boost::filesystem::path& path); - const boost::filesystem::path& getAvatarPath() const; - const JID& getJID() const; - void setDisplayJID(const JID& jid); - const JID& getDisplayJID() const; - void applyPresence(boost::shared_ptr<Presence> presence); - const std::vector<std::string>& getGroups() const; - /** Only used so a contact can know about the groups it's in*/ - void addGroup(const std::string& group); - void removeGroup(const std::string& group); - void clearPresence(); - - MUCOccupant::Role getMUCRole() const; - void setMUCRole(const MUCOccupant::Role& role); - MUCOccupant::Affiliation getMUCAffiliation() const; - void setMUCAffiliation(const MUCOccupant::Affiliation& affiliation); - std::string getMUCAffiliationText() const; - - void setSupportedFeatures(const std::set<Feature>& features); - bool supportsFeature(Feature feature) const; - - void setBlockState(BlockState state); - BlockState blockState() const; - - VCard::ref getVCard() const; - void setVCard(VCard::ref vcard); - - boost::signal<void ()> onVCardRequested; - - private: - JID jid_; - JID displayJID_; - boost::posix_time::ptime lastAvailableTime_; - boost::filesystem::path avatarPath_; - boost::shared_ptr<Presence> presence_; - std::vector<std::string> groups_; - MUCOccupant::Role mucRole_; - MUCOccupant::Affiliation mucAffiliation_; - std::set<Feature> features_; - BlockState blockState_; - VCard::ref vcard_; + public: + enum Feature { + FileTransferFeature, + WhiteboardFeature + }; + + enum BlockState { + BlockingNotSupported, + IsBlocked, + IsUnblocked, + IsDomainBlocked + }; + + public: + ContactRosterItem(const JID& jid, const JID& displayJID, const std::string& name, GroupRosterItem* parent); + virtual ~ContactRosterItem(); + + StatusShow::Type getStatusShow() const; + StatusShow::Type getSimplifiedStatusShow() const; + std::string getStatusText() const; + std::string getIdleText() const; + boost::posix_time::ptime getIdle() const; + std::string getOfflineSinceText() const; + boost::posix_time::ptime getOfflineSince() const; + void setAvatarPath(const boost::filesystem::path& path); + const boost::filesystem::path& getAvatarPath() const; + const JID& getJID() const; + void setDisplayJID(const JID& jid); + const JID& getDisplayJID() const; + void applyPresence(std::shared_ptr<Presence> presence); + const std::vector<std::string>& getGroups() const; + /** Only used so a contact can know about the groups it's in*/ + void addGroup(const std::string& group); + void removeGroup(const std::string& group); + void clearPresence(); + + MUCOccupant::Role getMUCRole() const; + void setMUCRole(const MUCOccupant::Role& role); + MUCOccupant::Affiliation getMUCAffiliation() const; + void setMUCAffiliation(const MUCOccupant::Affiliation& affiliation); + std::string getMUCAffiliationText() const; + + void setSupportedFeatures(const std::set<Feature>& features); + bool supportsFeature(Feature feature) const; + + void setBlockState(BlockState state); + BlockState blockState() const; + + VCard::ref getVCard() const; + void setVCard(VCard::ref vcard); + + boost::signals2::signal<void ()> onVCardRequested; + + private: + JID jid_; + JID displayJID_; + boost::filesystem::path avatarPath_; + std::shared_ptr<Presence> presence_; + std::vector<std::string> groups_; + MUCOccupant::Role mucRole_; + MUCOccupant::Affiliation mucAffiliation_; + std::set<Feature> features_; + BlockState blockState_; + VCard::ref vcard_; }; } diff --git a/Swift/Controllers/Roster/FuzzyRosterFilter.h b/Swift/Controllers/Roster/FuzzyRosterFilter.h index 6710084..8c45935 100644 --- a/Swift/Controllers/Roster/FuzzyRosterFilter.h +++ b/Swift/Controllers/Roster/FuzzyRosterFilter.h @@ -4,33 +4,39 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once #include <string> #include <Swift/Controllers/ContactSuggester.h> #include <Swift/Controllers/Roster/ContactRosterItem.h> -#include <Swift/Controllers/Roster/RosterItem.h> #include <Swift/Controllers/Roster/RosterFilter.h> +#include <Swift/Controllers/Roster/RosterItem.h> namespace Swift { class FuzzyRosterFilter : public RosterFilter { - public: - FuzzyRosterFilter(const std::string& query) : query_(query) { } - virtual ~FuzzyRosterFilter() {} - virtual bool operator() (RosterItem* item) const { - ContactRosterItem *contactItem = dynamic_cast<ContactRosterItem*>(item); - if (contactItem) { - const bool itemMatched = ContactSuggester::fuzzyMatch(contactItem->getDisplayName(), query_) || ContactSuggester::fuzzyMatch(contactItem->getDisplayJID(), query_); - return !itemMatched; - } else { - return false; - } - } - - private: - std::string query_; + public: + FuzzyRosterFilter(const std::string& query) : query_(query) { } + virtual ~FuzzyRosterFilter() {} + virtual bool operator() (RosterItem* item) const { + ContactRosterItem *contactItem = dynamic_cast<ContactRosterItem*>(item); + if (contactItem) { + const bool itemMatched = ContactSuggester::fuzzyMatch(contactItem->getDisplayName(), query_) || ContactSuggester::fuzzyMatch(contactItem->getDisplayJID(), query_); + return !itemMatched; + } else { + return false; + } + } + + private: + std::string query_; }; } diff --git a/Swift/Controllers/Roster/GroupRosterItem.cpp b/Swift/Controllers/Roster/GroupRosterItem.cpp index a241dec..ac40afd 100644 --- a/Swift/Controllers/Roster/GroupRosterItem.cpp +++ b/Swift/Controllers/Roster/GroupRosterItem.cpp @@ -1,11 +1,10 @@ /* - * Copyright (c) 2010 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ -#include "Swift/Controllers/Roster/GroupRosterItem.h" - +#include <Swift/Controllers/Roster/GroupRosterItem.h> #include <boost/bind.hpp> //#include <boost/algorithm.hpp> #include <iostream> @@ -13,7 +12,7 @@ namespace Swift { GroupRosterItem::GroupRosterItem(const std::string& name, GroupRosterItem* parent, bool sortByStatus) : RosterItem(name, parent), sortByStatus_(sortByStatus), manualSort_(false) { - expanded_ = true; + expanded_ = true; } GroupRosterItem::~GroupRosterItem() { @@ -21,77 +20,77 @@ GroupRosterItem::~GroupRosterItem() { } void GroupRosterItem::setManualSort(const std::string& manualSortValue) { - manualSort_ = true; - bool changed = manualSortValue_ != manualSortValue; - manualSortValue_ = manualSortValue; - if (changed) { - onChildrenChanged(); - onDataChanged(); - } + manualSort_ = true; + bool changed = manualSortValue_ != manualSortValue; + manualSortValue_ = manualSortValue; + if (changed) { + onChildrenChanged(); + onDataChanged(); + } } const std::string& GroupRosterItem::getSortableDisplayName() const { - return manualSort_ ? manualSortValue_ : RosterItem::getSortableDisplayName(); + return manualSort_ ? manualSortValue_ : RosterItem::getSortableDisplayName(); } bool GroupRosterItem::isExpanded() const { - return expanded_; + 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. + 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); - } + bool old = expanded_; + expanded_ = expanded; + if (expanded != old) { + onExpandedChanged(expanded); + } } const std::vector<RosterItem*>& GroupRosterItem::getChildren() const { - return children_; + return children_; } const std::vector<RosterItem*>& GroupRosterItem::getDisplayedChildren() const { - return displayedChildren_; + 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(); + 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(); + 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(); } /** @@ -99,136 +98,136 @@ void GroupRosterItem::removeAll() { * 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; + std::vector<RosterItem*>::iterator it = children_.begin(); + ContactRosterItem* removed = nullptr; + 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; } GroupRosterItem* GroupRosterItem::removeGroupChild(const std::string& groupName) { - std::vector<RosterItem*>::iterator it = children_.begin(); - GroupRosterItem* removed = NULL; - while (it != children_.end()) { - GroupRosterItem* group = dynamic_cast<GroupRosterItem*>(*it); - if (group && group->getDisplayName() == groupName) { - displayedChildren_.erase(std::remove(displayedChildren_.begin(), displayedChildren_.end(), group), displayedChildren_.end()); - removed = group; - delete group; - it = children_.erase(it); - continue; - } - ++it; - } - onChildrenChanged(); - onDataChanged(); - return removed; + std::vector<RosterItem*>::iterator it = children_.begin(); + GroupRosterItem* removed = nullptr; + while (it != children_.end()) { + GroupRosterItem* group = dynamic_cast<GroupRosterItem*>(*it); + if (group && group->getDisplayName() == groupName) { + displayedChildren_.erase(std::remove(displayedChildren_.begin(), displayedChildren_.end(), group), displayedChildren_.end()); + removed = group; + delete group; + it = children_.erase(it); + continue; + } + ++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; + /* 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(); + 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(); - } + 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(); + bool found = false; + for (auto& i : displayedChildren_) { + if (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(); - } + 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() || sortDisplayed()) { - onChildrenChanged(); - onDataChanged(); - } + size_t oldSize = getDisplayedChildren().size(); + if (group->getDisplayedChildren().size() > 0) { + bool found = false; + for (auto& i : displayedChildren_) { + if (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() || sortDisplayed()) { + onChildrenChanged(); + onDataChanged(); + } } diff --git a/Swift/Controllers/Roster/GroupRosterItem.h b/Swift/Controllers/Roster/GroupRosterItem.h index 90ba471..a4e008f 100644 --- a/Swift/Controllers/Roster/GroupRosterItem.h +++ b/Swift/Controllers/Roster/GroupRosterItem.h @@ -1,49 +1,49 @@ /* - * Copyright (c) 2010 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include "Swift/Controllers/Roster/RosterItem.h" #include <string> -#include "Swift/Controllers/Roster/ContactRosterItem.h" - #include <vector> +#include <Swift/Controllers/Roster/ContactRosterItem.h> +#include <Swift/Controllers/Roster/RosterItem.h> + namespace Swift { class GroupRosterItem : public RosterItem { - public: - GroupRosterItem(const std::string& name, GroupRosterItem* parent, bool sortByStatus); - virtual ~GroupRosterItem(); - const std::vector<RosterItem*>& getChildren() const; - const std::vector<RosterItem*>& getDisplayedChildren() const; - void addChild(RosterItem* item); - ContactRosterItem* removeChild(const JID& jid); - GroupRosterItem* removeGroupChild(const std::string& group); - void removeAll(); - void setDisplayed(RosterItem* item, bool displayed); - boost::signal<void ()> onChildrenChanged; - static bool itemLessThanWithStatus(const RosterItem* left, const RosterItem* right); - static bool itemLessThanWithoutStatus(const RosterItem* left, const RosterItem* right); - void setExpanded(bool expanded); - bool isExpanded() const; - boost::signal<void (bool)> onExpandedChanged; - void setManualSort(const std::string& manualSortValue); - virtual const std::string& getSortableDisplayName() const; - private: - void handleChildrenChanged(GroupRosterItem* group); - void handleDataChanged(RosterItem* item); - bool sortDisplayed(); - std::string name_; - bool expanded_; - std::vector<RosterItem*> children_; - std::vector<RosterItem*> displayedChildren_; - bool sortByStatus_; - bool manualSort_; - std::string manualSortValue_; + public: + GroupRosterItem(const std::string& name, GroupRosterItem* parent, bool sortByStatus); + virtual ~GroupRosterItem(); + const std::vector<RosterItem*>& getChildren() const; + const std::vector<RosterItem*>& getDisplayedChildren() const; + void addChild(RosterItem* item); + ContactRosterItem* removeChild(const JID& jid); + GroupRosterItem* removeGroupChild(const std::string& group); + void removeAll(); + void setDisplayed(RosterItem* item, bool displayed); + boost::signals2::signal<void ()> onChildrenChanged; + static bool itemLessThanWithStatus(const RosterItem* left, const RosterItem* right); + static bool itemLessThanWithoutStatus(const RosterItem* left, const RosterItem* right); + void setExpanded(bool expanded); + bool isExpanded() const; + boost::signals2::signal<void (bool)> onExpandedChanged; + void setManualSort(const std::string& manualSortValue); + virtual const std::string& getSortableDisplayName() const; + private: + void handleChildrenChanged(GroupRosterItem* group); + void handleDataChanged(RosterItem* item); + bool sortDisplayed(); + std::string name_; + bool expanded_; + std::vector<RosterItem*> children_; + std::vector<RosterItem*> displayedChildren_; + bool sortByStatus_; + bool manualSort_; + std::string manualSortValue_; }; } diff --git a/Swift/Controllers/Roster/ItemOperations/AppearOffline.h b/Swift/Controllers/Roster/ItemOperations/AppearOffline.h index 6438a8e..c57974b 100644 --- a/Swift/Controllers/Roster/ItemOperations/AppearOffline.h +++ b/Swift/Controllers/Roster/ItemOperations/AppearOffline.h @@ -1,29 +1,29 @@ /* - * Copyright (c) 2010 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swift/Controllers/Roster/ItemOperations/RosterItemOperation.h> #include <Swift/Controllers/Roster/ContactRosterItem.h> +#include <Swift/Controllers/Roster/ItemOperations/RosterItemOperation.h> namespace Swift { class RosterItem; class AppearOffline : public RosterItemOperation { - public: - AppearOffline() { - } - - virtual void operator() (RosterItem* item) const { - ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(item); - if (contact) { - contact->clearPresence(); - } - } + public: + AppearOffline() { + } + + virtual void operator() (RosterItem* item) const { + ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(item); + if (contact) { + contact->clearPresence(); + } + } }; diff --git a/Swift/Controllers/Roster/ItemOperations/RosterItemOperation.h b/Swift/Controllers/Roster/ItemOperations/RosterItemOperation.h index da81d2b..c633c20 100644 --- a/Swift/Controllers/Roster/ItemOperations/RosterItemOperation.h +++ b/Swift/Controllers/Roster/ItemOperations/RosterItemOperation.h @@ -1,30 +1,32 @@ /* - * Copyright (c) 2010 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include "Swift/Controllers/Roster/RosterItem.h" +#include <Swiften/JID/JID.h> + +#include <Swift/Controllers/Roster/RosterItem.h> namespace Swift { class RosterItemOperation { - public: - RosterItemOperation(bool requiresLookup = false, const JID& lookupJID = JID()) : requiresLookup_(requiresLookup), lookupJID_(lookupJID) {} - virtual ~RosterItemOperation() {} - bool requiresLookup() const {return requiresLookup_;} - const JID& lookupJID() const {return lookupJID_;} - /** - * This is called when iterating over possible subjects, so must check it's - * applying to the right items - even if requiresLookup() is true an item - * with the same bare JID but different full JID may be passed. - */ - virtual void operator() (RosterItem*) const = 0; - private: - bool requiresLookup_; - JID lookupJID_; + public: + RosterItemOperation(bool requiresLookup = false, const JID& lookupJID = JID()) : requiresLookup_(requiresLookup), lookupJID_(lookupJID) {} + virtual ~RosterItemOperation() {} + bool requiresLookup() const {return requiresLookup_;} + const JID& lookupJID() const {return lookupJID_;} + /** + * This is called when iterating over possible subjects, so must check it's + * applying to the right items - even if requiresLookup() is true an item + * with the same bare JID but different full JID may be passed. + */ + virtual void operator() (RosterItem*) const = 0; + private: + bool requiresLookup_; + JID lookupJID_; }; } diff --git a/Swift/Controllers/Roster/ItemOperations/SetAvailableFeatures.h b/Swift/Controllers/Roster/ItemOperations/SetAvailableFeatures.h index 620a1ae..29f9722 100644 --- a/Swift/Controllers/Roster/ItemOperations/SetAvailableFeatures.h +++ b/Swift/Controllers/Roster/ItemOperations/SetAvailableFeatures.h @@ -4,33 +4,39 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once #include <Swiften/JID/JID.h> -#include <Swift/Controllers/Roster/ItemOperations/RosterItemOperation.h> #include <Swift/Controllers/Roster/ContactRosterItem.h> +#include <Swift/Controllers/Roster/ItemOperations/RosterItemOperation.h> namespace Swift { class RosterItem; class SetAvailableFeatures : public RosterItemOperation { - public: - SetAvailableFeatures(const JID& jid, const std::set<ContactRosterItem::Feature>& availableFeatures, JID::CompareType compareType = JID::WithoutResource) : RosterItemOperation(true, jid), jid_(jid), availableFeatures_(availableFeatures), compareType_(compareType) { - } - - virtual void operator() (RosterItem* item) const { - ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(item); - if (contact && contact->getJID().equals(jid_, compareType_)) { - contact->setSupportedFeatures(availableFeatures_); - } - } - - private: - JID jid_; - std::set<ContactRosterItem::Feature> availableFeatures_; - JID::CompareType compareType_; + public: + SetAvailableFeatures(const JID& jid, const std::set<ContactRosterItem::Feature>& availableFeatures, JID::CompareType compareType = JID::WithoutResource) : RosterItemOperation(true, jid), jid_(jid), availableFeatures_(availableFeatures), compareType_(compareType) { + } + + virtual void operator() (RosterItem* item) const { + ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(item); + if (contact && contact->getJID().equals(jid_, compareType_)) { + contact->setSupportedFeatures(availableFeatures_); + } + } + + private: + JID jid_; + std::set<ContactRosterItem::Feature> availableFeatures_; + JID::CompareType compareType_; }; } diff --git a/Swift/Controllers/Roster/ItemOperations/SetAvatar.h b/Swift/Controllers/Roster/ItemOperations/SetAvatar.h index 910a651..d47c921 100644 --- a/Swift/Controllers/Roster/ItemOperations/SetAvatar.h +++ b/Swift/Controllers/Roster/ItemOperations/SetAvatar.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2013 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -11,29 +11,29 @@ #include <Swiften/Elements/Presence.h> #include <Swiften/JID/JID.h> -#include <Swift/Controllers/Roster/ItemOperations/RosterItemOperation.h> #include <Swift/Controllers/Roster/ContactRosterItem.h> +#include <Swift/Controllers/Roster/ItemOperations/RosterItemOperation.h> namespace Swift { class RosterItem; class SetAvatar : public RosterItemOperation { - public: - SetAvatar(const JID& jid, const boost::filesystem::path& path, JID::CompareType compareType = JID::WithoutResource) : RosterItemOperation(true, jid), jid_(jid), path_(path), compareType_(compareType) { - } - - virtual void operator() (RosterItem* item) const { - ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(item); - if (contact && contact->getJID().equals(jid_, compareType_)) { - contact->setAvatarPath(path_); - } - } - - private: - JID jid_; - boost::filesystem::path path_; - JID::CompareType compareType_; + public: + SetAvatar(const JID& jid, const boost::filesystem::path& path, JID::CompareType compareType = JID::WithoutResource) : RosterItemOperation(true, jid), jid_(jid), path_(path), compareType_(compareType) { + } + + virtual void operator() (RosterItem* item) const { + ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(item); + if (contact && contact->getJID().equals(jid_, compareType_)) { + contact->setAvatarPath(path_); + } + } + + private: + JID jid_; + boost::filesystem::path path_; + JID::CompareType compareType_; }; } diff --git a/Swift/Controllers/Roster/ItemOperations/SetBlockingState.h b/Swift/Controllers/Roster/ItemOperations/SetBlockingState.h index ddb2c7a..818d9b4 100644 --- a/Swift/Controllers/Roster/ItemOperations/SetBlockingState.h +++ b/Swift/Controllers/Roster/ItemOperations/SetBlockingState.h @@ -4,42 +4,48 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once #include <Swiften/JID/JID.h> -#include <Swift/Controllers/Roster/ItemOperations/RosterItemOperation.h> #include <Swift/Controllers/Roster/ContactRosterItem.h> +#include <Swift/Controllers/Roster/ItemOperations/RosterItemOperation.h> namespace Swift { class RosterItem; class SetBlockingState : public RosterItemOperation { - public: - SetBlockingState(const JID& jid, ContactRosterItem::BlockState state, JID::CompareType compareType = JID::WithoutResource) : RosterItemOperation(!jid.getNode().empty(), jid), jid_(jid), state_(state), compareType_(compareType) { - if (state_ == ContactRosterItem::IsBlocked && jid.getNode().empty()) { - state_ = ContactRosterItem::IsDomainBlocked; - } - } - - virtual void operator() (RosterItem* item) const { - ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(item); - if (jid_.getNode().empty()) { - if (contact && contact->getJID().getDomain() == jid_.getDomain()) { - contact->setBlockState(state_); - } - } else { - if (contact && contact->getJID().equals(jid_, compareType_)) { - contact->setBlockState(state_); - } - } - } - - private: - JID jid_; - ContactRosterItem::BlockState state_; - JID::CompareType compareType_; + public: + SetBlockingState(const JID& jid, ContactRosterItem::BlockState state, JID::CompareType compareType = JID::WithoutResource) : RosterItemOperation(!jid.getNode().empty(), jid), jid_(jid), state_(state), compareType_(compareType) { + if (state_ == ContactRosterItem::IsBlocked && jid.getNode().empty()) { + state_ = ContactRosterItem::IsDomainBlocked; + } + } + + virtual void operator() (RosterItem* item) const { + ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(item); + if (jid_.getNode().empty()) { + if (contact && contact->getJID().getDomain() == jid_.getDomain()) { + contact->setBlockState(state_); + } + } else { + if (contact && contact->getJID().equals(jid_, compareType_)) { + contact->setBlockState(state_); + } + } + } + + private: + JID jid_; + ContactRosterItem::BlockState state_; + JID::CompareType compareType_; }; } diff --git a/Swift/Controllers/Roster/ItemOperations/SetMUC.h b/Swift/Controllers/Roster/ItemOperations/SetMUC.h index 5919144..7640c24 100644 --- a/Swift/Controllers/Roster/ItemOperations/SetMUC.h +++ b/Swift/Controllers/Roster/ItemOperations/SetMUC.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014 Isode Limited. + * Copyright (c) 2013-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -8,31 +8,31 @@ #include <Swiften/JID/JID.h> -#include <Swift/Controllers/Roster/ItemOperations/RosterItemOperation.h> #include <Swift/Controllers/Roster/ContactRosterItem.h> +#include <Swift/Controllers/Roster/ItemOperations/RosterItemOperation.h> namespace Swift { class RosterItem; class SetMUC : public RosterItemOperation { - public: - SetMUC(const JID& jid, const MUCOccupant::Role& role, const MUCOccupant::Affiliation& affiliation) - : RosterItemOperation(true, jid), jid_(jid), mucRole_(role), mucAffiliation_(affiliation) { - } - - virtual void operator() (RosterItem* item) const { - ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(item); - if (contact && contact->getJID().equals(jid_, JID::WithResource)) { - contact->setMUCRole(mucRole_); - contact->setMUCAffiliation(mucAffiliation_); - } - } - - private: - JID jid_; - MUCOccupant::Role mucRole_; - MUCOccupant::Affiliation mucAffiliation_; + public: + SetMUC(const JID& jid, const MUCOccupant::Role& role, const MUCOccupant::Affiliation& affiliation) + : RosterItemOperation(true, jid), jid_(jid), mucRole_(role), mucAffiliation_(affiliation) { + } + + virtual void operator() (RosterItem* item) const { + ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(item); + if (contact && contact->getJID().equals(jid_, JID::WithResource)) { + contact->setMUCRole(mucRole_); + contact->setMUCAffiliation(mucAffiliation_); + } + } + + private: + JID jid_; + MUCOccupant::Role mucRole_; + MUCOccupant::Affiliation mucAffiliation_; }; } diff --git a/Swift/Controllers/Roster/ItemOperations/SetName.h b/Swift/Controllers/Roster/ItemOperations/SetName.h index 5708740..fa0694d 100644 --- a/Swift/Controllers/Roster/ItemOperations/SetName.h +++ b/Swift/Controllers/Roster/ItemOperations/SetName.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -8,29 +8,29 @@ #include <Swiften/JID/JID.h> -#include <Swift/Controllers/Roster/ItemOperations/RosterItemOperation.h> #include <Swift/Controllers/Roster/ContactRosterItem.h> +#include <Swift/Controllers/Roster/ItemOperations/RosterItemOperation.h> namespace Swift { class RosterItem; class SetName : public RosterItemOperation { - public: - SetName(const std::string& name, const JID& jid, JID::CompareType compareType = JID::WithoutResource) : RosterItemOperation(true, jid), name_(name), jid_(jid), compareType_(compareType) { - } - - virtual void operator() (RosterItem* item) const { - ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(item); - if (contact && contact->getJID().equals(jid_, compareType_)) { - contact->setDisplayName(name_); - } - } - - private: - std::string name_; - JID jid_; - JID::CompareType compareType_; + public: + SetName(const std::string& name, const JID& jid, JID::CompareType compareType = JID::WithoutResource) : RosterItemOperation(true, jid), name_(name), jid_(jid), compareType_(compareType) { + } + + virtual void operator() (RosterItem* item) const { + ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(item); + if (contact && contact->getJID().equals(jid_, compareType_)) { + contact->setDisplayName(name_); + } + } + + private: + std::string name_; + JID jid_; + JID::CompareType compareType_; }; } diff --git a/Swift/Controllers/Roster/ItemOperations/SetPresence.h b/Swift/Controllers/Roster/ItemOperations/SetPresence.h index 2b5bbbe..fc39e5c 100644 --- a/Swift/Controllers/Roster/ItemOperations/SetPresence.h +++ b/Swift/Controllers/Roster/ItemOperations/SetPresence.h @@ -17,20 +17,20 @@ namespace Swift { class RosterItem; class SetPresence : public RosterItemOperation { - public: - SetPresence(Presence::ref presence, JID::CompareType compareType = JID::WithoutResource) : RosterItemOperation(true, compareType == JID::WithoutResource ? presence->getFrom().toBare() : presence->getFrom()), presence_(presence), compareType_(compareType) { - } - - virtual void operator() (RosterItem* item) const { - ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(item); - if (contact && contact->getJID().equals(presence_->getFrom(), compareType_)) { - contact->applyPresence(presence_); - } - } - - private: - Presence::ref presence_; - JID::CompareType compareType_; + public: + SetPresence(Presence::ref presence, JID::CompareType compareType = JID::WithoutResource) : RosterItemOperation(true, compareType == JID::WithoutResource ? presence->getFrom().toBare() : presence->getFrom()), presence_(presence), compareType_(compareType) { + } + + virtual void operator() (RosterItem* item) const { + ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(item); + if (contact && contact->getJID().equals(presence_->getFrom(), compareType_)) { + contact->applyPresence(presence_); + } + } + + private: + Presence::ref presence_; + JID::CompareType compareType_; }; } diff --git a/Swift/Controllers/Roster/ItemOperations/SetVCard.h b/Swift/Controllers/Roster/ItemOperations/SetVCard.h index 8ee73f9..278ae56 100644 --- a/Swift/Controllers/Roster/ItemOperations/SetVCard.h +++ b/Swift/Controllers/Roster/ItemOperations/SetVCard.h @@ -4,34 +4,40 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once #include <Swiften/Elements/VCard.h> #include <Swiften/JID/JID.h> -#include <Swift/Controllers/Roster/ItemOperations/RosterItemOperation.h> #include <Swift/Controllers/Roster/ContactRosterItem.h> +#include <Swift/Controllers/Roster/ItemOperations/RosterItemOperation.h> namespace Swift { class RosterItem; class SetVCard : public RosterItemOperation { - public: - SetVCard(const JID& jid, VCard::ref vcard, JID::CompareType compareType = JID::WithoutResource) : RosterItemOperation(true, jid), jid_(jid), vcard_(vcard), compareType_(compareType) { - } - - virtual void operator() (RosterItem* item) const { - ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(item); - if (contact && contact->getJID().equals(jid_, compareType_)) { - contact->setVCard(vcard_); - } - } - - private: - JID jid_; - VCard::ref vcard_; - JID::CompareType compareType_; + public: + SetVCard(const JID& jid, VCard::ref vcard, JID::CompareType compareType = JID::WithoutResource) : RosterItemOperation(true, jid), jid_(jid), vcard_(vcard), compareType_(compareType) { + } + + virtual void operator() (RosterItem* item) const { + ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(item); + if (contact && contact->getJID().equals(jid_, compareType_)) { + contact->setVCard(vcard_); + } + } + + private: + JID jid_; + VCard::ref vcard_; + JID::CompareType compareType_; }; } diff --git a/Swift/Controllers/Roster/LeastCommonSubsequence.h b/Swift/Controllers/Roster/LeastCommonSubsequence.h index 0b5aa0a..8daa20c 100644 --- a/Swift/Controllers/Roster/LeastCommonSubsequence.h +++ b/Swift/Controllers/Roster/LeastCommonSubsequence.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2013 Isode Limited. + * Copyright (c) 2011-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -7,101 +7,102 @@ #pragma once #include <vector> + #include <boost/numeric/conversion/cast.hpp> namespace Swift { - using std::equal_to; + using std::equal_to; - namespace Detail { - template<typename XIt, typename YIt, typename Length, typename Predicate> - void computeLeastCommonSubsequenceMatrix(XIt xBegin, XIt xEnd, YIt yBegin, YIt yEnd, std::vector<Length>& result) { - size_t width = static_cast<size_t>(std::distance(xBegin, xEnd) + 1); - size_t height = static_cast<size_t>(std::distance(yBegin, yEnd) + 1); - result.resize(width * height); + namespace Detail { + template<typename XIt, typename YIt, typename Length, typename Predicate> + void computeLeastCommonSubsequenceMatrix(XIt xBegin, XIt xEnd, YIt yBegin, YIt yEnd, std::vector<Length>& result) { + size_t width = static_cast<size_t>(std::distance(xBegin, xEnd) + 1); + size_t height = static_cast<size_t>(std::distance(yBegin, yEnd) + 1); + result.resize(width * height); - // Initialize first row & column - for (size_t i = 0; i < width; ++i) { - result[i] = 0; - } - for (size_t j = 0; j < height; ++j) { - result[j*width] = 0; - } + // Initialize first row & column + for (size_t i = 0; i < width; ++i) { + result[i] = 0; + } + for (size_t j = 0; j < height; ++j) { + result[j*width] = 0; + } - // Compute the LCS lengths for subsets - Predicate predicate; - for (size_t i = 1; i < width; ++i) { - for (size_t j = 1; j < height; ++j) { - result[i + j*width] = predicate(*(xBegin + boost::numeric_cast<long long>(i)-1), *(yBegin + boost::numeric_cast<long long >(j)-1)) ? result[(i-1) + (j-1)*width] + 1 : std::max(result[i + (j-1)*width], result[i-1 + (j*width)]); - } - } - } - } + // Compute the LCS lengths for subsets + Predicate predicate; + for (size_t i = 1; i < width; ++i) { + for (size_t j = 1; j < height; ++j) { + result[i + j*width] = predicate(*(xBegin + boost::numeric_cast<long long>(i)-1), *(yBegin + boost::numeric_cast<long long >(j)-1)) ? result[(i-1) + (j-1)*width] + 1 : std::max(result[i + (j-1)*width], result[i-1 + (j*width)]); + } + } + } + } - template<typename X, typename InsertRemovePredicate, typename UpdatePredicate> - void computeIndexDiff(const std::vector<X>& x, const std::vector<X>& y, std::vector<size_t>& updates, std::vector<size_t>& postUpdates, std::vector<size_t>& removes, std::vector<size_t>& inserts) { - InsertRemovePredicate insertRemovePredicate; - UpdatePredicate updatePredicate; + template<typename X, typename InsertRemovePredicate, typename UpdatePredicate> + void computeIndexDiff(const std::vector<X>& x, const std::vector<X>& y, std::vector<size_t>& updates, std::vector<size_t>& postUpdates, std::vector<size_t>& removes, std::vector<size_t>& inserts) { + InsertRemovePredicate insertRemovePredicate; + UpdatePredicate updatePredicate; - // Find & handle common prefix (Optimization to reduce LCS matrix size) - typename std::vector<X>::const_iterator xBegin = x.begin(); - typename std::vector<X>::const_iterator yBegin = y.begin(); - while (xBegin < x.end() && yBegin < y.end() && insertRemovePredicate(*xBegin, *yBegin)) { - if (updatePredicate(*xBegin, *yBegin)) { - updates.push_back(static_cast<size_t>(std::distance(x.begin(), xBegin))); - postUpdates.push_back(static_cast<size_t>(std::distance(y.begin(), yBegin))); - } - ++xBegin; - ++yBegin; - } - size_t prefixLength = static_cast<size_t>(std::distance(x.begin(), xBegin)); + // Find & handle common prefix (Optimization to reduce LCS matrix size) + typename std::vector<X>::const_iterator xBegin = x.begin(); + typename std::vector<X>::const_iterator yBegin = y.begin(); + while (xBegin < x.end() && yBegin < y.end() && insertRemovePredicate(*xBegin, *yBegin)) { + if (updatePredicate(*xBegin, *yBegin)) { + updates.push_back(static_cast<size_t>(std::distance(x.begin(), xBegin))); + postUpdates.push_back(static_cast<size_t>(std::distance(y.begin(), yBegin))); + } + ++xBegin; + ++yBegin; + } + size_t prefixLength = static_cast<size_t>(std::distance(x.begin(), xBegin)); - // Find & handle common suffix (Optimization to reduce LCS matrix size) - typename std::vector<X>::const_reverse_iterator xEnd = x.rbegin(); - typename std::vector<X>::const_reverse_iterator yEnd = y.rbegin(); - while (xEnd.base() > xBegin && yEnd.base() > yBegin && insertRemovePredicate(*xEnd, *yEnd)) { - if (updatePredicate(*xEnd, *yEnd)) { - updates.push_back(static_cast<size_t>(std::distance(x.begin(), xEnd.base()) - 1)); - postUpdates.push_back(static_cast<size_t>(std::distance(y.begin(), yEnd.base()) - 1)); - } - ++xEnd; - ++yEnd; - } + // Find & handle common suffix (Optimization to reduce LCS matrix size) + typename std::vector<X>::const_reverse_iterator xEnd = x.rbegin(); + typename std::vector<X>::const_reverse_iterator yEnd = y.rbegin(); + while (xEnd.base() > xBegin && yEnd.base() > yBegin && insertRemovePredicate(*xEnd, *yEnd)) { + if (updatePredicate(*xEnd, *yEnd)) { + updates.push_back(static_cast<size_t>(std::distance(x.begin(), xEnd.base()) - 1)); + postUpdates.push_back(static_cast<size_t>(std::distance(y.begin(), yEnd.base()) - 1)); + } + ++xEnd; + ++yEnd; + } - // Compute lengths - size_t xLength = static_cast<size_t>(std::distance(xBegin, xEnd.base())); - size_t yLength = static_cast<size_t>(std::distance(yBegin, yEnd.base())); + // Compute lengths + size_t xLength = static_cast<size_t>(std::distance(xBegin, xEnd.base())); + size_t yLength = static_cast<size_t>(std::distance(yBegin, yEnd.base())); - // Compute LCS matrix - std::vector<unsigned int> lcs; - Detail::computeLeastCommonSubsequenceMatrix<typename std::vector<X>::const_iterator, typename std::vector<X>::const_iterator, unsigned int, InsertRemovePredicate>(xBegin, xEnd.base(), yBegin, yEnd.base(), lcs); + // Compute LCS matrix + std::vector<unsigned int> lcs; + Detail::computeLeastCommonSubsequenceMatrix<typename std::vector<X>::const_iterator, typename std::vector<X>::const_iterator, unsigned int, InsertRemovePredicate>(xBegin, xEnd.base(), yBegin, yEnd.base(), lcs); - // Process LCS matrix - size_t i = xLength; - size_t j = yLength; - size_t width = xLength + 1; - while (true) { - if (i > 0 && j > 0 && insertRemovePredicate(x[prefixLength + i-1], y[prefixLength + j-1])) { - // x[i-1] same - if (updatePredicate(x[prefixLength + i - 1], y[prefixLength + j - 1])) { - updates.push_back(prefixLength + i-1); - postUpdates.push_back(prefixLength + j-1); - } - i -= 1; - j -= 1; - } - else if (j > 0 && (i == 0 || lcs[i + (j-1)*width] >= lcs[i-1 + j*width])) { - // y[j-1] added - inserts.push_back(prefixLength + j-1); - j -= 1; - } - else if (i > 0 && (j == 0 || lcs[i + (j-1)*width] < lcs[i-1 + j*width])) { - // x[i-1] removed - removes.push_back(prefixLength + i-1); - i -= 1; - } - else { - break; - } - } - } + // Process LCS matrix + size_t i = xLength; + size_t j = yLength; + size_t width = xLength + 1; + while (true) { + if (i > 0 && j > 0 && insertRemovePredicate(x[prefixLength + i-1], y[prefixLength + j-1])) { + // x[i-1] same + if (updatePredicate(x[prefixLength + i - 1], y[prefixLength + j - 1])) { + updates.push_back(prefixLength + i-1); + postUpdates.push_back(prefixLength + j-1); + } + i -= 1; + j -= 1; + } + else if (j > 0 && (i == 0 || lcs[i + (j-1)*width] >= lcs[i-1 + j*width])) { + // y[j-1] added + inserts.push_back(prefixLength + j-1); + j -= 1; + } + else if (i > 0 && (j == 0 || lcs[i + (j-1)*width] < lcs[i-1 + j*width])) { + // x[i-1] removed + removes.push_back(prefixLength + i-1); + i -= 1; + } + else { + break; + } + } + } } diff --git a/Swift/Controllers/Roster/OfflineRosterFilter.h b/Swift/Controllers/Roster/OfflineRosterFilter.h index 61ac3f4..033eecb 100644 --- a/Swift/Controllers/Roster/OfflineRosterFilter.h +++ b/Swift/Controllers/Roster/OfflineRosterFilter.h @@ -1,25 +1,26 @@ /* - * Copyright (c) 2010 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include "Swift/Controllers/Roster/ContactRosterItem.h" -#include "Swift/Controllers/Roster/RosterItem.h" -#include "Swift/Controllers/Roster/RosterFilter.h" -#include "Swiften/Elements/StatusShow.h" +#include <Swiften/Elements/StatusShow.h> + +#include <Swift/Controllers/Roster/ContactRosterItem.h> +#include <Swift/Controllers/Roster/RosterFilter.h> +#include <Swift/Controllers/Roster/RosterItem.h> namespace Swift { class OfflineRosterFilter : public RosterFilter { - public: - virtual ~OfflineRosterFilter() {} - virtual bool operator() (RosterItem *item) const { - ContactRosterItem *contactItem = dynamic_cast<ContactRosterItem*>(item); - return contactItem && contactItem->getStatusShow() == StatusShow::None; - } + public: + virtual ~OfflineRosterFilter() {} + virtual bool operator() (RosterItem *item) const { + ContactRosterItem *contactItem = dynamic_cast<ContactRosterItem*>(item); + return contactItem && contactItem->getStatusShow() == StatusShow::None; + } }; } diff --git a/Swift/Controllers/Roster/Roster.cpp b/Swift/Controllers/Roster/Roster.cpp index 77d6b78..68297a4 100644 --- a/Swift/Controllers/Roster/Roster.cpp +++ b/Swift/Controllers/Roster/Roster.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2015 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -7,12 +7,12 @@ #include <Swift/Controllers/Roster/Roster.h> #include <deque> +#include <memory> #include <set> #include <string> #include <boost/bind.hpp> -#include <Swiften/Base/foreach.h> #include <Swiften/JID/JID.h> #include <Swift/Controllers/Roster/ContactRosterItem.h> @@ -22,253 +22,250 @@ 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::unique_ptr<GroupRosterItem>(new 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()); - } - ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(item); - if (contact) { - contact->onVCardRequested.disconnect(boost::bind(boost::ref(onVCardUpdateRequested), contact->getJID())); - } - 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() const { - return root_; + return root_.get(); } std::set<JID> Roster::getJIDs() const { - std::set<JID> jids; - - std::deque<RosterItem*> queue; - queue.push_back(root_); - 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; + 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; } 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; + 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::setBlockingSupported(bool isSupported) { - if (!blockingSupported_) { - foreach(ItemMap::value_type i, itemMap_) { - foreach(ContactRosterItem* item, i.second) { - item->setBlockState(ContactRosterItem::IsUnblocked); - } - } - } - blockingSupported_ = 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->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()) { - 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) { + 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()) { + 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); + 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(); - onFilterRemoved(filter); + for (unsigned int i = 0; i < filters_.size(); i++) { + if (filters_[i] == filter) { + filters_.erase(filters_.begin() + i); + break; + } + } + 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); + } + } } } diff --git a/Swift/Controllers/Roster/Roster.h b/Swift/Controllers/Roster/Roster.h index 269ec4d..d22b38d 100644 --- a/Swift/Controllers/Roster/Roster.h +++ b/Swift/Controllers/Roster/Roster.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2015 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -7,13 +7,13 @@ #pragma once #include <map> +#include <memory> #include <set> #include <string> #include <vector> -#include <boost/shared_ptr.hpp> +#include <boost/signals2.hpp> -#include <Swiften/Base/boost_bsignals.h> #include <Swiften/JID/JID.h> #include <Swift/Controllers/Roster/ContactRosterItem.h> @@ -27,46 +27,48 @@ class GroupRosterItem; class ContactRosterItem; class Roster { - public: - Roster(bool sortByStatus = true, bool fullJIDMapping = false); - ~Roster(); + public: + Roster(bool sortByStatus = true, bool fullJIDMapping = false); + ~Roster(); - void addContact(const JID& jid, const JID& displayJID, const std::string& name, const std::string& group, const boost::filesystem::path& avatarPath); - void removeContact(const JID& jid); - void removeContactFromGroup(const JID& jid, const std::string& group); - void removeGroup(const std::string& group); - void removeAll(); - void applyOnItems(const RosterItemOperation& operation); - void applyOnAllItems(const RosterItemOperation& operation); - void applyOnItem(const RosterItemOperation& operation, const JID& jid); - void addFilter(RosterFilter* filter); - void removeFilter(RosterFilter* filter); - GroupRosterItem* getRoot() const; - std::set<JID> getJIDs() const; + void addContact(const JID& jid, const JID& displayJID, const std::string& name, const std::string& group, const boost::filesystem::path& avatarPath); + void removeContact(const JID& jid); + void removeContactFromGroup(const JID& jid, const std::string& group); + void removeGroup(const std::string& group); + void removeAll(); + void applyOnItems(const RosterItemOperation& operation); + void applyOnAllItems(const RosterItemOperation& operation); + void applyOnItem(const RosterItemOperation& operation, const JID& jid); + void addFilter(RosterFilter* filter); + void removeFilter(RosterFilter* filter); + GroupRosterItem* getRoot() const; + std::set<JID> getJIDs() const; - std::vector<RosterFilter*> getFilters() {return filters_;} - boost::signal<void (GroupRosterItem*)> onChildrenChanged; - boost::signal<void (GroupRosterItem*)> onGroupAdded; - boost::signal<void (RosterItem*)> onDataChanged; - boost::signal<void (JID&)> onVCardUpdateRequested; - boost::signal<void (RosterFilter* filter)> onFilterAdded; - boost::signal<void (RosterFilter* filter)> onFilterRemoved; - GroupRosterItem* getGroup(const std::string& groupName); - void setBlockingSupported(bool isSupported); + std::vector<RosterFilter*> getFilters() {return filters_;} + boost::signals2::signal<void (GroupRosterItem*)> onChildrenChanged; + boost::signals2::signal<void (GroupRosterItem*)> onGroupAdded; + boost::signals2::signal<void (RosterItem*)> onDataChanged; + boost::signals2::signal<void (JID&)> onVCardUpdateRequested; + boost::signals2::signal<void (RosterFilter* filter)> onFilterAdded; + boost::signals2::signal<void (RosterFilter* filter)> onFilterRemoved; + GroupRosterItem* getGroup(const std::string& groupName); + void setBlockingSupported(bool isSupported); - private: - void handleDataChanged(RosterItem* item); - void handleChildrenChanged(GroupRosterItem* item); - void filterGroup(GroupRosterItem* item); - void filterContact(ContactRosterItem* contact, GroupRosterItem* group); - void filterAll(); - GroupRosterItem* root_; - std::vector<RosterFilter*> filters_; - typedef std::map<JID, std::vector<ContactRosterItem*> > ItemMap; - ItemMap itemMap_; - bool fullJIDMapping_; - bool sortByStatus_; - bool blockingSupported_; + private: + void handleDataChanged(RosterItem* item); + void handleChildrenChanged(GroupRosterItem* item); + void filterGroup(GroupRosterItem* item); + void filterContact(ContactRosterItem* contact, GroupRosterItem* group); + void filterAll(); + + private: + std::vector<RosterFilter*> filters_; + typedef std::map<JID, std::vector<ContactRosterItem*> > ItemMap; + ItemMap itemMap_; + bool fullJIDMapping_; + bool sortByStatus_; + bool blockingSupported_ = false; + const std::unique_ptr<GroupRosterItem> root_; }; } diff --git a/Swift/Controllers/Roster/RosterController.cpp b/Swift/Controllers/Roster/RosterController.cpp index 4fbdea4..1d20c4a 100644 --- a/Swift/Controllers/Roster/RosterController.cpp +++ b/Swift/Controllers/Roster/RosterController.cpp @@ -1,22 +1,23 @@ /* - * Copyright (c) 2010-2015 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #include <Swift/Controllers/Roster/RosterController.h> +#include <memory> + #include <boost/bind.hpp> -#include <boost/smart_ptr/make_shared.hpp> #include <Swiften/Avatars/AvatarManager.h> #include <Swiften/Base/Path.h> -#include <Swiften/Base/foreach.h> #include <Swiften/Base/format.h> #include <Swiften/Client/ClientBlockListManager.h> #include <Swiften/Client/NickManager.h> #include <Swiften/Client/NickResolver.h> #include <Swiften/Disco/EntityCapsManager.h> +#include <Swiften/Disco/FeatureOracle.h> #include <Swiften/Elements/DiscoInfo.h> #include <Swiften/FileTransfer/FileTransferManager.h> #include <Swiften/JID/JID.h> @@ -30,7 +31,6 @@ #include <Swiften/Roster/XMPPRosterItem.h> #include <Swiften/VCards/VCardManager.h> -#include <Swift/Controllers/FileTransfer/FileTransferOverview.h> #include <Swift/Controllers/Intl.h> #include <Swift/Controllers/Roster/GroupRosterItem.h> #include <Swift/Controllers/Roster/ItemOperations/AppearOffline.h> @@ -49,7 +49,6 @@ #include <Swift/Controllers/UIEvents/RemoveRosterItemUIEvent.h> #include <Swift/Controllers/UIEvents/RenameGroupUIEvent.h> #include <Swift/Controllers/UIEvents/RenameRosterItemUIEvent.h> -#include <Swift/Controllers/UIEvents/SendFileUIEvent.h> #include <Swift/Controllers/UIInterfaces/MainWindow.h> #include <Swift/Controllers/UIInterfaces/MainWindowFactory.h> #include <Swift/Controllers/XMPPEvents/ErrorEvent.h> @@ -61,355 +60,347 @@ namespace Swift { /** * The controller does not gain ownership of these parameters. */ -RosterController::RosterController(const JID& jid, XMPPRoster* xmppRoster, AvatarManager* avatarManager, MainWindowFactory* mainWindowFactory, NickManager* nickManager, NickResolver* nickResolver, PresenceOracle* presenceOracle, SubscriptionManager* subscriptionManager, EventController* eventController, UIEventStream* uiEventStream, IQRouter* iqRouter, SettingsProvider* settings, EntityCapsProvider* entityCapsManager, FileTransferOverview* fileTransferOverview, ClientBlockListManager* clientBlockListManager, VCardManager* vcardManager) - : myJID_(jid), xmppRoster_(xmppRoster), mainWindowFactory_(mainWindowFactory), mainWindow_(mainWindowFactory_->createMainWindow(uiEventStream)), roster_(new Roster()), offlineFilter_(new OfflineRosterFilter()), vcardManager_(vcardManager), avatarManager_(avatarManager), nickManager_(nickManager), nickResolver_(nickResolver), presenceOracle_(presenceOracle), uiEventStream_(uiEventStream), entityCapsManager_(entityCapsManager), ftOverview_(fileTransferOverview), clientBlockListManager_(clientBlockListManager) { - assert(fileTransferOverview); - iqRouter_ = iqRouter; - subscriptionManager_ = subscriptionManager; - eventController_ = eventController; - settings_ = settings; - expandiness_ = new RosterGroupExpandinessPersister(roster_, settings); - mainWindow_->setRosterModel(roster_); - rosterVCardProvider_ = new RosterVCardProvider(roster_, vcardManager, JID::WithoutResource); - - changeStatusConnection_ = mainWindow_->onChangeStatusRequest.connect(boost::bind(&RosterController::handleChangeStatusRequest, this, _1, _2)); - signOutConnection_ = mainWindow_->onSignOutRequest.connect(boost::bind(boost::ref(onSignOutRequest))); - xmppRoster_->onJIDAdded.connect(boost::bind(&RosterController::handleOnJIDAdded, this, _1)); - xmppRoster_->onJIDUpdated.connect(boost::bind(&RosterController::handleOnJIDUpdated, this, _1, _2, _3)); - xmppRoster_->onJIDRemoved.connect(boost::bind(&RosterController::handleOnJIDRemoved, this, _1)); - xmppRoster_->onRosterCleared.connect(boost::bind(&RosterController::handleRosterCleared, this)); - subscriptionManager_->onPresenceSubscriptionRequest.connect(boost::bind(&RosterController::handleSubscriptionRequest, this, _1, _2)); - uiEventConnection_ = uiEventStream->onUIEvent.connect(boost::bind(&RosterController::handleUIEvent, this, _1)); - - vcardManager_->onOwnVCardChanged.connect(boost::bind(&RosterController::handleOwnVCardChanged, this, _1)); - avatarManager_->onAvatarChanged.connect(boost::bind(&RosterController::handleAvatarChanged, this, _1)); - presenceOracle_->onPresenceChange.connect(boost::bind(&RosterController::handlePresenceChanged, this, _1)); - mainWindow_->setMyAvatarPath(pathToString(avatarManager_->getAvatarPath(myJID_.toBare()))); - - nickManager_->onOwnNickChanged.connect(boost::bind(&MainWindow::setMyNick, mainWindow_, _1)); - mainWindow_->setMyJID(jid); - mainWindow_->setMyNick(nickManager_->getOwnNick()); - - entityCapsManager_->onCapsChanged.connect(boost::bind(&RosterController::handleOnCapsChanged, this, _1)); - - settings_->onSettingChanged.connect(boost::bind(&RosterController::handleSettingChanged, this, _1)); - - handleShowOfflineToggled(settings_->getSetting(SettingConstants::SHOW_OFFLINE)); - - ownContact_ = boost::make_shared<ContactRosterItem>(myJID_.toBare(), myJID_.toBare(), nickManager_->getOwnNick(), static_cast<GroupRosterItem*>(0)); - ownContact_->setVCard(vcardManager_->getVCard(myJID_.toBare())); - ownContact_->setAvatarPath(pathToString(avatarManager_->getAvatarPath(myJID_.toBare()))); - mainWindow_->setMyContactRosterItem(ownContact_); +RosterController::RosterController(const JID& jid, XMPPRoster* xmppRoster, AvatarManager* avatarManager, MainWindowFactory* mainWindowFactory, NickManager* nickManager, NickResolver* nickResolver, PresenceOracle* presenceOracle, SubscriptionManager* subscriptionManager, EventController* eventController, UIEventStream* uiEventStream, IQRouter* iqRouter, SettingsProvider* settings, EntityCapsProvider* entityCapsManager, ClientBlockListManager* clientBlockListManager, VCardManager* vcardManager) + : myJID_(jid), xmppRoster_(xmppRoster), mainWindowFactory_(mainWindowFactory), mainWindow_(mainWindowFactory_->createMainWindow(uiEventStream)), roster_(new Roster()), offlineFilter_(new OfflineRosterFilter()), vcardManager_(vcardManager), avatarManager_(avatarManager), nickManager_(nickManager), nickResolver_(nickResolver), presenceOracle_(presenceOracle), uiEventStream_(uiEventStream), entityCapsManager_(entityCapsManager), clientBlockListManager_(clientBlockListManager) { + iqRouter_ = iqRouter; + subscriptionManager_ = subscriptionManager; + eventController_ = eventController; + settings_ = settings; + expandiness_ = new RosterGroupExpandinessPersister(roster_, settings); + mainWindow_->setRosterModel(roster_); + rosterVCardProvider_ = new RosterVCardProvider(roster_, vcardManager, JID::WithoutResource); + + changeStatusConnection_ = mainWindow_->onChangeStatusRequest.connect(boost::bind(&RosterController::handleChangeStatusRequest, this, _1, _2)); + signOutConnection_ = mainWindow_->onSignOutRequest.connect(boost::bind(boost::ref(onSignOutRequest))); + xmppRoster_->onJIDAdded.connect(boost::bind(&RosterController::handleOnJIDAdded, this, _1)); + xmppRoster_->onJIDUpdated.connect(boost::bind(&RosterController::handleOnJIDUpdated, this, _1, _2, _3)); + xmppRoster_->onJIDRemoved.connect(boost::bind(&RosterController::handleOnJIDRemoved, this, _1)); + xmppRoster_->onRosterCleared.connect(boost::bind(&RosterController::handleRosterCleared, this)); + subscriptionManager_->onPresenceSubscriptionRequest.connect(boost::bind(&RosterController::handleSubscriptionRequest, this, _1, _2)); + uiEventConnection_ = uiEventStream->onUIEvent.connect(boost::bind(&RosterController::handleUIEvent, this, _1)); + + featureOracle_ = std::unique_ptr<FeatureOracle>(new FeatureOracle(entityCapsManager_, presenceOracle_)); + + vcardManager_->onOwnVCardChanged.connect(boost::bind(&RosterController::handleOwnVCardChanged, this, _1)); + avatarManager_->onAvatarChanged.connect(boost::bind(&RosterController::handleAvatarChanged, this, _1)); + presenceOracle_->onPresenceChange.connect(boost::bind(&RosterController::handlePresenceChanged, this, _1)); + mainWindow_->setMyAvatarPath(pathToString(avatarManager_->getAvatarPath(myJID_.toBare()))); + + nickManager_->onOwnNickChanged.connect(boost::bind(&MainWindow::setMyNick, mainWindow_, _1)); + mainWindow_->setMyJID(jid); + mainWindow_->setMyNick(nickManager_->getOwnNick()); + + entityCapsManager_->onCapsChanged.connect(boost::bind(&RosterController::handleOnCapsChanged, this, _1)); + + settings_->onSettingChanged.connect(boost::bind(&RosterController::handleSettingChanged, this, _1)); + + handleShowOfflineToggled(settings_->getSetting(SettingConstants::SHOW_OFFLINE)); + + ownContact_ = std::make_shared<ContactRosterItem>(myJID_.toBare(), myJID_.toBare(), nickManager_->getOwnNick(), static_cast<GroupRosterItem*>(nullptr)); + ownContact_->setVCard(vcardManager_->getVCard(myJID_.toBare())); + ownContact_->setAvatarPath(pathToString(avatarManager_->getAvatarPath(myJID_.toBare()))); + mainWindow_->setMyContactRosterItem(ownContact_); } -RosterController::~RosterController() { - settings_->onSettingChanged.disconnect(boost::bind(&RosterController::handleSettingChanged, this, _1)); - nickManager_->onOwnNickChanged.disconnect(boost::bind(&MainWindow::setMyNick, mainWindow_, _1)); - - delete offlineFilter_; - delete expandiness_; +RosterController::~RosterController() { + settings_->onSettingChanged.disconnect(boost::bind(&RosterController::handleSettingChanged, this, _1)); + nickManager_->onOwnNickChanged.disconnect(boost::bind(&MainWindow::setMyNick, mainWindow_, _1)); + + delete offlineFilter_; + delete expandiness_; - mainWindow_->setRosterModel(NULL); - if (mainWindow_->canDelete()) { - delete mainWindow_; - } - delete rosterVCardProvider_; - delete roster_; + mainWindow_->setRosterModel(nullptr); + if (mainWindow_->canDelete()) { + delete mainWindow_; + } + delete rosterVCardProvider_; + delete roster_; } void RosterController::setEnabled(bool enabled) { - if (!enabled) { - roster_->applyOnItems(AppearOffline()); - } + if (!enabled) { + roster_->applyOnItems(AppearOffline()); + } } void RosterController::handleShowOfflineToggled(bool state) { - if (state) { - roster_->removeFilter(offlineFilter_); - } else { - roster_->addFilter(offlineFilter_); - } + if (state) { + roster_->removeFilter(offlineFilter_); + } else { + roster_->addFilter(offlineFilter_); + } } void RosterController::handleChangeStatusRequest(StatusShow::Type show, const std::string &statusText) { - onChangeStatusRequest(show, statusText); + onChangeStatusRequest(show, statusText); } void RosterController::handleOnJIDAdded(const JID& jid) { - std::vector<std::string> groups = xmppRoster_->getGroupsForJID(jid); - std::string name = nickResolver_->jidToNick(jid); - if (!groups.empty()) { - foreach(const std::string& group, groups) { - roster_->addContact(jid, jid, name, group, avatarManager_->getAvatarPath(jid)); - } - } - else { - roster_->addContact(jid, jid, name, QT_TRANSLATE_NOOP("", "Contacts"), avatarManager_->getAvatarPath(jid)); - } - applyAllPresenceTo(jid); + std::vector<std::string> groups = xmppRoster_->getGroupsForJID(jid); + std::string name = nickResolver_->jidToNick(jid); + if (!groups.empty()) { + for (const auto& group : groups) { + roster_->addContact(jid, jid, name, group, avatarManager_->getAvatarPath(jid)); + } + } + else { + roster_->addContact(jid, jid, name, QT_TRANSLATE_NOOP("", "Contacts"), avatarManager_->getAvatarPath(jid)); + } + applyAllPresenceTo(jid); } void RosterController::applyAllPresenceTo(const JID& jid) { - foreach (Presence::ref presence, presenceOracle_->getAllPresence(jid)) { - roster_->applyOnItems(SetPresence(presence)); - } + for (auto&& presence : presenceOracle_->getAllPresence(jid)) { + roster_->applyOnItems(SetPresence(presence)); + } } void RosterController::handleRosterCleared() { - roster_->removeAll(); + roster_->removeAll(); } void RosterController::handleOnJIDRemoved(const JID& jid) { - roster_->removeContact(jid); + roster_->removeContact(jid); } void RosterController::handleOnJIDUpdated(const JID& jid, const std::string& oldName, const std::vector<std::string>& passedOldGroups) { - if (oldName != xmppRoster_->getNameForJID(jid)) { - roster_->applyOnItems(SetName(nickResolver_->jidToNick(jid), jid)); - } - std::vector<std::string> groups = xmppRoster_->getGroupsForJID(jid); - std::vector<std::string> oldGroups = passedOldGroups; - std::string name = nickResolver_->jidToNick(jid); - std::string contactsGroup = QT_TRANSLATE_NOOP("", "Contacts"); - if (oldGroups.empty()) { - oldGroups.push_back(contactsGroup); - } - if (groups.empty()) { - groups.push_back(contactsGroup); - } - foreach(const std::string& group, groups) { - if (std::find(oldGroups.begin(), oldGroups.end(), group) == oldGroups.end()) { - roster_->addContact(jid, jid, name, group, avatarManager_->getAvatarPath(jid)); - } - } - foreach(const std::string& group, oldGroups) { - if (std::find(groups.begin(), groups.end(), group) == groups.end()) { - roster_->removeContactFromGroup(jid, group); - if (roster_->getGroup(group)->getChildren().size() == 0) { - roster_->removeGroup(group); - } - } - } - applyAllPresenceTo(jid); + if (oldName != xmppRoster_->getNameForJID(jid)) { + roster_->applyOnItems(SetName(nickResolver_->jidToNick(jid), jid)); + } + std::vector<std::string> groups = xmppRoster_->getGroupsForJID(jid); + std::vector<std::string> oldGroups = passedOldGroups; + std::string name = nickResolver_->jidToNick(jid); + std::string contactsGroup = QT_TRANSLATE_NOOP("", "Contacts"); + if (oldGroups.empty()) { + oldGroups.push_back(contactsGroup); + } + if (groups.empty()) { + groups.push_back(contactsGroup); + } + for (const auto& group : groups) { + if (std::find(oldGroups.begin(), oldGroups.end(), group) == oldGroups.end()) { + roster_->addContact(jid, jid, name, group, avatarManager_->getAvatarPath(jid)); + } + } + for (const auto& group : oldGroups) { + if (std::find(groups.begin(), groups.end(), group) == groups.end()) { + roster_->removeContactFromGroup(jid, group); + if (roster_->getGroup(group)->getChildren().size() == 0) { + roster_->removeGroup(group); + } + } + } + applyAllPresenceTo(jid); } void RosterController::handleSettingChanged(const std::string& settingPath) { - if (settingPath == SettingConstants::SHOW_OFFLINE.getKey()) { - handleShowOfflineToggled(settings_->getSetting(SettingConstants::SHOW_OFFLINE)); - } + if (settingPath == SettingConstants::SHOW_OFFLINE.getKey()) { + handleShowOfflineToggled(settings_->getSetting(SettingConstants::SHOW_OFFLINE)); + } } void RosterController::handleBlockingStateChanged() { - if (clientBlockListManager_->getBlockList()->getState() == BlockList::Available) { - foreach(const JID& jid, clientBlockListManager_->getBlockList()->getItems()) { - roster_->applyOnItems(SetBlockingState(jid, ContactRosterItem::IsBlocked)); - } - } + if (clientBlockListManager_->getBlockList()->getState() == BlockList::Available) { + for (const auto& jid : clientBlockListManager_->getBlockList()->getItems()) { + roster_->applyOnItems(SetBlockingState(jid, ContactRosterItem::IsBlocked)); + } + } } void RosterController::handleBlockingItemAdded(const JID& jid) { - roster_->applyOnItems(SetBlockingState(jid, ContactRosterItem::IsBlocked)); + roster_->applyOnItems(SetBlockingState(jid, ContactRosterItem::IsBlocked)); } void RosterController::handleBlockingItemRemoved(const JID& jid) { - roster_->applyOnItems(SetBlockingState(jid, ContactRosterItem::IsUnblocked)); + roster_->applyOnItems(SetBlockingState(jid, ContactRosterItem::IsUnblocked)); } -void RosterController::handleUIEvent(boost::shared_ptr<UIEvent> event) { - if (boost::shared_ptr<AddContactUIEvent> addContactEvent = boost::dynamic_pointer_cast<AddContactUIEvent>(event)) { - RosterItemPayload item; - item.setName(addContactEvent->getName()); - item.setJID(addContactEvent->getJID()); - item.setGroups(std::vector<std::string>(addContactEvent->getGroups().begin(), addContactEvent->getGroups().end())); - boost::shared_ptr<RosterPayload> roster(new RosterPayload()); - roster->addItem(item); - SetRosterRequest::ref request = SetRosterRequest::create(roster, iqRouter_); - request->onResponse.connect(boost::bind(&RosterController::handleRosterSetError, this, _1, roster)); - request->send(); - subscriptionManager_->requestSubscription(addContactEvent->getJID()); - } - else if (boost::shared_ptr<RemoveRosterItemUIEvent> removeEvent = boost::dynamic_pointer_cast<RemoveRosterItemUIEvent>(event)) { - RosterItemPayload item(removeEvent->getJID(), "", RosterItemPayload::Remove); - boost::shared_ptr<RosterPayload> roster(new RosterPayload()); - roster->addItem(item); - SetRosterRequest::ref request = SetRosterRequest::create(roster, iqRouter_); - request->onResponse.connect(boost::bind(&RosterController::handleRosterSetError, this, _1, roster)); - request->send(); - - } - else if (boost::shared_ptr<RenameRosterItemUIEvent> renameEvent = boost::dynamic_pointer_cast<RenameRosterItemUIEvent>(event)) { - JID contact(renameEvent->getJID()); - RosterItemPayload item(contact, renameEvent->getNewName(), xmppRoster_->getSubscriptionStateForJID(contact)); - item.setGroups(xmppRoster_->getGroupsForJID(contact)); - boost::shared_ptr<RosterPayload> roster(new RosterPayload()); - roster->addItem(item); - SetRosterRequest::ref request = SetRosterRequest::create(roster, iqRouter_); - request->onResponse.connect(boost::bind(&RosterController::handleRosterSetError, this, _1, roster)); - request->send(); - } - else if (boost::shared_ptr<RenameGroupUIEvent> renameGroupEvent = boost::dynamic_pointer_cast<RenameGroupUIEvent>(event)) { - std::vector<XMPPRosterItem> items = xmppRoster_->getItems(); - std::string group = renameGroupEvent->getGroup(); - // FIXME: We should handle contacts groups specially to avoid clashes - if (group == QT_TRANSLATE_NOOP("", "Contacts")) { - group = ""; - } - foreach(XMPPRosterItem& item, items) { - std::vector<std::string> groups = item.getGroups(); - if ( (group.empty() && groups.empty()) || std::find(groups.begin(), groups.end(), group) != groups.end()) { - groups.erase(std::remove(groups.begin(), groups.end(), group), groups.end()); - if (std::find(groups.begin(), groups.end(), renameGroupEvent->getNewName()) == groups.end()) { - groups.push_back(renameGroupEvent->getNewName()); - } - item.setGroups(groups); - updateItem(item); - } - } - } - else if (boost::shared_ptr<SendFileUIEvent> sendFileEvent = boost::dynamic_pointer_cast<SendFileUIEvent>(event)) { - //TODO add send file dialog to ChatView of receipient jid - ftOverview_->sendFile(sendFileEvent->getJID(), sendFileEvent->getFilename()); - } +void RosterController::handleUIEvent(std::shared_ptr<UIEvent> event) { + if (std::shared_ptr<AddContactUIEvent> addContactEvent = std::dynamic_pointer_cast<AddContactUIEvent>(event)) { + RosterItemPayload item; + item.setName(addContactEvent->getName()); + item.setJID(addContactEvent->getJID()); + item.setGroups(std::vector<std::string>(addContactEvent->getGroups().begin(), addContactEvent->getGroups().end())); + std::shared_ptr<RosterPayload> roster(new RosterPayload()); + roster->addItem(item); + SetRosterRequest::ref request = SetRosterRequest::create(roster, iqRouter_); + request->onResponse.connect(boost::bind(&RosterController::handleRosterSetError, this, _1, roster)); + request->send(); + subscriptionManager_->requestSubscription(addContactEvent->getJID()); + } + else if (std::shared_ptr<RemoveRosterItemUIEvent> removeEvent = std::dynamic_pointer_cast<RemoveRosterItemUIEvent>(event)) { + RosterItemPayload item(removeEvent->getJID(), "", RosterItemPayload::Remove); + std::shared_ptr<RosterPayload> roster(new RosterPayload()); + roster->addItem(item); + SetRosterRequest::ref request = SetRosterRequest::create(roster, iqRouter_); + request->onResponse.connect(boost::bind(&RosterController::handleRosterSetError, this, _1, roster)); + request->send(); + + } + else if (std::shared_ptr<RenameRosterItemUIEvent> renameEvent = std::dynamic_pointer_cast<RenameRosterItemUIEvent>(event)) { + JID contact(renameEvent->getJID()); + RosterItemPayload item(contact, renameEvent->getNewName(), xmppRoster_->getSubscriptionStateForJID(contact)); + item.setGroups(xmppRoster_->getGroupsForJID(contact)); + std::shared_ptr<RosterPayload> roster(new RosterPayload()); + roster->addItem(item); + SetRosterRequest::ref request = SetRosterRequest::create(roster, iqRouter_); + request->onResponse.connect(boost::bind(&RosterController::handleRosterSetError, this, _1, roster)); + request->send(); + } + else if (std::shared_ptr<RenameGroupUIEvent> renameGroupEvent = std::dynamic_pointer_cast<RenameGroupUIEvent>(event)) { + std::vector<XMPPRosterItem> items = xmppRoster_->getItems(); + std::string group = renameGroupEvent->getGroup(); + // FIXME: We should handle contacts groups specially to avoid clashes + if (group == QT_TRANSLATE_NOOP("", "Contacts")) { + group = ""; + } + for (auto& item : items) { + std::vector<std::string> groups = item.getGroups(); + if ( (group.empty() && groups.empty()) || std::find(groups.begin(), groups.end(), group) != groups.end()) { + groups.erase(std::remove(groups.begin(), groups.end(), group), groups.end()); + if (std::find(groups.begin(), groups.end(), renameGroupEvent->getNewName()) == groups.end()) { + groups.push_back(renameGroupEvent->getNewName()); + } + item.setGroups(groups); + updateItem(item); + } + } + } } void RosterController::setContactGroups(const JID& jid, const std::vector<std::string>& groups) { - updateItem(XMPPRosterItem(jid, xmppRoster_->getNameForJID(jid), groups, xmppRoster_->getSubscriptionStateForJID(jid))); + updateItem(XMPPRosterItem(jid, xmppRoster_->getNameForJID(jid), groups, xmppRoster_->getSubscriptionStateForJID(jid))); } void RosterController::updateItem(const XMPPRosterItem& item) { - RosterItemPayload itemPayload(item.getJID(), item.getName(), item.getSubscription()); - itemPayload.setGroups(item.getGroups()); + RosterItemPayload itemPayload(item.getJID(), item.getName(), item.getSubscription()); + itemPayload.setGroups(item.getGroups()); - RosterPayload::ref roster = boost::make_shared<RosterPayload>(); - roster->addItem(itemPayload); + RosterPayload::ref roster = std::make_shared<RosterPayload>(); + roster->addItem(itemPayload); - SetRosterRequest::ref request = SetRosterRequest::create(roster, iqRouter_); - request->onResponse.connect(boost::bind(&RosterController::handleRosterItemUpdated, this, _1, roster)); - request->send(); + SetRosterRequest::ref request = SetRosterRequest::create(roster, iqRouter_); + request->onResponse.connect(boost::bind(&RosterController::handleRosterItemUpdated, this, _1, roster)); + request->send(); } void RosterController::initBlockingCommand() { - boost::shared_ptr<BlockList> blockList = clientBlockListManager_->requestBlockList(); - - blockingOnStateChangedConnection_ = blockList->onStateChanged.connect(boost::bind(&RosterController::handleBlockingStateChanged, this)); - blockingOnItemAddedConnection_ = blockList->onItemAdded.connect(boost::bind(&RosterController::handleBlockingItemAdded, this, _1)); - blockingOnItemRemovedConnection_ = blockList->onItemRemoved.connect(boost::bind(&RosterController::handleBlockingItemRemoved, this, _1)); - roster_->setBlockingSupported(true); - if (blockList->getState() == BlockList::Available) { - foreach(const JID& jid, blockList->getItems()) { - roster_->applyOnItems(SetBlockingState(jid, ContactRosterItem::IsBlocked)); - } - } + std::shared_ptr<BlockList> blockList = clientBlockListManager_->requestBlockList(); + + blockingOnStateChangedConnection_ = blockList->onStateChanged.connect(boost::bind(&RosterController::handleBlockingStateChanged, this)); + blockingOnItemAddedConnection_ = blockList->onItemAdded.connect(boost::bind(&RosterController::handleBlockingItemAdded, this, _1)); + blockingOnItemRemovedConnection_ = blockList->onItemRemoved.connect(boost::bind(&RosterController::handleBlockingItemRemoved, this, _1)); + roster_->setBlockingSupported(true); + if (blockList->getState() == BlockList::Available) { + for (const auto& jid : blockList->getItems()) { + roster_->applyOnItems(SetBlockingState(jid, ContactRosterItem::IsBlocked)); + } + } } -void RosterController::handleRosterItemUpdated(ErrorPayload::ref error, boost::shared_ptr<RosterPayload> rosterPayload) { - if (!!error) { - handleRosterSetError(error, rosterPayload); - } - boost::shared_ptr<BlockList> blockList = clientBlockListManager_->getBlockList(); - std::vector<RosterItemPayload> items = rosterPayload->getItems(); - if (blockList->getState() == BlockList::Available && items.size() > 0) { - std::vector<JID> jids = blockList->getItems(); - if (std::find(jids.begin(), jids.end(), items[0].getJID()) != jids.end()) { - roster_->applyOnItems(SetBlockingState(items[0].getJID(), ContactRosterItem::IsBlocked)); - } - } +void RosterController::handleRosterItemUpdated(ErrorPayload::ref error, std::shared_ptr<RosterPayload> rosterPayload) { + if (!!error) { + handleRosterSetError(error, rosterPayload); + } + std::shared_ptr<BlockList> blockList = clientBlockListManager_->getBlockList(); + std::vector<RosterItemPayload> items = rosterPayload->getItems(); + if (blockList->getState() == BlockList::Available && items.size() > 0) { + std::vector<JID> jids = blockList->getItems(); + if (std::find(jids.begin(), jids.end(), items[0].getJID()) != jids.end()) { + roster_->applyOnItems(SetBlockingState(items[0].getJID(), ContactRosterItem::IsBlocked)); + } + } } -void RosterController::handleRosterSetError(ErrorPayload::ref error, boost::shared_ptr<RosterPayload> rosterPayload) { - if (!error) { - return; - } - std::string text = str(format(QT_TRANSLATE_NOOP("", "Server %1% rejected contact list change to item '%2%'")) % myJID_.getDomain() % rosterPayload->getItems()[0].getJID().toString()); - if (!error->getText().empty()) { - text += ": " + error->getText(); - } - boost::shared_ptr<ErrorEvent> errorEvent(new ErrorEvent(JID(myJID_.getDomain()), text)); - eventController_->handleIncomingEvent(errorEvent); +void RosterController::handleRosterSetError(ErrorPayload::ref error, std::shared_ptr<RosterPayload> rosterPayload) { + if (!error) { + return; + } + std::string text = str(format(QT_TRANSLATE_NOOP("", "Server %1% rejected contact list change to item '%2%'")) % myJID_.getDomain() % rosterPayload->getItems()[0].getJID().toString()); + if (!error->getText().empty()) { + text += ": " + error->getText(); + } + std::shared_ptr<ErrorEvent> errorEvent(new ErrorEvent(JID(myJID_.getDomain()), text)); + eventController_->handleIncomingEvent(errorEvent); } void RosterController::handleIncomingPresence(Presence::ref newPresence) { - if (newPresence->getType() == Presence::Error) { - return; - } - Presence::ref accountPresence = presenceOracle_->getAccountPresence(newPresence->getFrom().toBare()); - if (!accountPresence) { - accountPresence = Presence::create(); - accountPresence->setFrom(newPresence->getFrom()); - accountPresence->setType(Presence::Unavailable); - } - roster_->applyOnItems(SetPresence(accountPresence)); + if (newPresence->getType() == Presence::Error) { + return; + } + Presence::ref accountPresence = presenceOracle_->getAccountPresence(newPresence->getFrom().toBare()); + if (!accountPresence) { + accountPresence = Presence::create(); + accountPresence->setFrom(newPresence->getFrom()); + accountPresence->setType(Presence::Unavailable); + } + roster_->applyOnItems(SetPresence(accountPresence)); } void RosterController::handleSubscriptionRequest(const JID& jid, const std::string& message) { - if (xmppRoster_->containsJID(jid) && (xmppRoster_->getSubscriptionStateForJID(jid) == RosterItemPayload::To || xmppRoster_->getSubscriptionStateForJID(jid) == RosterItemPayload::Both)) { - subscriptionManager_->confirmSubscription(jid); - return; - } - SubscriptionRequestEvent* eventPointer = new SubscriptionRequestEvent(jid, message); - eventPointer->onAccept.connect(boost::bind(&RosterController::handleSubscriptionRequestAccepted, this, eventPointer)); - eventPointer->onDecline.connect(boost::bind(&RosterController::handleSubscriptionRequestDeclined, this, eventPointer)); - boost::shared_ptr<StanzaEvent> event(eventPointer); - eventController_->handleIncomingEvent(event); + if (xmppRoster_->containsJID(jid) && (xmppRoster_->getSubscriptionStateForJID(jid) == RosterItemPayload::To || xmppRoster_->getSubscriptionStateForJID(jid) == RosterItemPayload::Both)) { + subscriptionManager_->confirmSubscription(jid); + return; + } + SubscriptionRequestEvent* eventPointer = new SubscriptionRequestEvent(jid, message); + eventPointer->onAccept.connect(boost::bind(&RosterController::handleSubscriptionRequestAccepted, this, eventPointer)); + eventPointer->onDecline.connect(boost::bind(&RosterController::handleSubscriptionRequestDeclined, this, eventPointer)); + std::shared_ptr<StanzaEvent> event(eventPointer); + eventController_->handleIncomingEvent(event); } void RosterController::handleSubscriptionRequestAccepted(SubscriptionRequestEvent* event) { - subscriptionManager_->confirmSubscription(event->getJID()); - if (!xmppRoster_->containsJID(event->getJID()) || xmppRoster_->getSubscriptionStateForJID(event->getJID()) == RosterItemPayload::None || xmppRoster_->getSubscriptionStateForJID(event->getJID()) == RosterItemPayload::From) { - subscriptionManager_->requestSubscription(event->getJID()); - } + subscriptionManager_->confirmSubscription(event->getJID()); + if (!xmppRoster_->containsJID(event->getJID()) || xmppRoster_->getSubscriptionStateForJID(event->getJID()) == RosterItemPayload::None || xmppRoster_->getSubscriptionStateForJID(event->getJID()) == RosterItemPayload::From) { + subscriptionManager_->requestSubscription(event->getJID()); + } } void RosterController::handleSubscriptionRequestDeclined(SubscriptionRequestEvent* event) { - subscriptionManager_->cancelSubscription(event->getJID()); + subscriptionManager_->cancelSubscription(event->getJID()); } void RosterController::handleOwnVCardChanged(VCard::ref vcard) { - ownContact_->setVCard(vcard); - mainWindow_->setMyContactRosterItem(ownContact_); + ownContact_->setVCard(vcard); + mainWindow_->setMyContactRosterItem(ownContact_); } void RosterController::handleAvatarChanged(const JID& jid) { - boost::filesystem::path path = avatarManager_->getAvatarPath(jid); - roster_->applyOnItems(SetAvatar(jid, path)); - if (jid.equals(myJID_, JID::WithoutResource)) { - mainWindow_->setMyAvatarPath(pathToString(path)); - ownContact_->setAvatarPath(pathToString(path)); - mainWindow_->setMyContactRosterItem(ownContact_); - } + boost::filesystem::path path = avatarManager_->getAvatarPath(jid); + roster_->applyOnItems(SetAvatar(jid, path)); + if (jid.equals(myJID_, JID::WithoutResource)) { + mainWindow_->setMyAvatarPath(pathToString(path)); + ownContact_->setAvatarPath(pathToString(path)); + mainWindow_->setMyContactRosterItem(ownContact_); + } } void RosterController::handlePresenceChanged(Presence::ref presence) { - if (presence->getFrom().equals(myJID_, JID::WithResource)) { - ownContact_->applyPresence(presence); - mainWindow_->setMyContactRosterItem(ownContact_); - } - else { - handleIncomingPresence(presence); - } + if (presence->getFrom().equals(myJID_, JID::WithResource)) { + ownContact_->applyPresence(presence); + mainWindow_->setMyContactRosterItem(ownContact_); + } + handleIncomingPresence(presence); } boost::optional<XMPPRosterItem> RosterController::getItem(const JID& jid) const { - return xmppRoster_->getItem(jid); + return xmppRoster_->getItem(jid); } std::set<std::string> RosterController::getGroups() const { - return xmppRoster_->getGroups(); + return xmppRoster_->getGroups(); } void RosterController::handleOnCapsChanged(const JID& jid) { - DiscoInfo::ref info = entityCapsManager_->getCaps(jid); - if (info) { - std::set<ContactRosterItem::Feature> features; - if (FileTransferManager::isSupportedBy(info)) { - features.insert(ContactRosterItem::FileTransferFeature); - } - if (info->hasFeature(DiscoInfo::WhiteboardFeature)) { - features.insert(ContactRosterItem::WhiteboardFeature); - } - roster_->applyOnItems(SetAvailableFeatures(jid, features)); - } + std::set<ContactRosterItem::Feature> features; + if (featureOracle_->isFileTransferSupported(jid.toBare()) == Tristate::Yes || featureOracle_->isFileTransferSupported(jid.toBare()) == Tristate::Maybe) { + features.insert(ContactRosterItem::FileTransferFeature); + } + if (featureOracle_->isWhiteboardSupported(jid.toBare()) == Tristate::Yes) { + features.insert(ContactRosterItem::WhiteboardFeature); + } + roster_->applyOnItems(SetAvailableFeatures(jid, features)); } } diff --git a/Swift/Controllers/Roster/RosterController.h b/Swift/Controllers/Roster/RosterController.h index 545abfc..ca2ecdc 100644 --- a/Swift/Controllers/Roster/RosterController.h +++ b/Swift/Controllers/Roster/RosterController.h @@ -1,18 +1,18 @@ /* - * Copyright (c) 2010-2015 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #pragma once +#include <memory> #include <set> #include <string> -#include <boost/shared_ptr.hpp> +#include <boost/signals2.hpp> #include <Swiften/Avatars/AvatarManager.h> -#include <Swiften/Base/boost_bsignals.h> #include <Swiften/Elements/ErrorPayload.h> #include <Swiften/Elements/Presence.h> #include <Swiften/Elements/RosterPayload.h> @@ -23,104 +23,104 @@ #include <Swift/Controllers/UIEvents/UIEvent.h> namespace Swift { - class AvatarManager; - class ClientBlockListManager; - class EntityCapsProvider; - class EventController; - class FileTransferManager; - class FileTransferOverview; - class IQRouter; - class MainWindow; - class MainWindowFactory; - class NickManager; - class NickResolver; - class OfflineRosterFilter; - class PresenceOracle; - class Roster; - class RosterGroupExpandinessPersister; - class RosterVCardProvider; - class SettingsProvider; - class SubscriptionManager; - class SubscriptionRequestEvent; - class UIEventStream; - class VCardManager; - class XMPPRoster; - class XMPPRosterItem; + class AvatarManager; + class ClientBlockListManager; + class EntityCapsProvider; + class EventController; + class FeatureOracle; + class FileTransferManager; + class IQRouter; + class MainWindow; + class MainWindowFactory; + class NickManager; + class NickResolver; + class OfflineRosterFilter; + class PresenceOracle; + class Roster; + class RosterGroupExpandinessPersister; + class RosterVCardProvider; + class SettingsProvider; + class SubscriptionManager; + class SubscriptionRequestEvent; + class UIEventStream; + class VCardManager; + class XMPPRoster; + class XMPPRosterItem; - class RosterController { - public: - RosterController(const JID& jid, XMPPRoster* xmppRoster, AvatarManager* avatarManager, MainWindowFactory* mainWindowFactory, NickManager* nickManager, NickResolver* nickResolver, PresenceOracle* presenceOracle, SubscriptionManager* subscriptionManager, EventController* eventController, UIEventStream* uiEventStream, IQRouter* iqRouter, SettingsProvider* settings, EntityCapsProvider* entityCapsProvider, FileTransferOverview* fileTransferOverview, ClientBlockListManager* clientBlockListManager, VCardManager* vcardManager); - ~RosterController(); - void showRosterWindow(); - void setJID(const JID& jid) { myJID_ = jid; } - MainWindow* getWindow() {return mainWindow_;} - boost::signal<void (StatusShow::Type, const std::string&)> onChangeStatusRequest; - boost::signal<void ()> onSignOutRequest; - void handleOwnVCardChanged(VCard::ref vcard); - void handleAvatarChanged(const JID& jid); - void handlePresenceChanged(Presence::ref presence); - void setEnabled(bool enabled); + class RosterController { + public: + RosterController(const JID& jid, XMPPRoster* xmppRoster, AvatarManager* avatarManager, MainWindowFactory* mainWindowFactory, NickManager* nickManager, NickResolver* nickResolver, PresenceOracle* presenceOracle, SubscriptionManager* subscriptionManager, EventController* eventController, UIEventStream* uiEventStream, IQRouter* iqRouter, SettingsProvider* settings, EntityCapsProvider* entityCapsProvider, ClientBlockListManager* clientBlockListManager, VCardManager* vcardManager); + ~RosterController(); + void showRosterWindow(); + void setJID(const JID& jid) { myJID_ = jid; } + MainWindow* getWindow() {return mainWindow_;} + boost::signals2::signal<void (StatusShow::Type, const std::string&)> onChangeStatusRequest; + boost::signals2::signal<void ()> onSignOutRequest; + void handleOwnVCardChanged(VCard::ref vcard); + void handleAvatarChanged(const JID& jid); + void handlePresenceChanged(Presence::ref presence); + void setEnabled(bool enabled); - boost::optional<XMPPRosterItem> getItem(const JID&) const; - std::set<std::string> getGroups() const; + boost::optional<XMPPRosterItem> getItem(const JID&) const; + std::set<std::string> getGroups() const; - void setContactGroups(const JID& jid, const std::vector<std::string>& groups); - void updateItem(const XMPPRosterItem&); + void setContactGroups(const JID& jid, const std::vector<std::string>& groups); + void updateItem(const XMPPRosterItem&); - void initBlockingCommand(); + void initBlockingCommand(); - private: - void handleOnJIDAdded(const JID &jid); - void handleRosterCleared(); - void handleOnJIDRemoved(const JID &jid); - void handleOnJIDUpdated(const JID &jid, const std::string& oldName, const std::vector<std::string>& oldGroups); - void handleStartChatRequest(const JID& contact); - void handleChangeStatusRequest(StatusShow::Type show, const std::string &statusText); - void handleShowOfflineToggled(bool state); - void handleIncomingPresence(boost::shared_ptr<Presence> newPresence); - void handleSubscriptionRequest(const JID& jid, const std::string& message); - void handleSubscriptionRequestAccepted(SubscriptionRequestEvent* event); - void handleSubscriptionRequestDeclined(SubscriptionRequestEvent* event); - void handleUIEvent(boost::shared_ptr<UIEvent> event); - void handleRosterItemUpdated(ErrorPayload::ref error, boost::shared_ptr<RosterPayload> rosterPayload); - void handleRosterSetError(ErrorPayload::ref error, boost::shared_ptr<RosterPayload> rosterPayload); - void applyAllPresenceTo(const JID& jid); - void handleEditProfileRequest(); - void handleOnCapsChanged(const JID& jid); - void handleSettingChanged(const std::string& settingPath); + private: + void handleOnJIDAdded(const JID &jid); + void handleRosterCleared(); + void handleOnJIDRemoved(const JID &jid); + void handleOnJIDUpdated(const JID &jid, const std::string& oldName, const std::vector<std::string>& oldGroups); + void handleStartChatRequest(const JID& contact); + void handleChangeStatusRequest(StatusShow::Type show, const std::string &statusText); + void handleShowOfflineToggled(bool state); + void handleIncomingPresence(std::shared_ptr<Presence> newPresence); + void handleSubscriptionRequest(const JID& jid, const std::string& message); + void handleSubscriptionRequestAccepted(SubscriptionRequestEvent* event); + void handleSubscriptionRequestDeclined(SubscriptionRequestEvent* event); + void handleUIEvent(std::shared_ptr<UIEvent> event); + void handleRosterItemUpdated(ErrorPayload::ref error, std::shared_ptr<RosterPayload> rosterPayload); + void handleRosterSetError(ErrorPayload::ref error, std::shared_ptr<RosterPayload> rosterPayload); + void applyAllPresenceTo(const JID& jid); + void handleEditProfileRequest(); + void handleOnCapsChanged(const JID& jid); + void handleSettingChanged(const std::string& settingPath); - void handleBlockingStateChanged(); - void handleBlockingItemAdded(const JID& jid); - void handleBlockingItemRemoved(const JID& jid); + void handleBlockingStateChanged(); + void handleBlockingItemAdded(const JID& jid); + void handleBlockingItemRemoved(const JID& jid); - JID myJID_; - XMPPRoster* xmppRoster_; - MainWindowFactory* mainWindowFactory_; - MainWindow* mainWindow_; - Roster* roster_; - OfflineRosterFilter* offlineFilter_; - VCardManager* vcardManager_; - AvatarManager* avatarManager_; - NickManager* nickManager_; - NickResolver* nickResolver_; - PresenceOracle* presenceOracle_; - SubscriptionManager* subscriptionManager_; - EventController* eventController_; - RosterGroupExpandinessPersister* expandiness_; - IQRouter* iqRouter_; - SettingsProvider* settings_; - UIEventStream* uiEventStream_; - EntityCapsProvider* entityCapsManager_; - FileTransferOverview* ftOverview_; - ClientBlockListManager* clientBlockListManager_; - RosterVCardProvider* rosterVCardProvider_; - boost::shared_ptr<ContactRosterItem> ownContact_; - - boost::bsignals::scoped_connection blockingOnStateChangedConnection_; - boost::bsignals::scoped_connection blockingOnItemAddedConnection_; - boost::bsignals::scoped_connection blockingOnItemRemovedConnection_; - boost::bsignals::scoped_connection changeStatusConnection_; - boost::bsignals::scoped_connection signOutConnection_; - boost::bsignals::scoped_connection uiEventConnection_; - }; + JID myJID_; + XMPPRoster* xmppRoster_; + MainWindowFactory* mainWindowFactory_; + MainWindow* mainWindow_; + Roster* roster_; + OfflineRosterFilter* offlineFilter_; + VCardManager* vcardManager_; + AvatarManager* avatarManager_; + NickManager* nickManager_; + NickResolver* nickResolver_; + PresenceOracle* presenceOracle_; + SubscriptionManager* subscriptionManager_; + EventController* eventController_; + RosterGroupExpandinessPersister* expandiness_; + IQRouter* iqRouter_; + SettingsProvider* settings_; + UIEventStream* uiEventStream_; + EntityCapsProvider* entityCapsManager_; + ClientBlockListManager* clientBlockListManager_; + RosterVCardProvider* rosterVCardProvider_; + std::shared_ptr<ContactRosterItem> ownContact_; + std::unique_ptr<FeatureOracle> featureOracle_; + + boost::signals2::scoped_connection blockingOnStateChangedConnection_; + boost::signals2::scoped_connection blockingOnItemAddedConnection_; + boost::signals2::scoped_connection blockingOnItemRemovedConnection_; + boost::signals2::scoped_connection changeStatusConnection_; + boost::signals2::scoped_connection signOutConnection_; + boost::signals2::scoped_connection uiEventConnection_; + }; } diff --git a/Swift/Controllers/Roster/RosterFilter.h b/Swift/Controllers/Roster/RosterFilter.h index 8712569..6075c66 100644 --- a/Swift/Controllers/Roster/RosterFilter.h +++ b/Swift/Controllers/Roster/RosterFilter.h @@ -1,19 +1,19 @@ /* - * Copyright (c) 2010 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include "Swift/Controllers/Roster/RosterItem.h" +#include <Swift/Controllers/Roster/RosterItem.h> namespace Swift { class RosterFilter { - public: - virtual ~RosterFilter() {} - virtual bool operator() (RosterItem* item) const = 0; + public: + virtual ~RosterFilter() {} + virtual bool operator() (RosterItem* item) const = 0; }; } diff --git a/Swift/Controllers/Roster/RosterGroupExpandinessPersister.cpp b/Swift/Controllers/Roster/RosterGroupExpandinessPersister.cpp index 79ad812..0f07c0b 100644 --- a/Swift/Controllers/Roster/RosterGroupExpandinessPersister.cpp +++ b/Swift/Controllers/Roster/RosterGroupExpandinessPersister.cpp @@ -1,61 +1,62 @@ /* - * Copyright (c) 2010-2012 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #include <Swift/Controllers/Roster/RosterGroupExpandinessPersister.h> -#include <boost/bind.hpp> #include <vector> -#include <Swiften/Base/foreach.h> +#include <boost/bind.hpp> + #include <Swiften/Base/String.h> + #include <Swift/Controllers/Roster/GroupRosterItem.h> #include <Swift/Controllers/SettingConstants.h> namespace Swift { RosterGroupExpandinessPersister::RosterGroupExpandinessPersister(Roster* roster, SettingsProvider* settings) : roster_(roster), settings_(settings) { - load(); - roster_->onGroupAdded.connect(boost::bind(&RosterGroupExpandinessPersister::handleGroupAdded, this, _1)); + load(); + roster_->onGroupAdded.connect(boost::bind(&RosterGroupExpandinessPersister::handleGroupAdded, this, _1)); } void RosterGroupExpandinessPersister::handleGroupAdded(GroupRosterItem* group) { - if (collapsed_.find(group->getDisplayName()) != collapsed_.end()) { - group->setExpanded(false); - } else { - group->setExpanded(true); - } - group->onExpandedChanged.connect(boost::bind(&RosterGroupExpandinessPersister::handleExpandedChanged, this, group, _1)); + if (collapsed_.find(group->getDisplayName()) != collapsed_.end()) { + group->setExpanded(false); + } else { + group->setExpanded(true); + } + group->onExpandedChanged.connect(boost::bind(&RosterGroupExpandinessPersister::handleExpandedChanged, this, group, _1)); } void RosterGroupExpandinessPersister::handleExpandedChanged(GroupRosterItem* group, bool expanded) { - if (expanded) { - std::string displayName = group->getDisplayName(); - //collapsed_.erase(std::remove(collapsed_.begin(), collapsed_.end(), displayName), collapsed_.end()); - collapsed_.erase(displayName); - } else { - collapsed_.insert(group->getDisplayName()); - } - save(); + if (expanded) { + std::string displayName = group->getDisplayName(); + //collapsed_.erase(std::remove(collapsed_.begin(), collapsed_.end(), displayName), collapsed_.end()); + collapsed_.erase(displayName); + } else { + collapsed_.insert(group->getDisplayName()); + } + save(); } void RosterGroupExpandinessPersister::save() { - std::string setting; - foreach (const std::string& group, collapsed_) { - if (!setting.empty()) { - setting += "\n"; - } - setting += group; - } - settings_->storeSetting(SettingConstants::EXPANDED_ROSTER_GROUPS, setting); + std::string setting; + for (const auto& group : collapsed_) { + if (!setting.empty()) { + setting += "\n"; + } + setting += group; + } + settings_->storeSetting(SettingConstants::EXPANDED_ROSTER_GROUPS, setting); } void RosterGroupExpandinessPersister::load() { - std::string saved = settings_->getSetting(SettingConstants::EXPANDED_ROSTER_GROUPS); - std::vector<std::string> collapsed = String::split(saved, '\n'); - collapsed_.insert(collapsed.begin(), collapsed.end()); + std::string saved = settings_->getSetting(SettingConstants::EXPANDED_ROSTER_GROUPS); + std::vector<std::string> collapsed = String::split(saved, '\n'); + collapsed_.insert(collapsed.begin(), collapsed.end()); } diff --git a/Swift/Controllers/Roster/RosterGroupExpandinessPersister.h b/Swift/Controllers/Roster/RosterGroupExpandinessPersister.h index 6addc81..4cc08a7 100644 --- a/Swift/Controllers/Roster/RosterGroupExpandinessPersister.h +++ b/Swift/Controllers/Roster/RosterGroupExpandinessPersister.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2012 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -7,20 +7,21 @@ #pragma once #include <set> -#include "Swift/Controllers/Roster/Roster.h" -#include "Swift/Controllers/Settings/SettingsProvider.h" + +#include <Swift/Controllers/Roster/Roster.h> +#include <Swift/Controllers/Settings/SettingsProvider.h> namespace Swift { - class RosterGroupExpandinessPersister { - public: - RosterGroupExpandinessPersister(Roster* roster, SettingsProvider* settings); - private: - void handleExpandedChanged(GroupRosterItem* group, bool expanded); - void handleGroupAdded(GroupRosterItem* group); - void load(); - void save(); - std::set<std::string> collapsed_; - Roster* roster_; - SettingsProvider* settings_; - }; + class RosterGroupExpandinessPersister { + public: + RosterGroupExpandinessPersister(Roster* roster, SettingsProvider* settings); + private: + void handleExpandedChanged(GroupRosterItem* group, bool expanded); + void handleGroupAdded(GroupRosterItem* group); + void load(); + void save(); + std::set<std::string> collapsed_; + Roster* roster_; + SettingsProvider* settings_; + }; } diff --git a/Swift/Controllers/Roster/RosterItem.cpp b/Swift/Controllers/Roster/RosterItem.cpp index 7864fd9..685613f 100644 --- a/Swift/Controllers/Roster/RosterItem.cpp +++ b/Swift/Controllers/Roster/RosterItem.cpp @@ -1,22 +1,22 @@ /* - * Copyright (c) 2010 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ -#include "Swift/Controllers/Roster/RosterItem.h" +#include <Swift/Controllers/Roster/RosterItem.h> #include <boost/algorithm/string.hpp> -#include "Swift/Controllers/Roster/GroupRosterItem.h" +#include <Swift/Controllers/Roster/GroupRosterItem.h> namespace Swift { RosterItem::RosterItem(const std::string& name, GroupRosterItem* parent) : name_(name), sortableDisplayName_(boost::to_lower_copy(name_)), parent_(parent) { - /* The following would be good, but because of C++'s inheritance not working in constructors, it's not going to work. */ - //if (parent) { - // parent_->addChild(this); - //} + /* The following would be good, but because of C++'s inheritance not working in constructors, it's not going to work. */ + //if (parent) { + // parent_->addChild(this); + //} } RosterItem::~RosterItem() { @@ -24,21 +24,21 @@ RosterItem::~RosterItem() { } GroupRosterItem* RosterItem::getParent() const { - return parent_; + return parent_; } void RosterItem::setDisplayName(const std::string& name) { - name_ = name; - sortableDisplayName_ = boost::to_lower_copy(name_); - onDataChanged(); + name_ = name; + sortableDisplayName_ = boost::to_lower_copy(name_); + onDataChanged(); } const std::string& RosterItem::getDisplayName() const { - return name_; + return name_; } const std::string& RosterItem::getSortableDisplayName() const { - return sortableDisplayName_; + return sortableDisplayName_; } diff --git a/Swift/Controllers/Roster/RosterItem.h b/Swift/Controllers/Roster/RosterItem.h index 84cba2c..b834785 100644 --- a/Swift/Controllers/Roster/RosterItem.h +++ b/Swift/Controllers/Roster/RosterItem.h @@ -1,31 +1,31 @@ /* - * Copyright (c) 2010 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include "Swiften/Base/boost_bsignals.h" -#include <boost/shared_ptr.hpp> - +#include <memory> #include <string> +#include <boost/signals2.hpp> + namespace Swift { class GroupRosterItem; class RosterItem { - public: - RosterItem(const std::string& name, GroupRosterItem* parent); - virtual ~RosterItem(); - boost::signal<void ()> onDataChanged; - GroupRosterItem* getParent() const; - void setDisplayName(const std::string& name); - const std::string& getDisplayName() const; - virtual const std::string& getSortableDisplayName() const; - private: - std::string name_; - std::string sortableDisplayName_; - GroupRosterItem* parent_; + public: + RosterItem(const std::string& name, GroupRosterItem* parent); + virtual ~RosterItem(); + boost::signals2::signal<void ()> onDataChanged; + GroupRosterItem* getParent() const; + void setDisplayName(const std::string& name); + const std::string& getDisplayName() const; + virtual const std::string& getSortableDisplayName() const; + private: + std::string name_; + std::string sortableDisplayName_; + GroupRosterItem* parent_; }; } diff --git a/Swift/Controllers/Roster/RosterVCardProvider.cpp b/Swift/Controllers/Roster/RosterVCardProvider.cpp index 954ac68..2aa82a9 100644 --- a/Swift/Controllers/Roster/RosterVCardProvider.cpp +++ b/Swift/Controllers/Roster/RosterVCardProvider.cpp @@ -4,32 +4,38 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #include <Swift/Controllers/Roster/RosterVCardProvider.h> #include <Swiften/VCards/VCardManager.h> -#include <Swift/Controllers/Roster/Roster.h> #include <Swift/Controllers/Roster/ItemOperations/SetVCard.h> +#include <Swift/Controllers/Roster/Roster.h> namespace Swift { RosterVCardProvider::RosterVCardProvider(Roster* roster, VCardManager* vcardManager, JID::CompareType compareType) : roster_(roster), vcardManager_(vcardManager), compareType_(compareType) { - vcardUpdateRequestedConnection = roster_->onVCardUpdateRequested.connect(boost::bind(&RosterVCardProvider::handleVCardUpdateRequested, this, _1)); - vcardChangedConnection = vcardManager_->onVCardChanged.connect(boost::bind(&RosterVCardProvider::handleVCardChanged, this, _1, _2)); + vcardUpdateRequestedConnection = roster_->onVCardUpdateRequested.connect(boost::bind(&RosterVCardProvider::handleVCardUpdateRequested, this, _1)); + vcardChangedConnection = vcardManager_->onVCardChanged.connect(boost::bind(&RosterVCardProvider::handleVCardChanged, this, _1, _2)); } RosterVCardProvider::~RosterVCardProvider() { } void RosterVCardProvider::handleVCardUpdateRequested(const JID& jid) { - VCard::ref vcard = vcardManager_->getVCardAndRequestWhenNeeded(jid); - if (vcard) { - handleVCardChanged(jid, vcard); - } + VCard::ref vcard = vcardManager_->getVCardAndRequestWhenNeeded(jid); + if (vcard) { + handleVCardChanged(jid, vcard); + } } void RosterVCardProvider::handleVCardChanged(const JID& jid, VCard::ref vcard) { - roster_->applyOnItem(SetVCard(jid, vcard, compareType_), jid); + roster_->applyOnItem(SetVCard(jid, vcard, compareType_), jid); } diff --git a/Swift/Controllers/Roster/RosterVCardProvider.h b/Swift/Controllers/Roster/RosterVCardProvider.h index da41298..337b0b2 100644 --- a/Swift/Controllers/Roster/RosterVCardProvider.h +++ b/Swift/Controllers/Roster/RosterVCardProvider.h @@ -4,11 +4,17 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once -#include <boost/signals/connection.hpp> +#include <boost/signals2.hpp> +#include <boost/signals2/connection.hpp> -#include <Swiften/Base/boost_bsignals.h> #include <Swiften/Elements/VCard.h> #include <Swiften/JID/JID.h> @@ -18,20 +24,20 @@ class Roster; class VCardManager; class RosterVCardProvider { - public: - RosterVCardProvider(Roster* roster, VCardManager* vcardManager, JID::CompareType compareType); - ~RosterVCardProvider(); - - private: - void handleVCardUpdateRequested(const JID& jid); - void handleVCardChanged(const JID& jid, VCard::ref vcard); - - private: - Roster* roster_; - VCardManager* vcardManager_; - JID::CompareType compareType_; - boost::bsignals::scoped_connection vcardUpdateRequestedConnection; - boost::bsignals::scoped_connection vcardChangedConnection; + public: + RosterVCardProvider(Roster* roster, VCardManager* vcardManager, JID::CompareType compareType); + ~RosterVCardProvider(); + + private: + void handleVCardUpdateRequested(const JID& jid); + void handleVCardChanged(const JID& jid, VCard::ref vcard); + + private: + Roster* roster_; + VCardManager* vcardManager_; + JID::CompareType compareType_; + boost::signals2::scoped_connection vcardUpdateRequestedConnection; + boost::signals2::scoped_connection vcardChangedConnection; }; } diff --git a/Swift/Controllers/Roster/TableRoster.cpp b/Swift/Controllers/Roster/TableRoster.cpp index 9f3cd54..713f390 100644 --- a/Swift/Controllers/Roster/TableRoster.cpp +++ b/Swift/Controllers/Roster/TableRoster.cpp @@ -1,185 +1,186 @@ /* - * Copyright (c) 2011 Isode Limited. + * Copyright (c) 2011-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #include <Swift/Controllers/Roster/TableRoster.h> -#include <boost/cast.hpp> -#include <cassert> #include <algorithm> +#include <cassert> + +#include <boost/cast.hpp> #include <boost/numeric/conversion/cast.hpp> -#include <Swiften/Base/foreach.h> -#include <Swiften/Network/TimerFactory.h> #include <Swiften/Network/Timer.h> -#include <Swift/Controllers/Roster/Roster.h> +#include <Swiften/Network/TimerFactory.h> + #include <Swift/Controllers/Roster/GroupRosterItem.h> #include <Swift/Controllers/Roster/LeastCommonSubsequence.h> +#include <Swift/Controllers/Roster/Roster.h> namespace Swift { - struct SectionNameEquals { - bool operator()(const TableRoster::Section& s1, const TableRoster::Section& s2) const { - return s1.name == s2.name; - } - }; - - template<typename T> - struct True { - bool operator()(const T&, const T&) const { - return true; - } - }; - - struct ItemEquals { - bool operator()(const TableRoster::Item& i1, const TableRoster::Item& i2) const { - return i1.jid == i2.jid; - } - }; - - - struct ItemNeedsUpdate { - bool operator()(const TableRoster::Item& i1, const TableRoster::Item& i2) const { - return i1.status != i2.status || i1.description != i2.description || i1.name != i2.name || i1.avatarPath.empty() != i2.avatarPath.empty(); - } - }; - - struct CreateIndexForSection { - CreateIndexForSection(size_t section) : section(section) { - } - - TableRoster::Index operator()(size_t row) const { - return TableRoster::Index(section, row); - } - - size_t section; - }; + struct SectionNameEquals { + bool operator()(const TableRoster::Section& s1, const TableRoster::Section& s2) const { + return s1.name == s2.name; + } + }; + + template<typename T> + struct True { + bool operator()(const T&, const T&) const { + return true; + } + }; + + struct ItemEquals { + bool operator()(const TableRoster::Item& i1, const TableRoster::Item& i2) const { + return i1.jid == i2.jid; + } + }; + + + struct ItemNeedsUpdate { + bool operator()(const TableRoster::Item& i1, const TableRoster::Item& i2) const { + return i1.status != i2.status || i1.description != i2.description || i1.name != i2.name || i1.avatarPath.empty() != i2.avatarPath.empty(); + } + }; + + struct CreateIndexForSection { + CreateIndexForSection(size_t section) : section(section) { + } + + TableRoster::Index operator()(size_t row) const { + return TableRoster::Index(section, row); + } + + size_t section; + }; } using namespace Swift; TableRoster::TableRoster(Roster* model, TimerFactory* timerFactory, int updateDelay) : model(model), updatePending(false) { - updateTimer = timerFactory->createTimer(updateDelay); - updateTimer->onTick.connect(boost::bind(&TableRoster::handleUpdateTimerTick, this)); - if (model) { - model->onChildrenChanged.connect(boost::bind(&TableRoster::scheduleUpdate, this)); - model->onGroupAdded.connect(boost::bind(&TableRoster::scheduleUpdate, this)); - model->onDataChanged.connect(boost::bind(&TableRoster::scheduleUpdate, this)); - } + updateTimer = timerFactory->createTimer(updateDelay); + updateTimer->onTick.connect(boost::bind(&TableRoster::handleUpdateTimerTick, this)); + if (model) { + model->onChildrenChanged.connect(boost::bind(&TableRoster::scheduleUpdate, this)); + model->onGroupAdded.connect(boost::bind(&TableRoster::scheduleUpdate, this)); + model->onDataChanged.connect(boost::bind(&TableRoster::scheduleUpdate, this)); + } } TableRoster::~TableRoster() { - updateTimer->stop(); - updateTimer->onTick.disconnect(boost::bind(&TableRoster::handleUpdateTimerTick, this)); - if (model) { - model->onDataChanged.disconnect(boost::bind(&TableRoster::scheduleUpdate, this)); - model->onGroupAdded.disconnect(boost::bind(&TableRoster::scheduleUpdate, this)); - model->onChildrenChanged.disconnect(boost::bind(&TableRoster::scheduleUpdate, this)); - } + updateTimer->stop(); + updateTimer->onTick.disconnect(boost::bind(&TableRoster::handleUpdateTimerTick, this)); + if (model) { + model->onDataChanged.disconnect(boost::bind(&TableRoster::scheduleUpdate, this)); + model->onGroupAdded.disconnect(boost::bind(&TableRoster::scheduleUpdate, this)); + model->onChildrenChanged.disconnect(boost::bind(&TableRoster::scheduleUpdate, this)); + } } - + size_t TableRoster::getNumberOfSections() const { - return sections.size(); + return sections.size(); } const std::string& TableRoster::getSectionTitle(size_t section) { - return sections[section].name; + return sections[section].name; } size_t TableRoster::getNumberOfRowsInSection(size_t section) const { - return sections[section].items.size(); + return sections[section].items.size(); } const TableRoster::Item& TableRoster::getItem(const Index& index) const { - return sections[index.section].items[index.row]; + return sections[index.section].items[index.row]; } - + void TableRoster::handleUpdateTimerTick() { - updateTimer->stop(); - updatePending = false; - - // Get a model for the new roster - std::vector<Section> newSections; - if (model) { - foreach(RosterItem* item, model->getRoot()->getDisplayedChildren()) { - if (GroupRosterItem* groupItem = boost::polymorphic_downcast<GroupRosterItem*>(item)) { - //std::cerr << "* " << groupItem->getDisplayName() << std::endl; - Section section(groupItem->getDisplayName()); - foreach(RosterItem* groupChildItem, groupItem->getDisplayedChildren()) { - if (ContactRosterItem* contact = boost::polymorphic_downcast<ContactRosterItem*>(groupChildItem)) { - //std::cerr << " - " << contact->getDisplayJID() << std::endl; - section.items.push_back(Item(contact->getDisplayName(), contact->getStatusText(), contact->getDisplayJID(), contact->getStatusShow(), contact->getAvatarPath())); - } - } - newSections.push_back(section); - } - } - } - - // Do a diff with the previous roster - Update update; - std::vector<size_t> sectionUpdates; - std::vector<size_t> sectionPostUpdates; - computeIndexDiff<Section,SectionNameEquals,True<Section> >(sections, newSections, sectionUpdates, sectionPostUpdates, update.deletedSections, update.insertedSections); - assert(sectionUpdates.size() == sectionPostUpdates.size()); - for (size_t i = 0; i < sectionUpdates.size(); ++i) { - assert(sectionUpdates[i] < sections.size()); - assert(sectionPostUpdates[i] < newSections.size()); - std::vector<size_t> itemUpdates; - std::vector<size_t> itemPostUpdates; - std::vector<size_t> itemRemoves; - std::vector<size_t> itemInserts; - computeIndexDiff<Item, ItemEquals, ItemNeedsUpdate >(sections[sectionUpdates[i]].items, newSections[sectionPostUpdates[i]].items, itemUpdates, itemPostUpdates, itemRemoves, itemInserts); - size_t end = update.insertedRows.size(); - update.insertedRows.resize(update.insertedRows.size() + itemInserts.size()); - std::transform(itemInserts.begin(), itemInserts.end(), update.insertedRows.begin() + boost::numeric_cast<long long>(end), CreateIndexForSection(sectionPostUpdates[i])); - end = update.deletedRows.size(); - update.deletedRows.resize(update.deletedRows.size() + itemRemoves.size()); - std::transform(itemRemoves.begin(), itemRemoves.end(), update.deletedRows.begin() + boost::numeric_cast<long long>(end), CreateIndexForSection(sectionUpdates[i])); - end = update.updatedRows.size(); - update.updatedRows.resize(update.updatedRows.size() + itemUpdates.size()); - std::transform(itemUpdates.begin(), itemUpdates.end(), update.updatedRows.begin() + boost::numeric_cast<long long>(end), CreateIndexForSection(sectionPostUpdates[i])); - } - - // Switch the old model with the new - sections.swap(newSections); - - /* - std::cerr << "-S: "; - for (size_t i = 0; i < update.deletedSections.size(); ++i) { - std::cerr << update.deletedSections[i] << " "; - } - std::cerr << std::endl; - std::cerr << "+S: "; - for (size_t i = 0; i < update.insertedSections.size(); ++i) { - std::cerr << update.insertedSections[i] << " "; - } - std::cerr << std::endl; - std::cerr << "-R: "; - for (size_t i = 0; i < update.deletedRows.size(); ++i) { - std::cerr << update.deletedRows[i].section << "," << update.deletedRows[i].row << " "; - } - std::cerr << std::endl; - std::cerr << "*R: "; - for (size_t i = 0; i < update.updatedRows.size(); ++i) { - std::cerr << update.updatedRows[i].section << "," << update.updatedRows[i].row << " "; - } - std::cerr << std::endl; - std::cerr << "+R: "; - for (size_t i = 0; i < update.insertedRows.size(); ++i) { - std::cerr << update.insertedRows[i].section << "," << update.insertedRows[i].row << " "; - } - std::cerr << std::endl; - */ - - // Emit the update - onUpdate(update); + updateTimer->stop(); + updatePending = false; + + // Get a model for the new roster + std::vector<Section> newSections; + if (model) { + for (auto item : model->getRoot()->getDisplayedChildren()) { + if (GroupRosterItem* groupItem = boost::polymorphic_downcast<GroupRosterItem*>(item)) { + //std::cerr << "* " << groupItem->getDisplayName() << std::endl; + Section section(groupItem->getDisplayName()); + for (auto groupChildItem : groupItem->getDisplayedChildren()) { + if (ContactRosterItem* contact = boost::polymorphic_downcast<ContactRosterItem*>(groupChildItem)) { + //std::cerr << " - " << contact->getDisplayJID() << std::endl; + section.items.push_back(Item(contact->getDisplayName(), contact->getStatusText(), contact->getDisplayJID(), contact->getStatusShow(), contact->getAvatarPath())); + } + } + newSections.push_back(section); + } + } + } + + // Do a diff with the previous roster + Update update; + std::vector<size_t> sectionUpdates; + std::vector<size_t> sectionPostUpdates; + computeIndexDiff<Section,SectionNameEquals,True<Section> >(sections, newSections, sectionUpdates, sectionPostUpdates, update.deletedSections, update.insertedSections); + assert(sectionUpdates.size() == sectionPostUpdates.size()); + for (size_t i = 0; i < sectionUpdates.size(); ++i) { + assert(sectionUpdates[i] < sections.size()); + assert(sectionPostUpdates[i] < newSections.size()); + std::vector<size_t> itemUpdates; + std::vector<size_t> itemPostUpdates; + std::vector<size_t> itemRemoves; + std::vector<size_t> itemInserts; + computeIndexDiff<Item, ItemEquals, ItemNeedsUpdate >(sections[sectionUpdates[i]].items, newSections[sectionPostUpdates[i]].items, itemUpdates, itemPostUpdates, itemRemoves, itemInserts); + size_t end = update.insertedRows.size(); + update.insertedRows.resize(update.insertedRows.size() + itemInserts.size()); + std::transform(itemInserts.begin(), itemInserts.end(), update.insertedRows.begin() + boost::numeric_cast<long long>(end), CreateIndexForSection(sectionPostUpdates[i])); + end = update.deletedRows.size(); + update.deletedRows.resize(update.deletedRows.size() + itemRemoves.size()); + std::transform(itemRemoves.begin(), itemRemoves.end(), update.deletedRows.begin() + boost::numeric_cast<long long>(end), CreateIndexForSection(sectionUpdates[i])); + end = update.updatedRows.size(); + update.updatedRows.resize(update.updatedRows.size() + itemUpdates.size()); + std::transform(itemUpdates.begin(), itemUpdates.end(), update.updatedRows.begin() + boost::numeric_cast<long long>(end), CreateIndexForSection(sectionPostUpdates[i])); + } + + // Switch the old model with the new + sections.swap(newSections); + + /* + std::cerr << "-S: "; + for (size_t i = 0; i < update.deletedSections.size(); ++i) { + std::cerr << update.deletedSections[i] << " "; + } + std::cerr << std::endl; + std::cerr << "+S: "; + for (size_t i = 0; i < update.insertedSections.size(); ++i) { + std::cerr << update.insertedSections[i] << " "; + } + std::cerr << std::endl; + std::cerr << "-R: "; + for (size_t i = 0; i < update.deletedRows.size(); ++i) { + std::cerr << update.deletedRows[i].section << "," << update.deletedRows[i].row << " "; + } + std::cerr << std::endl; + std::cerr << "*R: "; + for (size_t i = 0; i < update.updatedRows.size(); ++i) { + std::cerr << update.updatedRows[i].section << "," << update.updatedRows[i].row << " "; + } + std::cerr << std::endl; + std::cerr << "+R: "; + for (size_t i = 0; i < update.insertedRows.size(); ++i) { + std::cerr << update.insertedRows[i].section << "," << update.insertedRows[i].row << " "; + } + std::cerr << std::endl; + */ + + // Emit the update + onUpdate(update); } void TableRoster::scheduleUpdate() { - if (!updatePending) { - updatePending = true; - updateTimer->start(); - } + if (!updatePending) { + updatePending = true; + updateTimer->start(); + } } diff --git a/Swift/Controllers/Roster/TableRoster.h b/Swift/Controllers/Roster/TableRoster.h index f0010f5..22c9ca9 100644 --- a/Swift/Controllers/Roster/TableRoster.h +++ b/Swift/Controllers/Roster/TableRoster.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 Isode Limited. + * Copyright (c) 2011-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -8,77 +8,78 @@ #include <string> #include <vector> -#include <Swiften/Base/boost_bsignals.h> -#include <Swiften/JID/JID.h> -#include <Swiften/Elements/StatusShow.h> #include <boost/filesystem/path.hpp> +#include <boost/signals2.hpp> + +#include <Swiften/Elements/StatusShow.h> +#include <Swiften/JID/JID.h> namespace Swift { - class Roster; - class TimerFactory; - class Timer; - - class TableRoster { - public: - struct Item { - Item(const std::string& name, const std::string& description, const JID& jid, StatusShow::Type status, const boost::filesystem::path& avatarPath) : name(name), description(description), jid(jid), status(status), avatarPath(avatarPath) { - } - std::string name; - std::string description; - JID jid; - StatusShow::Type status; - boost::filesystem::path avatarPath; - }; - - struct Index { - Index(size_t section = 0, size_t row = 0) : section(section), row(row) { - } - size_t section; - size_t row; - - bool operator==(const Index& o) const { - return o.section == section && o.row == row; - } - }; - - struct Update { - std::vector<Index> updatedRows; - std::vector<Index> insertedRows; - std::vector<Index> deletedRows; - std::vector<size_t> insertedSections; - std::vector<size_t> deletedSections; - }; - - TableRoster(Roster* model, TimerFactory* timerFactory, int updateDelay); - ~TableRoster(); - - size_t getNumberOfSections() const; - size_t getNumberOfRowsInSection(size_t section) const; - - const std::string& getSectionTitle(size_t); - - const Item& getItem(const Index&) const; - - boost::signal<void (const Update&)> onUpdate; - - private: - void handleUpdateTimerTick(); - void scheduleUpdate(); - - private: - friend struct SectionNameEquals; - struct Section { - Section(const std::string& name) : name(name) { - } - - std::string name; - std::vector<Item> items; - }; - - Roster* model; - std::vector<Section> sections; - bool updatePending; - boost::shared_ptr<Timer> updateTimer; - }; + class Roster; + class TimerFactory; + class Timer; + + class TableRoster { + public: + struct Item { + Item(const std::string& name, const std::string& description, const JID& jid, StatusShow::Type status, const boost::filesystem::path& avatarPath) : name(name), description(description), jid(jid), status(status), avatarPath(avatarPath) { + } + std::string name; + std::string description; + JID jid; + StatusShow::Type status; + boost::filesystem::path avatarPath; + }; + + struct Index { + Index(size_t section = 0, size_t row = 0) : section(section), row(row) { + } + size_t section; + size_t row; + + bool operator==(const Index& o) const { + return o.section == section && o.row == row; + } + }; + + struct Update { + std::vector<Index> updatedRows; + std::vector<Index> insertedRows; + std::vector<Index> deletedRows; + std::vector<size_t> insertedSections; + std::vector<size_t> deletedSections; + }; + + TableRoster(Roster* model, TimerFactory* timerFactory, int updateDelay); + ~TableRoster(); + + size_t getNumberOfSections() const; + size_t getNumberOfRowsInSection(size_t section) const; + + const std::string& getSectionTitle(size_t); + + const Item& getItem(const Index&) const; + + boost::signals2::signal<void (const Update&)> onUpdate; + + private: + void handleUpdateTimerTick(); + void scheduleUpdate(); + + private: + friend struct SectionNameEquals; + struct Section { + Section(const std::string& name) : name(name) { + } + + std::string name; + std::vector<Item> items; + }; + + Roster* model; + std::vector<Section> sections; + bool updatePending; + std::shared_ptr<Timer> updateTimer; + }; } diff --git a/Swift/Controllers/Roster/UnitTest/LeastCommonSubsequenceTest.cpp b/Swift/Controllers/Roster/UnitTest/LeastCommonSubsequenceTest.cpp index 996b460..5844ebe 100644 --- a/Swift/Controllers/Roster/UnitTest/LeastCommonSubsequenceTest.cpp +++ b/Swift/Controllers/Roster/UnitTest/LeastCommonSubsequenceTest.cpp @@ -1,308 +1,311 @@ /* - * Copyright (c) 2011 Isode Limited. + * Copyright (c) 2011-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ -#include <boost/assign/list_of.hpp> #include <functional> +#include <boost/assign/list_of.hpp> + #include <QA/Checker/IO.h> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> + #include <Swift/Controllers/Roster/LeastCommonSubsequence.h> using namespace Swift; struct IsBOrC { - bool operator()(char c, char c2) const { - CPPUNIT_ASSERT_EQUAL(c, c2); - return c == 'b' || c == 'c'; - } + bool operator()(char c, char c2) const { + CPPUNIT_ASSERT_EQUAL(c, c2); + return c == 'b' || c == 'c'; + } }; struct IsXOrY { - bool operator()(char c, char c2) const { - CPPUNIT_ASSERT_EQUAL(c, c2); - return c == 'x' || c == 'y'; - } + bool operator()(char c, char c2) const { + CPPUNIT_ASSERT_EQUAL(c, c2); + return c == 'x' || c == 'y'; + } }; struct IsArizonaOrNewJersey { - bool operator()(const std::string& s, const std::string& s2) const { - CPPUNIT_ASSERT_EQUAL(s, s2); - return s == "Arizona" || s == "New Jersey"; - } + bool operator()(const std::string& s, const std::string& s2) const { + CPPUNIT_ASSERT_EQUAL(s, s2); + return s == "Arizona" || s == "New Jersey"; + } }; class LeastCommonSubsequenceTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(LeastCommonSubsequenceTest); - CPPUNIT_TEST(testComputeLeastCommonSubsequenceMatrix_1); - CPPUNIT_TEST(testComputeLeastCommonSubsequenceMatrix_2); - CPPUNIT_TEST(testComputeLeastCommonSubsequenceMatrix_Sequence1Empty); - CPPUNIT_TEST(testComputeLeastCommonSubsequenceMatrix_Sequence2Empty); - CPPUNIT_TEST(testComputeLeastCommonSubsequenceMatrix_BothSequencesEmpty); - CPPUNIT_TEST(testComputeLeastCommonSubsequenceMatrix_NoCommonSequence); - CPPUNIT_TEST(testComputeLeastCommonSubsequenceMatrix_SameSequences); - CPPUNIT_TEST(testComputeIndexDiff_1); - CPPUNIT_TEST(testComputeIndexDiff_2); - CPPUNIT_TEST(testComputeIndexDiff_Sequence1Empty); - CPPUNIT_TEST(testComputeIndexDiff_Sequence2Empty); - CPPUNIT_TEST(testComputeIndexDiff_BothSequencesEmpty); - CPPUNIT_TEST(testComputeIndexDiff_NoCommonSequence); - CPPUNIT_TEST(testComputeIndexDiff_SameSequences); - CPPUNIT_TEST(testComputeIndexDiff_CommonPrefixAndSuffix); - CPPUNIT_TEST_SUITE_END(); - - public: - void testComputeLeastCommonSubsequenceMatrix_1() { - std::vector<char> x = boost::assign::list_of('x')('m')('j')('y')('a')('u')('z'); - std::vector<char> y = boost::assign::list_of('m')('z')('j')('a')('w')('x')('u'); - - std::vector<int> result; - Detail::computeLeastCommonSubsequenceMatrix<std::vector<char>::const_iterator, std::vector<char>::const_iterator, int, std::equal_to<char> >(x.begin(), x.end(), y.begin(), y.end(), result); - - std::vector<int> expected = boost::assign::list_of - (0)(0)(0)(0)(0)(0)(0)(0) - (0)(0)(1)(1)(1)(1)(1)(1) - (0)(0)(1)(1)(1)(1)(1)(2) - (0)(0)(1)(2)(2)(2)(2)(2) - (0)(0)(1)(2)(2)(3)(3)(3) - (0)(0)(1)(2)(2)(3)(3)(3) - (0)(1)(1)(2)(2)(3)(3)(3) - (0)(1)(1)(2)(2)(3)(4)(4); - CPPUNIT_ASSERT_EQUAL(expected, result); - } - - void testComputeLeastCommonSubsequenceMatrix_2() { - std::vector<char> x = boost::assign::list_of('x')('x')('x')('m')('j')('y')('a')('u')('z'); - std::vector<char> y = boost::assign::list_of('m')('z')('j')('a')('w')('x')('u'); - - std::vector<int> result; - Detail::computeLeastCommonSubsequenceMatrix<std::vector<char>::const_iterator, std::vector<char>::const_iterator, int, std::equal_to<char> >(x.begin(), x.end(), y.begin(), y.end(), result); - - std::vector<int> expected = boost::assign::list_of - (0)(0)(0)(0)(0)(0)(0)(0)(0)(0) - (0)(0)(0)(0)(1)(1)(1)(1)(1)(1) - (0)(0)(0)(0)(1)(1)(1)(1)(1)(2) - (0)(0)(0)(0)(1)(2)(2)(2)(2)(2) - (0)(0)(0)(0)(1)(2)(2)(3)(3)(3) - (0)(0)(0)(0)(1)(2)(2)(3)(3)(3) - (0)(1)(1)(1)(1)(2)(2)(3)(3)(3) - (0)(1)(1)(1)(1)(2)(2)(3)(4)(4); - CPPUNIT_ASSERT_EQUAL(expected, result); - } - - void testComputeLeastCommonSubsequenceMatrix_Sequence1Empty() { - std::vector<char> x; - std::vector<char> y = boost::assign::list_of('a')('b')('c'); - - std::vector<int> result; - Detail::computeLeastCommonSubsequenceMatrix<std::vector<char>::const_iterator, std::vector<char>::const_iterator, int, std::equal_to<char> >(x.begin(), x.end(), y.begin(), y.end(), result); - - std::vector<int> expected = boost::assign::list_of - (0) - (0) - (0) - (0); - CPPUNIT_ASSERT_EQUAL(expected, result); - } - - void testComputeLeastCommonSubsequenceMatrix_Sequence2Empty() { - std::vector<char> x = boost::assign::list_of('a')('b')('c'); - std::vector<char> y; - - std::vector<int> result; - Detail::computeLeastCommonSubsequenceMatrix<std::vector<char>::const_iterator, std::vector<char>::const_iterator, int, std::equal_to<char> >(x.begin(), x.end(), y.begin(), y.end(), result); - - std::vector<int> expected = boost::assign::list_of - (0)(0)(0)(0); - CPPUNIT_ASSERT_EQUAL(expected, result); - } - - void testComputeLeastCommonSubsequenceMatrix_BothSequencesEmpty() { - std::vector<char> x; - std::vector<char> y; - - std::vector<int> result; - Detail::computeLeastCommonSubsequenceMatrix<std::vector<char>::const_iterator, std::vector<char>::const_iterator, int, std::equal_to<char> >(x.begin(), x.end(), y.begin(), y.end(), result); - - std::vector<int> expected = boost::assign::list_of(0); - CPPUNIT_ASSERT_EQUAL(expected, result); - } - - void testComputeLeastCommonSubsequenceMatrix_NoCommonSequence() { - std::vector<char> x = boost::assign::list_of('a')('b')('c'); - std::vector<char> y = boost::assign::list_of('d')('e')('f')('g'); - - std::vector<int> result; - Detail::computeLeastCommonSubsequenceMatrix<std::vector<char>::const_iterator, std::vector<char>::const_iterator, int, std::equal_to<char> >(x.begin(), x.end(), y.begin(), y.end(), result); - - std::vector<int> expected = boost::assign::list_of - (0)(0)(0)(0) - (0)(0)(0)(0) - (0)(0)(0)(0) - (0)(0)(0)(0) - (0)(0)(0)(0); - CPPUNIT_ASSERT_EQUAL(expected, result); - } - - void testComputeLeastCommonSubsequenceMatrix_SameSequences() { - std::vector<char> x = boost::assign::list_of('a')('b')('c'); - std::vector<char> y = boost::assign::list_of('a')('b')('c'); - - std::vector<int> result; - Detail::computeLeastCommonSubsequenceMatrix<std::vector<char>::const_iterator, std::vector<char>::const_iterator, int, std::equal_to<char> >(x.begin(), x.end(), y.begin(), y.end(), result); - - std::vector<int> expected = boost::assign::list_of - (0)(0)(0)(0) - (0)(1)(1)(1) - (0)(1)(2)(2) - (0)(1)(2)(3); - CPPUNIT_ASSERT_EQUAL(expected, result); - } - - void testComputeIndexDiff_1() { - std::vector<std::string> x = boost::assign::list_of("Arizona")("California")("Delaware")("New Jersey")("Washington"); - std::vector<std::string> y = boost::assign::list_of("Alaska")("Arizona")("California")("Georgia")("New Jersey")("Virginia"); - - std::vector<size_t> updates; - std::vector<size_t> postUpdates; - std::vector<size_t> removes; - std::vector<size_t> inserts; - computeIndexDiff<std::string, std::equal_to<std::string>, IsArizonaOrNewJersey >(x, y, updates, postUpdates, removes, inserts); - - std::vector<size_t> expectedUpdates = boost::assign::list_of(3)(0); - std::vector<size_t> expectedPostUpdates = boost::assign::list_of(4)(1); - std::vector<size_t> expectedRemoves = boost::assign::list_of(4)(2); - std::vector<size_t> expectedInserts = boost::assign::list_of(5)(3)(0); - CPPUNIT_ASSERT_EQUAL(expectedUpdates, updates); - CPPUNIT_ASSERT_EQUAL(expectedPostUpdates, postUpdates); - CPPUNIT_ASSERT_EQUAL(expectedRemoves, removes); - CPPUNIT_ASSERT_EQUAL(expectedInserts, inserts); - } - - void testComputeIndexDiff_2() { - std::vector<char> x = boost::assign::list_of('x')('y'); - std::vector<char> y = boost::assign::list_of('x'); - - std::vector<size_t> updates; - std::vector<size_t> postUpdates; - std::vector<size_t> removes; - std::vector<size_t> inserts; - computeIndexDiff<char, std::equal_to<char>, IsBOrC >(x, y, updates, postUpdates, removes, inserts); - - std::vector<size_t> expectedRemoves = boost::assign::list_of(1); - CPPUNIT_ASSERT(updates.empty()); - CPPUNIT_ASSERT(postUpdates.empty()); - CPPUNIT_ASSERT(inserts.empty()); - CPPUNIT_ASSERT_EQUAL(expectedRemoves, removes); - } - - void testComputeIndexDiff_Sequence1Empty() { - std::vector<char> x; - std::vector<char> y = boost::assign::list_of('a')('b')('c'); - - std::vector<size_t> updates; - std::vector<size_t> postUpdates; - std::vector<size_t> removes; - std::vector<size_t> inserts; - computeIndexDiff<char, std::equal_to<char>, IsBOrC >(x, y, updates, postUpdates, removes, inserts); - - std::vector<size_t> expectedInserts = boost::assign::list_of(2)(1)(0); - CPPUNIT_ASSERT(updates.empty()); - CPPUNIT_ASSERT(postUpdates.empty()); - CPPUNIT_ASSERT(removes.empty()); - CPPUNIT_ASSERT_EQUAL(expectedInserts, inserts); - } - - void testComputeIndexDiff_Sequence2Empty() { - std::vector<char> x = boost::assign::list_of('a')('b')('c'); - std::vector<char> y; - - std::vector<size_t> updates; - std::vector<size_t> postUpdates; - std::vector<size_t> removes; - std::vector<size_t> inserts; - computeIndexDiff<char, std::equal_to<char>, IsBOrC >(x, y, updates, postUpdates, removes, inserts); - - std::vector<size_t> expectedRemoves = boost::assign::list_of(2)(1)(0); - CPPUNIT_ASSERT(updates.empty()); - CPPUNIT_ASSERT(postUpdates.empty()); - CPPUNIT_ASSERT_EQUAL(expectedRemoves, removes); - CPPUNIT_ASSERT(inserts.empty()); - } - - void testComputeIndexDiff_BothSequencesEmpty() { - std::vector<char> x; - std::vector<char> y; - - std::vector<size_t> updates; - std::vector<size_t> postUpdates; - std::vector<size_t> removes; - std::vector<size_t> inserts; - computeIndexDiff<char, std::equal_to<char>, IsBOrC >(x, y, updates, postUpdates, removes, inserts); - - CPPUNIT_ASSERT(updates.empty()); - CPPUNIT_ASSERT(postUpdates.empty()); - CPPUNIT_ASSERT(removes.empty()); - CPPUNIT_ASSERT(inserts.empty()); - } - - void testComputeIndexDiff_NoCommonSequence() { - std::vector<char> x = boost::assign::list_of('a')('b')('c'); - std::vector<char> y = boost::assign::list_of('d')('e')('f')('g'); - - std::vector<size_t> updates; - std::vector<size_t> postUpdates; - std::vector<size_t> removes; - std::vector<size_t> inserts; - computeIndexDiff<char, std::equal_to<char>, IsBOrC >(x, y, updates, postUpdates, removes, inserts); - - std::vector<size_t> expectedRemoves = boost::assign::list_of(2)(1)(0); - std::vector<size_t> expectedInserts = boost::assign::list_of(3)(2)(1)(0); - CPPUNIT_ASSERT(updates.empty()); - CPPUNIT_ASSERT(postUpdates.empty()); - CPPUNIT_ASSERT_EQUAL(expectedRemoves, removes); - CPPUNIT_ASSERT_EQUAL(expectedInserts, inserts); - } - - void testComputeIndexDiff_SameSequences() { - std::vector<char> x = boost::assign::list_of('a')('b')('c'); - std::vector<char> y = boost::assign::list_of('a')('b')('c'); - - std::vector<size_t> updates; - std::vector<size_t> postUpdates; - std::vector<size_t> removes; - std::vector<size_t> inserts; - computeIndexDiff<char, std::equal_to<char>, IsBOrC >(x, y, updates, postUpdates, removes, inserts); - - std::vector<size_t> expectedUpdates = boost::assign::list_of(1)(2); - CPPUNIT_ASSERT_EQUAL(expectedUpdates, updates); - CPPUNIT_ASSERT_EQUAL(expectedUpdates, postUpdates); - CPPUNIT_ASSERT(removes.empty()); - CPPUNIT_ASSERT(inserts.empty()); - } - - void testComputeIndexDiff_CommonPrefixAndSuffix() { - std::vector<char> x = boost::assign::list_of('x')('x')('x')('x')('a')('b')('c')('d')('e')('y')('y')('y'); - std::vector<char> y = boost::assign::list_of('x')('x')('x')('x')('e')('a')('b')('f')('d')('g')('y')('y')('y'); - - std::vector<size_t> updates; - std::vector<size_t> postUpdates; - std::vector<size_t> removes; - std::vector<size_t> inserts; - computeIndexDiff<char, std::equal_to<char>, IsXOrY >(x, y, updates, postUpdates, removes, inserts); - - std::vector<size_t> expectedUpdates = boost::assign::list_of(0)(1)(2)(3)(11)(10)(9); - std::vector<size_t> expectedPostUpdates = boost::assign::list_of(0)(1)(2)(3)(12)(11)(10); - std::vector<size_t> expectedRemoves = boost::assign::list_of(8)(6); - std::vector<size_t> expectedInserts = boost::assign::list_of(9)(7)(4); - CPPUNIT_ASSERT_EQUAL(expectedUpdates, updates); - CPPUNIT_ASSERT_EQUAL(expectedPostUpdates, postUpdates); - CPPUNIT_ASSERT_EQUAL(expectedRemoves, removes); - CPPUNIT_ASSERT_EQUAL(expectedInserts, inserts); - } + CPPUNIT_TEST_SUITE(LeastCommonSubsequenceTest); + CPPUNIT_TEST(testComputeLeastCommonSubsequenceMatrix_1); + CPPUNIT_TEST(testComputeLeastCommonSubsequenceMatrix_2); + CPPUNIT_TEST(testComputeLeastCommonSubsequenceMatrix_Sequence1Empty); + CPPUNIT_TEST(testComputeLeastCommonSubsequenceMatrix_Sequence2Empty); + CPPUNIT_TEST(testComputeLeastCommonSubsequenceMatrix_BothSequencesEmpty); + CPPUNIT_TEST(testComputeLeastCommonSubsequenceMatrix_NoCommonSequence); + CPPUNIT_TEST(testComputeLeastCommonSubsequenceMatrix_SameSequences); + CPPUNIT_TEST(testComputeIndexDiff_1); + CPPUNIT_TEST(testComputeIndexDiff_2); + CPPUNIT_TEST(testComputeIndexDiff_Sequence1Empty); + CPPUNIT_TEST(testComputeIndexDiff_Sequence2Empty); + CPPUNIT_TEST(testComputeIndexDiff_BothSequencesEmpty); + CPPUNIT_TEST(testComputeIndexDiff_NoCommonSequence); + CPPUNIT_TEST(testComputeIndexDiff_SameSequences); + CPPUNIT_TEST(testComputeIndexDiff_CommonPrefixAndSuffix); + CPPUNIT_TEST_SUITE_END(); + + public: + void testComputeLeastCommonSubsequenceMatrix_1() { + std::vector<char> x = boost::assign::list_of('x')('m')('j')('y')('a')('u')('z'); + std::vector<char> y = boost::assign::list_of('m')('z')('j')('a')('w')('x')('u'); + + std::vector<int> result; + Detail::computeLeastCommonSubsequenceMatrix<std::vector<char>::const_iterator, std::vector<char>::const_iterator, int, std::equal_to<char> >(x.begin(), x.end(), y.begin(), y.end(), result); + + std::vector<int> expected = boost::assign::list_of + (0)(0)(0)(0)(0)(0)(0)(0) + (0)(0)(1)(1)(1)(1)(1)(1) + (0)(0)(1)(1)(1)(1)(1)(2) + (0)(0)(1)(2)(2)(2)(2)(2) + (0)(0)(1)(2)(2)(3)(3)(3) + (0)(0)(1)(2)(2)(3)(3)(3) + (0)(1)(1)(2)(2)(3)(3)(3) + (0)(1)(1)(2)(2)(3)(4)(4); + CPPUNIT_ASSERT_EQUAL(expected, result); + } + + void testComputeLeastCommonSubsequenceMatrix_2() { + std::vector<char> x = boost::assign::list_of('x')('x')('x')('m')('j')('y')('a')('u')('z'); + std::vector<char> y = boost::assign::list_of('m')('z')('j')('a')('w')('x')('u'); + + std::vector<int> result; + Detail::computeLeastCommonSubsequenceMatrix<std::vector<char>::const_iterator, std::vector<char>::const_iterator, int, std::equal_to<char> >(x.begin(), x.end(), y.begin(), y.end(), result); + + std::vector<int> expected = boost::assign::list_of + (0)(0)(0)(0)(0)(0)(0)(0)(0)(0) + (0)(0)(0)(0)(1)(1)(1)(1)(1)(1) + (0)(0)(0)(0)(1)(1)(1)(1)(1)(2) + (0)(0)(0)(0)(1)(2)(2)(2)(2)(2) + (0)(0)(0)(0)(1)(2)(2)(3)(3)(3) + (0)(0)(0)(0)(1)(2)(2)(3)(3)(3) + (0)(1)(1)(1)(1)(2)(2)(3)(3)(3) + (0)(1)(1)(1)(1)(2)(2)(3)(4)(4); + CPPUNIT_ASSERT_EQUAL(expected, result); + } + + void testComputeLeastCommonSubsequenceMatrix_Sequence1Empty() { + std::vector<char> x; + std::vector<char> y = boost::assign::list_of('a')('b')('c'); + + std::vector<int> result; + Detail::computeLeastCommonSubsequenceMatrix<std::vector<char>::const_iterator, std::vector<char>::const_iterator, int, std::equal_to<char> >(x.begin(), x.end(), y.begin(), y.end(), result); + + std::vector<int> expected = boost::assign::list_of + (0) + (0) + (0) + (0); + CPPUNIT_ASSERT_EQUAL(expected, result); + } + + void testComputeLeastCommonSubsequenceMatrix_Sequence2Empty() { + std::vector<char> x = boost::assign::list_of('a')('b')('c'); + std::vector<char> y; + + std::vector<int> result; + Detail::computeLeastCommonSubsequenceMatrix<std::vector<char>::const_iterator, std::vector<char>::const_iterator, int, std::equal_to<char> >(x.begin(), x.end(), y.begin(), y.end(), result); + + std::vector<int> expected = boost::assign::list_of + (0)(0)(0)(0); + CPPUNIT_ASSERT_EQUAL(expected, result); + } + + void testComputeLeastCommonSubsequenceMatrix_BothSequencesEmpty() { + std::vector<char> x; + std::vector<char> y; + + std::vector<int> result; + Detail::computeLeastCommonSubsequenceMatrix<std::vector<char>::const_iterator, std::vector<char>::const_iterator, int, std::equal_to<char> >(x.begin(), x.end(), y.begin(), y.end(), result); + + std::vector<int> expected = boost::assign::list_of(0); + CPPUNIT_ASSERT_EQUAL(expected, result); + } + + void testComputeLeastCommonSubsequenceMatrix_NoCommonSequence() { + std::vector<char> x = boost::assign::list_of('a')('b')('c'); + std::vector<char> y = boost::assign::list_of('d')('e')('f')('g'); + + std::vector<int> result; + Detail::computeLeastCommonSubsequenceMatrix<std::vector<char>::const_iterator, std::vector<char>::const_iterator, int, std::equal_to<char> >(x.begin(), x.end(), y.begin(), y.end(), result); + + std::vector<int> expected = boost::assign::list_of + (0)(0)(0)(0) + (0)(0)(0)(0) + (0)(0)(0)(0) + (0)(0)(0)(0) + (0)(0)(0)(0); + CPPUNIT_ASSERT_EQUAL(expected, result); + } + + void testComputeLeastCommonSubsequenceMatrix_SameSequences() { + std::vector<char> x = boost::assign::list_of('a')('b')('c'); + std::vector<char> y = boost::assign::list_of('a')('b')('c'); + + std::vector<int> result; + Detail::computeLeastCommonSubsequenceMatrix<std::vector<char>::const_iterator, std::vector<char>::const_iterator, int, std::equal_to<char> >(x.begin(), x.end(), y.begin(), y.end(), result); + + std::vector<int> expected = boost::assign::list_of + (0)(0)(0)(0) + (0)(1)(1)(1) + (0)(1)(2)(2) + (0)(1)(2)(3); + CPPUNIT_ASSERT_EQUAL(expected, result); + } + + void testComputeIndexDiff_1() { + std::vector<std::string> x = boost::assign::list_of("Arizona")("California")("Delaware")("New Jersey")("Washington"); + std::vector<std::string> y = boost::assign::list_of("Alaska")("Arizona")("California")("Georgia")("New Jersey")("Virginia"); + + std::vector<size_t> updates; + std::vector<size_t> postUpdates; + std::vector<size_t> removes; + std::vector<size_t> inserts; + computeIndexDiff<std::string, std::equal_to<std::string>, IsArizonaOrNewJersey >(x, y, updates, postUpdates, removes, inserts); + + std::vector<size_t> expectedUpdates = boost::assign::list_of(3)(0); + std::vector<size_t> expectedPostUpdates = boost::assign::list_of(4)(1); + std::vector<size_t> expectedRemoves = boost::assign::list_of(4)(2); + std::vector<size_t> expectedInserts = boost::assign::list_of(5)(3)(0); + CPPUNIT_ASSERT_EQUAL(expectedUpdates, updates); + CPPUNIT_ASSERT_EQUAL(expectedPostUpdates, postUpdates); + CPPUNIT_ASSERT_EQUAL(expectedRemoves, removes); + CPPUNIT_ASSERT_EQUAL(expectedInserts, inserts); + } + + void testComputeIndexDiff_2() { + std::vector<char> x = boost::assign::list_of('x')('y'); + std::vector<char> y = boost::assign::list_of('x'); + + std::vector<size_t> updates; + std::vector<size_t> postUpdates; + std::vector<size_t> removes; + std::vector<size_t> inserts; + computeIndexDiff<char, std::equal_to<char>, IsBOrC >(x, y, updates, postUpdates, removes, inserts); + + std::vector<size_t> expectedRemoves = boost::assign::list_of(1); + CPPUNIT_ASSERT(updates.empty()); + CPPUNIT_ASSERT(postUpdates.empty()); + CPPUNIT_ASSERT(inserts.empty()); + CPPUNIT_ASSERT_EQUAL(expectedRemoves, removes); + } + + void testComputeIndexDiff_Sequence1Empty() { + std::vector<char> x; + std::vector<char> y = boost::assign::list_of('a')('b')('c'); + + std::vector<size_t> updates; + std::vector<size_t> postUpdates; + std::vector<size_t> removes; + std::vector<size_t> inserts; + computeIndexDiff<char, std::equal_to<char>, IsBOrC >(x, y, updates, postUpdates, removes, inserts); + + std::vector<size_t> expectedInserts = boost::assign::list_of(2)(1)(0); + CPPUNIT_ASSERT(updates.empty()); + CPPUNIT_ASSERT(postUpdates.empty()); + CPPUNIT_ASSERT(removes.empty()); + CPPUNIT_ASSERT_EQUAL(expectedInserts, inserts); + } + + void testComputeIndexDiff_Sequence2Empty() { + std::vector<char> x = boost::assign::list_of('a')('b')('c'); + std::vector<char> y; + + std::vector<size_t> updates; + std::vector<size_t> postUpdates; + std::vector<size_t> removes; + std::vector<size_t> inserts; + computeIndexDiff<char, std::equal_to<char>, IsBOrC >(x, y, updates, postUpdates, removes, inserts); + + std::vector<size_t> expectedRemoves = boost::assign::list_of(2)(1)(0); + CPPUNIT_ASSERT(updates.empty()); + CPPUNIT_ASSERT(postUpdates.empty()); + CPPUNIT_ASSERT_EQUAL(expectedRemoves, removes); + CPPUNIT_ASSERT(inserts.empty()); + } + + void testComputeIndexDiff_BothSequencesEmpty() { + std::vector<char> x; + std::vector<char> y; + + std::vector<size_t> updates; + std::vector<size_t> postUpdates; + std::vector<size_t> removes; + std::vector<size_t> inserts; + computeIndexDiff<char, std::equal_to<char>, IsBOrC >(x, y, updates, postUpdates, removes, inserts); + + CPPUNIT_ASSERT(updates.empty()); + CPPUNIT_ASSERT(postUpdates.empty()); + CPPUNIT_ASSERT(removes.empty()); + CPPUNIT_ASSERT(inserts.empty()); + } + + void testComputeIndexDiff_NoCommonSequence() { + std::vector<char> x = boost::assign::list_of('a')('b')('c'); + std::vector<char> y = boost::assign::list_of('d')('e')('f')('g'); + + std::vector<size_t> updates; + std::vector<size_t> postUpdates; + std::vector<size_t> removes; + std::vector<size_t> inserts; + computeIndexDiff<char, std::equal_to<char>, IsBOrC >(x, y, updates, postUpdates, removes, inserts); + + std::vector<size_t> expectedRemoves = boost::assign::list_of(2)(1)(0); + std::vector<size_t> expectedInserts = boost::assign::list_of(3)(2)(1)(0); + CPPUNIT_ASSERT(updates.empty()); + CPPUNIT_ASSERT(postUpdates.empty()); + CPPUNIT_ASSERT_EQUAL(expectedRemoves, removes); + CPPUNIT_ASSERT_EQUAL(expectedInserts, inserts); + } + + void testComputeIndexDiff_SameSequences() { + std::vector<char> x = boost::assign::list_of('a')('b')('c'); + std::vector<char> y = boost::assign::list_of('a')('b')('c'); + + std::vector<size_t> updates; + std::vector<size_t> postUpdates; + std::vector<size_t> removes; + std::vector<size_t> inserts; + computeIndexDiff<char, std::equal_to<char>, IsBOrC >(x, y, updates, postUpdates, removes, inserts); + + std::vector<size_t> expectedUpdates = boost::assign::list_of(1)(2); + CPPUNIT_ASSERT_EQUAL(expectedUpdates, updates); + CPPUNIT_ASSERT_EQUAL(expectedUpdates, postUpdates); + CPPUNIT_ASSERT(removes.empty()); + CPPUNIT_ASSERT(inserts.empty()); + } + + void testComputeIndexDiff_CommonPrefixAndSuffix() { + std::vector<char> x = boost::assign::list_of('x')('x')('x')('x')('a')('b')('c')('d')('e')('y')('y')('y'); + std::vector<char> y = boost::assign::list_of('x')('x')('x')('x')('e')('a')('b')('f')('d')('g')('y')('y')('y'); + + std::vector<size_t> updates; + std::vector<size_t> postUpdates; + std::vector<size_t> removes; + std::vector<size_t> inserts; + computeIndexDiff<char, std::equal_to<char>, IsXOrY >(x, y, updates, postUpdates, removes, inserts); + + std::vector<size_t> expectedUpdates = boost::assign::list_of(0)(1)(2)(3)(11)(10)(9); + std::vector<size_t> expectedPostUpdates = boost::assign::list_of(0)(1)(2)(3)(12)(11)(10); + std::vector<size_t> expectedRemoves = boost::assign::list_of(8)(6); + std::vector<size_t> expectedInserts = boost::assign::list_of(9)(7)(4); + CPPUNIT_ASSERT_EQUAL(expectedUpdates, updates); + CPPUNIT_ASSERT_EQUAL(expectedPostUpdates, postUpdates); + CPPUNIT_ASSERT_EQUAL(expectedRemoves, removes); + CPPUNIT_ASSERT_EQUAL(expectedInserts, inserts); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(LeastCommonSubsequenceTest); diff --git a/Swift/Controllers/Roster/UnitTest/RosterControllerTest.cpp b/Swift/Controllers/Roster/UnitTest/RosterControllerTest.cpp index d774e6d..ddbd7d3 100644 --- a/Swift/Controllers/Roster/UnitTest/RosterControllerTest.cpp +++ b/Swift/Controllers/Roster/UnitTest/RosterControllerTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2015 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -9,17 +9,19 @@ #include <Swiften/Avatars/NullAvatarManager.h> #include <Swiften/Base/Algorithm.h> -#include <Swiften/Base/foreach.h> #include <Swiften/Client/ClientBlockListManager.h> #include <Swiften/Client/DummyNickManager.h> #include <Swiften/Client/DummyStanzaChannel.h> +#include <Swiften/Client/MemoryStorages.h> #include <Swiften/Client/NickResolver.h> #include <Swiften/Crypto/CryptoProvider.h> #include <Swiften/Crypto/PlatformCryptoProvider.h> +#include <Swiften/Disco/CapsInfoGenerator.h> +#include <Swiften/Disco/CapsManager.h> #include <Swiften/Disco/CapsProvider.h> +#include <Swiften/Disco/ClientDiscoManager.h> #include <Swiften/Disco/EntityCapsManager.h> #include <Swiften/EventLoop/DummyEventLoop.h> -#include <Swiften/FileTransfer/UnitTest/DummyFileTransferManager.h> #include <Swiften/Jingle/JingleSessionManager.h> #include <Swiften/MUC/MUCRegistry.h> #include <Swiften/Presence/PresenceOracle.h> @@ -30,7 +32,6 @@ #include <Swiften/VCards/VCardManager.h> #include <Swiften/VCards/VCardMemoryStorage.h> -#include <Swift/Controllers/FileTransfer/FileTransferOverview.h> #include <Swift/Controllers/Roster/ContactRosterItem.h> #include <Swift/Controllers/Roster/GroupRosterItem.h> #include <Swift/Controllers/Roster/Roster.h> @@ -43,354 +44,438 @@ using namespace Swift; -#define CHILDREN mainWindow_->roster->getRoot()->getChildren() - class DummyCapsProvider : public CapsProvider { - DiscoInfo::ref getCaps(const std::string&) const {return DiscoInfo::ref(new DiscoInfo());} + DiscoInfo::ref getCaps(const std::string&) const {return DiscoInfo::ref(new DiscoInfo());} }; class RosterControllerTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(RosterControllerTest); - CPPUNIT_TEST(testAdd); - CPPUNIT_TEST(testAddSubscription); - CPPUNIT_TEST(testReceiveRename); - CPPUNIT_TEST(testReceiveRegroup); - CPPUNIT_TEST(testSendRename); - CPPUNIT_TEST(testPresence); - CPPUNIT_TEST(testHighestPresence); - CPPUNIT_TEST(testNotHighestPresence); - CPPUNIT_TEST(testUnavailablePresence); - CPPUNIT_TEST(testRemoveResultsInUnavailablePresence); - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - jid_ = JID("testjid@swift.im/swift"); - xmppRoster_ = new XMPPRosterImpl(); - avatarManager_ = new NullAvatarManager(); - mainWindowFactory_ = new MockMainWindowFactory(); - mucRegistry_ = new MUCRegistry(); - nickResolver_ = new NickResolver(jid_.toBare(), xmppRoster_, NULL, mucRegistry_); - channel_ = new DummyIQChannel(); - router_ = new IQRouter(channel_); - stanzaChannel_ = new DummyStanzaChannel(); - presenceOracle_ = new PresenceOracle(stanzaChannel_, xmppRoster_); - subscriptionManager_ = new SubscriptionManager(stanzaChannel_); - eventController_ = new EventController(); - uiEventStream_ = new UIEventStream(); - settings_ = new DummySettingsProvider(); - nickManager_ = new DummyNickManager(); - capsProvider_ = new DummyCapsProvider(); - entityCapsManager_ = new EntityCapsManager(capsProvider_, stanzaChannel_); - jingleSessionManager_ = new JingleSessionManager(router_); - - ftManager_ = new DummyFileTransferManager(); - ftOverview_ = new FileTransferOverview(ftManager_); - clientBlockListManager_ = new ClientBlockListManager(router_); - crypto_ = PlatformCryptoProvider::create(); - vcardStorage_ = new VCardMemoryStorage(crypto_); - vcardManager_ = new VCardManager(jid_, router_, vcardStorage_); - rosterController_ = new RosterController(jid_, xmppRoster_, avatarManager_, mainWindowFactory_, nickManager_, nickResolver_, presenceOracle_, subscriptionManager_, eventController_, uiEventStream_, router_, settings_, entityCapsManager_, ftOverview_, clientBlockListManager_, vcardManager_); - mainWindow_ = mainWindowFactory_->last; - } - - void tearDown() { - delete rosterController_; - delete vcardManager_; - delete vcardStorage_; - delete crypto_; - delete clientBlockListManager_; - delete ftOverview_; - delete ftManager_; - delete jingleSessionManager_; - delete entityCapsManager_; - delete capsProvider_; - delete nickManager_; - delete nickResolver_; - delete mucRegistry_; - delete mainWindowFactory_; - delete avatarManager_; - delete router_; - delete channel_; - delete eventController_; - delete subscriptionManager_; - delete presenceOracle_; - delete stanzaChannel_; - delete uiEventStream_; - delete settings_; - delete xmppRoster_; - } - - GroupRosterItem* groupChild(size_t i) { - return dynamic_cast<GroupRosterItem*>(CHILDREN[i]); - } - - JID withResource(const JID& jid, const std::string& resource) { - return JID(jid.toBare().toString() + "/" + resource); - } - - void testPresence() { - std::vector<std::string> groups; - groups.push_back("testGroup1"); - groups.push_back("testGroup2"); - JID from("test@testdomain.com"); - xmppRoster_->addContact(from, "name", groups, RosterItemPayload::Both); - Presence::ref presence(new Presence()); - presence->setFrom(withResource(from, "bob")); - presence->setPriority(2); - presence->setStatus("So totally here"); - stanzaChannel_->onPresenceReceived(presence); - ContactRosterItem* item = dynamic_cast<ContactRosterItem*>(dynamic_cast<GroupRosterItem*>(CHILDREN[0])->getChildren()[0]); - CPPUNIT_ASSERT(item); - CPPUNIT_ASSERT_EQUAL(presence->getStatus(), item->getStatusText()); - ContactRosterItem* item2 = dynamic_cast<ContactRosterItem*>(dynamic_cast<GroupRosterItem*>(CHILDREN[1])->getChildren()[0]); - CPPUNIT_ASSERT(item2); - CPPUNIT_ASSERT_EQUAL(presence->getStatus(), item2->getStatusText()); - - } - - void testHighestPresence() { - std::vector<std::string> groups; - groups.push_back("testGroup1"); - JID from("test@testdomain.com"); - xmppRoster_->addContact(from, "name", groups, RosterItemPayload::Both); - Presence::ref lowPresence(new Presence()); - lowPresence->setFrom(withResource(from, "bob")); - lowPresence->setPriority(2); - lowPresence->setStatus("Not here"); - Presence::ref highPresence(new Presence()); - highPresence->setFrom(withResource(from, "bert")); - highPresence->setPriority(10); - highPresence->setStatus("So totally here"); - stanzaChannel_->onPresenceReceived(lowPresence); - stanzaChannel_->onPresenceReceived(highPresence); - ContactRosterItem* item = dynamic_cast<ContactRosterItem*>(dynamic_cast<GroupRosterItem*>(CHILDREN[0])->getChildren()[0]); - CPPUNIT_ASSERT(item); - CPPUNIT_ASSERT_EQUAL(highPresence->getStatus(), item->getStatusText()); - } - - void testNotHighestPresence() { - std::vector<std::string> groups; - groups.push_back("testGroup1"); - JID from("test@testdomain.com"); - xmppRoster_->addContact(from, "name", groups, RosterItemPayload::Both); - Presence::ref lowPresence(new Presence()); - lowPresence->setFrom(withResource(from, "bob")); - lowPresence->setPriority(2); - lowPresence->setStatus("Not here"); - Presence::ref highPresence(new Presence()); - highPresence->setFrom(withResource(from, "bert")); - highPresence->setPriority(10); - highPresence->setStatus("So totally here"); - stanzaChannel_->onPresenceReceived(highPresence); - stanzaChannel_->onPresenceReceived(lowPresence); - ContactRosterItem* item = dynamic_cast<ContactRosterItem*>(dynamic_cast<GroupRosterItem*>(CHILDREN[0])->getChildren()[0]); - CPPUNIT_ASSERT(item); - CPPUNIT_ASSERT_EQUAL(highPresence->getStatus(), item->getStatusText()); - } - - void testUnavailablePresence() { - std::vector<std::string> groups; - groups.push_back("testGroup1"); - JID from("test@testdomain.com"); - xmppRoster_->addContact(from, "name", groups, RosterItemPayload::Both); - - Presence::ref lowPresence(new Presence()); - lowPresence->setFrom(withResource(from, "bob")); - lowPresence->setPriority(2); - lowPresence->setShow(StatusShow::Away); - lowPresence->setStatus("Not here"); - Presence::ref lowPresenceOffline(new Presence()); - lowPresenceOffline->setFrom(withResource(from, "bob")); - lowPresenceOffline->setStatus("Signing out"); - lowPresenceOffline->setType(Presence::Unavailable); - - Presence::ref highPresence(new Presence()); - highPresence->setFrom(withResource(from, "bert")); - highPresence->setPriority(10); - highPresence->setStatus("So totally here"); - Presence::ref highPresenceOffline(new Presence()); - highPresenceOffline->setFrom(withResource(from, "bert")); - highPresenceOffline->setType(Presence::Unavailable); - - stanzaChannel_->onPresenceReceived(lowPresence); - Presence::ref accountPresence = presenceOracle_->getAccountPresence(from); - CPPUNIT_ASSERT_EQUAL(StatusShow::Away, accountPresence->getShow()); - - stanzaChannel_->onPresenceReceived(highPresence); - accountPresence = presenceOracle_->getAccountPresence(from); - CPPUNIT_ASSERT_EQUAL(StatusShow::Online, accountPresence->getShow()); - - stanzaChannel_->onPresenceReceived(highPresenceOffline); - - // After this, the roster should show the low presence. - ContactRosterItem* item = dynamic_cast<ContactRosterItem*>(dynamic_cast<GroupRosterItem*>(CHILDREN[0])->getChildren()[0]); - CPPUNIT_ASSERT(item); - - Presence::ref low = presenceOracle_->getAccountPresence(from); - - CPPUNIT_ASSERT_EQUAL(Presence::Available, low->getType()); - CPPUNIT_ASSERT_EQUAL(lowPresence->getStatus(), low->getStatus()); - CPPUNIT_ASSERT_EQUAL(lowPresence->getShow(), item->getStatusShow()); - CPPUNIT_ASSERT_EQUAL(lowPresence->getStatus(), item->getStatusText()); - stanzaChannel_->onPresenceReceived(lowPresenceOffline); - item = dynamic_cast<ContactRosterItem*>(dynamic_cast<GroupRosterItem*>(CHILDREN[0])->getChildren()[0]); - CPPUNIT_ASSERT(item); - /* A verification that if the test fails, it's the RosterController, not the PresenceOracle. */ - low = presenceOracle_->getHighestPriorityPresence(from); - CPPUNIT_ASSERT_EQUAL(Presence::Unavailable, low->getType()); - CPPUNIT_ASSERT_EQUAL(lowPresenceOffline->getStatus(), low->getStatus()); - CPPUNIT_ASSERT_EQUAL(StatusShow::None, item->getStatusShow()); - CPPUNIT_ASSERT_EQUAL(lowPresenceOffline->getStatus(), item->getStatusText()); - } - - void testAdd() { - std::vector<std::string> groups; - groups.push_back("testGroup1"); - groups.push_back("testGroup2"); - xmppRoster_->addContact(JID("test@testdomain.com/bob"), "name", groups, RosterItemPayload::Both); - - CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(CHILDREN.size())); - //CPPUNIT_ASSERT_EQUAL(std::string("Bob"), xmppRoster_->getNameForJID(JID("foo@bar.com"))); - } - - void testAddSubscription() { - std::vector<std::string> groups; - JID jid("test@testdomain.com"); - xmppRoster_->addContact(jid, "name", groups, RosterItemPayload::None); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(CHILDREN.size())); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(groupChild(0)->getChildren().size())); - xmppRoster_->addContact(jid, "name", groups, RosterItemPayload::To); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(CHILDREN.size())); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(groupChild(0)->getChildren().size())); - - xmppRoster_->addContact(jid, "name", groups, RosterItemPayload::Both); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(CHILDREN.size())); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(groupChild(0)->getChildren().size())); - - } - - void testReceiveRename() { - std::vector<std::string> groups; - JID jid("test@testdomain.com"); - xmppRoster_->addContact(jid, "name", groups, RosterItemPayload::Both); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(CHILDREN.size())); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(groupChild(0)->getChildren().size())); - CPPUNIT_ASSERT_EQUAL(std::string("name"), groupChild(0)->getChildren()[0]->getDisplayName()); - xmppRoster_->addContact(jid, "NewName", groups, RosterItemPayload::Both); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(CHILDREN.size())); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(groupChild(0)->getChildren().size())); - CPPUNIT_ASSERT_EQUAL(std::string("NewName"), groupChild(0)->getChildren()[0]->getDisplayName()); - } - - void testReceiveRegroup() { - std::vector<std::string> oldGroups; - std::vector<std::string> newGroups; - newGroups.push_back("A Group"); - std::vector<std::string> newestGroups; - newestGroups.push_back("Best Group"); - JID jid("test@testdomain.com"); - xmppRoster_->addContact(jid, "", oldGroups, RosterItemPayload::Both); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(CHILDREN.size())); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(groupChild(0)->getChildren().size())); - CPPUNIT_ASSERT_EQUAL(jid.toString(), groupChild(0)->getChildren()[0]->getDisplayName()); - - xmppRoster_->addContact(jid, "new name", newGroups, RosterItemPayload::Both); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(CHILDREN.size())); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(groupChild(0)->getChildren().size())); - CPPUNIT_ASSERT_EQUAL(std::string("new name"), groupChild(0)->getChildren()[0]->getDisplayName()); - CPPUNIT_ASSERT_EQUAL(std::string("A Group"), groupChild(0)->getDisplayName()); - - xmppRoster_->addContact(jid, "new name", newestGroups, RosterItemPayload::Both); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(CHILDREN.size())); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(groupChild(0)->getChildren().size())); - CPPUNIT_ASSERT_EQUAL(std::string("new name"), groupChild(0)->getChildren()[0]->getDisplayName()); - CPPUNIT_ASSERT_EQUAL(std::string("Best Group"), groupChild(0)->getDisplayName()); - } - - void testSendRename() { - JID jid("testling@wonderland.lit"); - std::vector<std::string> groups; - groups.push_back("Friends"); - groups.push_back("Enemies"); - xmppRoster_->addContact(jid, "Bob", groups, RosterItemPayload::From); - CPPUNIT_ASSERT_EQUAL(groups.size(), xmppRoster_->getGroupsForJID(jid).size()); - uiEventStream_->send(boost::shared_ptr<UIEvent>(new RenameRosterItemUIEvent(jid, "Robert"))); - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), channel_->iqs_.size()); - CPPUNIT_ASSERT_EQUAL(IQ::Set, channel_->iqs_[0]->getType()); - boost::shared_ptr<RosterPayload> payload = channel_->iqs_[0]->getPayload<RosterPayload>(); - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), payload->getItems().size()); - RosterItemPayload item = payload->getItems()[0]; - CPPUNIT_ASSERT_EQUAL(jid, item.getJID()); - CPPUNIT_ASSERT_EQUAL(std::string("Robert"), item.getName()); - - CPPUNIT_ASSERT_EQUAL(groups.size(), item.getGroups().size()); - assertVectorsEqual(groups, item.getGroups(), __LINE__); - } - - void testRemoveResultsInUnavailablePresence() { - std::vector<std::string> groups; - groups.push_back("testGroup1"); - JID from("test@testdomain.com"); - xmppRoster_->addContact(from, "name", groups, RosterItemPayload::Both); - Presence::ref lowPresence(new Presence()); - lowPresence->setFrom(withResource(from, "bob")); - lowPresence->setPriority(2); - lowPresence->setStatus("Not here"); - Presence::ref highPresence(new Presence()); - highPresence->setFrom(withResource(from, "bert")); - highPresence->setPriority(10); - highPresence->setStatus("So totally here"); - stanzaChannel_->onPresenceReceived(highPresence); - stanzaChannel_->onPresenceReceived(lowPresence); - - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), presenceOracle_->getAllPresence("test@testdomain.com").size()); - - xmppRoster_->onJIDRemoved(JID("test@testdomain.com")); - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), presenceOracle_->getAllPresence("test@testdomain.com").size()); - CPPUNIT_ASSERT_EQUAL(Presence::Unavailable, presenceOracle_->getAllPresence("test@testdomain.com")[0]->getType()); - } - - void assertVectorsEqual(const std::vector<std::string>& v1, const std::vector<std::string>& v2, int line) { - foreach (const std::string& entry, v1) { - if (std::find(v2.begin(), v2.end(), entry) == v2.end()) { - std::stringstream stream; - stream << "Couldn't find " << entry << " in v2 (line " << line << ")"; - CPPUNIT_FAIL(stream.str()); - } - } - } - - private: - JID jid_; - XMPPRosterImpl* xmppRoster_; - MUCRegistry* mucRegistry_; - AvatarManager* avatarManager_; - MockMainWindowFactory* mainWindowFactory_; - NickManager* nickManager_; - NickResolver* nickResolver_; - RosterController* rosterController_; - DummyIQChannel* channel_; - DummyStanzaChannel* stanzaChannel_; - IQRouter* router_; - PresenceOracle* presenceOracle_; - SubscriptionManager* subscriptionManager_; - EventController* eventController_; - UIEventStream* uiEventStream_; - MockMainWindow* mainWindow_; - DummySettingsProvider* settings_; - DummyCapsProvider* capsProvider_; - EntityCapsManager* entityCapsManager_; - JingleSessionManager* jingleSessionManager_; - FileTransferManager* ftManager_; - FileTransferOverview* ftOverview_; - ClientBlockListManager* clientBlockListManager_; - CryptoProvider* crypto_; - VCardStorage* vcardStorage_; - VCardManager* vcardManager_; + CPPUNIT_TEST_SUITE(RosterControllerTest); + CPPUNIT_TEST(testAdd); + CPPUNIT_TEST(testAddSubscription); + CPPUNIT_TEST(testReceiveRename); + CPPUNIT_TEST(testReceiveRegroup); + CPPUNIT_TEST(testSendRename); + CPPUNIT_TEST(testPresence); + CPPUNIT_TEST(testHighestPresence); + CPPUNIT_TEST(testNotHighestPresence); + CPPUNIT_TEST(testUnavailablePresence); + CPPUNIT_TEST(testRemoveResultsInUnavailablePresence); + CPPUNIT_TEST(testOwnContactInRosterPresence); + CPPUNIT_TEST(testMultiResourceFileTransferFeature); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + jid_ = JID("testjid@swift.im/swift"); + xmppRoster_ = new XMPPRosterImpl(); + avatarManager_ = new NullAvatarManager(); + mainWindowFactory_ = new MockMainWindowFactory(); + mucRegistry_ = new MUCRegistry(); + crypto_ = PlatformCryptoProvider::create(); + storages_ = std::unique_ptr<MemoryStorages>(new MemoryStorages(crypto_)); + nickResolver_ = new NickResolver(jid_.toBare(), xmppRoster_, nullptr, mucRegistry_); + channel_ = new DummyIQChannel(); + router_ = new IQRouter(channel_); + stanzaChannel_ = new DummyStanzaChannel(); + presenceOracle_ = new PresenceOracle(stanzaChannel_, xmppRoster_); + subscriptionManager_ = new SubscriptionManager(stanzaChannel_); + eventController_ = new EventController(); + uiEventStream_ = new UIEventStream(); + settings_ = new DummySettingsProvider(); + nickManager_ = new DummyNickManager(); + capsManager_ = std::unique_ptr<CapsManager>(new CapsManager(storages_->getCapsStorage(), stanzaChannel_, router_, crypto_)); + entityCapsManager_ = new EntityCapsManager(capsManager_.get(), stanzaChannel_); + jingleSessionManager_ = new JingleSessionManager(router_); + + clientBlockListManager_ = new ClientBlockListManager(router_); + vcardStorage_ = new VCardMemoryStorage(crypto_); + vcardManager_ = new VCardManager(jid_, router_, vcardStorage_); + rosterController_ = new RosterController(jid_, xmppRoster_, avatarManager_, mainWindowFactory_, nickManager_, nickResolver_, presenceOracle_, subscriptionManager_, eventController_, uiEventStream_, router_, settings_, entityCapsManager_, clientBlockListManager_, vcardManager_); + mainWindow_ = mainWindowFactory_->last; + capsInfoGenerator_ = std::unique_ptr<CapsInfoGenerator>(new CapsInfoGenerator("", crypto_)); + } + + void tearDown() { + delete rosterController_; + delete vcardManager_; + delete vcardStorage_; + delete crypto_; + delete clientBlockListManager_; + delete jingleSessionManager_; + delete entityCapsManager_; + delete nickManager_; + delete nickResolver_; + delete mucRegistry_; + delete mainWindowFactory_; + delete avatarManager_; + delete router_; + delete channel_; + delete eventController_; + delete subscriptionManager_; + delete presenceOracle_; + delete stanzaChannel_; + delete uiEventStream_; + delete settings_; + delete xmppRoster_; + } + + GroupRosterItem* groupChild(size_t i) { + return dynamic_cast<GroupRosterItem*>(getUIRosterChildren()[i]); + } + + JID withResource(const JID& jid, const std::string& resource) { + return JID(jid.toBare().toString() + "/" + resource); + } + + void testPresence() { + std::vector<std::string> groups; + groups.push_back("testGroup1"); + groups.push_back("testGroup2"); + JID from("test@testdomain.com"); + xmppRoster_->addContact(from, "name", groups, RosterItemPayload::Both); + Presence::ref presence(new Presence()); + presence->setFrom(withResource(from, "bob")); + presence->setPriority(2); + presence->setStatus("So totally here"); + stanzaChannel_->onPresenceReceived(presence); + ContactRosterItem* item = dynamic_cast<ContactRosterItem*>(dynamic_cast<GroupRosterItem*>(getUIRosterChildren()[0])->getChildren()[0]); + CPPUNIT_ASSERT(item); + CPPUNIT_ASSERT_EQUAL(presence->getStatus(), item->getStatusText()); + ContactRosterItem* item2 = dynamic_cast<ContactRosterItem*>(dynamic_cast<GroupRosterItem*>(getUIRosterChildren()[1])->getChildren()[0]); + CPPUNIT_ASSERT(item2); + CPPUNIT_ASSERT_EQUAL(presence->getStatus(), item2->getStatusText()); + } + + void testHighestPresence() { + std::vector<std::string> groups; + groups.push_back("testGroup1"); + JID from("test@testdomain.com"); + xmppRoster_->addContact(from, "name", groups, RosterItemPayload::Both); + Presence::ref lowPresence(new Presence()); + lowPresence->setFrom(withResource(from, "bob")); + lowPresence->setPriority(2); + lowPresence->setStatus("Not here"); + Presence::ref highPresence(new Presence()); + highPresence->setFrom(withResource(from, "bert")); + highPresence->setPriority(10); + highPresence->setStatus("So totally here"); + stanzaChannel_->onPresenceReceived(lowPresence); + stanzaChannel_->onPresenceReceived(highPresence); + ContactRosterItem* item = dynamic_cast<ContactRosterItem*>(dynamic_cast<GroupRosterItem*>(getUIRosterChildren()[0])->getChildren()[0]); + CPPUNIT_ASSERT(item); + CPPUNIT_ASSERT_EQUAL(highPresence->getStatus(), item->getStatusText()); + } + + void testNotHighestPresence() { + std::vector<std::string> groups; + groups.push_back("testGroup1"); + JID from("test@testdomain.com"); + xmppRoster_->addContact(from, "name", groups, RosterItemPayload::Both); + Presence::ref lowPresence(new Presence()); + lowPresence->setFrom(withResource(from, "bob")); + lowPresence->setPriority(2); + lowPresence->setStatus("Not here"); + Presence::ref highPresence(new Presence()); + highPresence->setFrom(withResource(from, "bert")); + highPresence->setPriority(10); + highPresence->setStatus("So totally here"); + stanzaChannel_->onPresenceReceived(highPresence); + stanzaChannel_->onPresenceReceived(lowPresence); + ContactRosterItem* item = dynamic_cast<ContactRosterItem*>(dynamic_cast<GroupRosterItem*>(getUIRosterChildren()[0])->getChildren()[0]); + CPPUNIT_ASSERT(item); + CPPUNIT_ASSERT_EQUAL(highPresence->getStatus(), item->getStatusText()); + } + + void testUnavailablePresence() { + std::vector<std::string> groups; + groups.push_back("testGroup1"); + JID from("test@testdomain.com"); + xmppRoster_->addContact(from, "name", groups, RosterItemPayload::Both); + + Presence::ref lowPresence(new Presence()); + lowPresence->setFrom(withResource(from, "bob")); + lowPresence->setPriority(2); + lowPresence->setShow(StatusShow::Away); + lowPresence->setStatus("Not here"); + Presence::ref lowPresenceOffline(new Presence()); + lowPresenceOffline->setFrom(withResource(from, "bob")); + lowPresenceOffline->setStatus("Signing out"); + lowPresenceOffline->setType(Presence::Unavailable); + + Presence::ref highPresence(new Presence()); + highPresence->setFrom(withResource(from, "bert")); + highPresence->setPriority(10); + highPresence->setStatus("So totally here"); + Presence::ref highPresenceOffline(new Presence()); + highPresenceOffline->setFrom(withResource(from, "bert")); + highPresenceOffline->setType(Presence::Unavailable); + + stanzaChannel_->onPresenceReceived(lowPresence); + Presence::ref accountPresence = presenceOracle_->getAccountPresence(from); + CPPUNIT_ASSERT_EQUAL(StatusShow::Away, accountPresence->getShow()); + + stanzaChannel_->onPresenceReceived(highPresence); + accountPresence = presenceOracle_->getAccountPresence(from); + CPPUNIT_ASSERT_EQUAL(StatusShow::Online, accountPresence->getShow()); + + stanzaChannel_->onPresenceReceived(highPresenceOffline); + + // After this, the roster should show the low presence. + ContactRosterItem* item = dynamic_cast<ContactRosterItem*>(dynamic_cast<GroupRosterItem*>(getUIRosterChildren()[0])->getChildren()[0]); + CPPUNIT_ASSERT(item); + + Presence::ref low = presenceOracle_->getAccountPresence(from); + + CPPUNIT_ASSERT_EQUAL(Presence::Available, low->getType()); + CPPUNIT_ASSERT_EQUAL(lowPresence->getStatus(), low->getStatus()); + CPPUNIT_ASSERT_EQUAL(lowPresence->getShow(), item->getStatusShow()); + CPPUNIT_ASSERT_EQUAL(lowPresence->getStatus(), item->getStatusText()); + stanzaChannel_->onPresenceReceived(lowPresenceOffline); + item = dynamic_cast<ContactRosterItem*>(dynamic_cast<GroupRosterItem*>(getUIRosterChildren()[0])->getChildren()[0]); + CPPUNIT_ASSERT(item); + /* A verification that if the test fails, it's the RosterController, not the PresenceOracle. */ + low = presenceOracle_->getHighestPriorityPresence(from); + CPPUNIT_ASSERT_EQUAL(Presence::Unavailable, low->getType()); + CPPUNIT_ASSERT_EQUAL(lowPresenceOffline->getStatus(), low->getStatus()); + CPPUNIT_ASSERT_EQUAL(StatusShow::None, item->getStatusShow()); + CPPUNIT_ASSERT_EQUAL(lowPresenceOffline->getStatus(), item->getStatusText()); + } + + void testAdd() { + std::vector<std::string> groups; + groups.push_back("testGroup1"); + groups.push_back("testGroup2"); + xmppRoster_->addContact(JID("test@testdomain.com/bob"), "name", groups, RosterItemPayload::Both); + + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(getUIRosterChildren().size())); + //CPPUNIT_ASSERT_EQUAL(std::string("Bob"), xmppRoster_->getNameForJID(JID("foo@bar.com"))); + } + + void testAddSubscription() { + std::vector<std::string> groups; + JID jid("test@testdomain.com"); + xmppRoster_->addContact(jid, "name", groups, RosterItemPayload::None); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(getUIRosterChildren().size())); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(groupChild(0)->getChildren().size())); + xmppRoster_->addContact(jid, "name", groups, RosterItemPayload::To); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(getUIRosterChildren().size())); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(groupChild(0)->getChildren().size())); + + xmppRoster_->addContact(jid, "name", groups, RosterItemPayload::Both); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(getUIRosterChildren().size())); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(groupChild(0)->getChildren().size())); + + } + + void testReceiveRename() { + std::vector<std::string> groups; + JID jid("test@testdomain.com"); + xmppRoster_->addContact(jid, "name", groups, RosterItemPayload::Both); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(getUIRosterChildren().size())); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(groupChild(0)->getChildren().size())); + CPPUNIT_ASSERT_EQUAL(std::string("name"), groupChild(0)->getChildren()[0]->getDisplayName()); + xmppRoster_->addContact(jid, "NewName", groups, RosterItemPayload::Both); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(getUIRosterChildren().size())); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(groupChild(0)->getChildren().size())); + CPPUNIT_ASSERT_EQUAL(std::string("NewName"), groupChild(0)->getChildren()[0]->getDisplayName()); + } + + void testReceiveRegroup() { + std::vector<std::string> oldGroups; + std::vector<std::string> newGroups; + newGroups.push_back("A Group"); + std::vector<std::string> newestGroups; + newestGroups.push_back("Best Group"); + JID jid("test@testdomain.com"); + xmppRoster_->addContact(jid, "", oldGroups, RosterItemPayload::Both); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(getUIRosterChildren().size())); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(groupChild(0)->getChildren().size())); + CPPUNIT_ASSERT_EQUAL(jid.toString(), groupChild(0)->getChildren()[0]->getDisplayName()); + + xmppRoster_->addContact(jid, "new name", newGroups, RosterItemPayload::Both); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(getUIRosterChildren().size())); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(groupChild(0)->getChildren().size())); + CPPUNIT_ASSERT_EQUAL(std::string("new name"), groupChild(0)->getChildren()[0]->getDisplayName()); + CPPUNIT_ASSERT_EQUAL(std::string("A Group"), groupChild(0)->getDisplayName()); + + xmppRoster_->addContact(jid, "new name", newestGroups, RosterItemPayload::Both); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(getUIRosterChildren().size())); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(groupChild(0)->getChildren().size())); + CPPUNIT_ASSERT_EQUAL(std::string("new name"), groupChild(0)->getChildren()[0]->getDisplayName()); + CPPUNIT_ASSERT_EQUAL(std::string("Best Group"), groupChild(0)->getDisplayName()); + } + + void testSendRename() { + JID jid("testling@wonderland.lit"); + std::vector<std::string> groups; + groups.push_back("Friends"); + groups.push_back("Enemies"); + xmppRoster_->addContact(jid, "Bob", groups, RosterItemPayload::From); + CPPUNIT_ASSERT_EQUAL(groups.size(), xmppRoster_->getGroupsForJID(jid).size()); + uiEventStream_->send(std::make_shared<RenameRosterItemUIEvent>(jid, "Robert")); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), channel_->iqs_.size()); + CPPUNIT_ASSERT_EQUAL(IQ::Set, channel_->iqs_[0]->getType()); + std::shared_ptr<RosterPayload> payload = channel_->iqs_[0]->getPayload<RosterPayload>(); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), payload->getItems().size()); + RosterItemPayload item = payload->getItems()[0]; + CPPUNIT_ASSERT_EQUAL(jid, item.getJID()); + CPPUNIT_ASSERT_EQUAL(std::string("Robert"), item.getName()); + + CPPUNIT_ASSERT_EQUAL(groups.size(), item.getGroups().size()); + assertVectorsEqual(groups, item.getGroups(), __LINE__); + } + + void testRemoveResultsInUnavailablePresence() { + std::vector<std::string> groups; + groups.push_back("testGroup1"); + JID from("test@testdomain.com"); + xmppRoster_->addContact(from, "name", groups, RosterItemPayload::Both); + Presence::ref lowPresence(new Presence()); + lowPresence->setFrom(withResource(from, "bob")); + lowPresence->setPriority(2); + lowPresence->setStatus("Not here"); + Presence::ref highPresence(new Presence()); + highPresence->setFrom(withResource(from, "bert")); + highPresence->setPriority(10); + highPresence->setStatus("So totally here"); + stanzaChannel_->onPresenceReceived(highPresence); + stanzaChannel_->onPresenceReceived(lowPresence); + + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), presenceOracle_->getAllPresence("test@testdomain.com").size()); + + xmppRoster_->onJIDRemoved(JID("test@testdomain.com")); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), presenceOracle_->getAllPresence("test@testdomain.com").size()); + CPPUNIT_ASSERT_EQUAL(Presence::Unavailable, presenceOracle_->getAllPresence("test@testdomain.com")[0]->getType()); + } + + void testOwnContactInRosterPresence() { + std::vector<std::string> groups; + groups.push_back("testGroup1"); + groups.push_back("testGroup2"); + JID from = jid_; + xmppRoster_->addContact(from.toBare(), "name", groups, RosterItemPayload::Both); + Presence::ref presence(new Presence()); + presence->setFrom(from); + presence->setPriority(2); + presence->setStatus("So totally here"); + stanzaChannel_->onPresenceReceived(presence); + ContactRosterItem* item = dynamic_cast<ContactRosterItem*>(dynamic_cast<GroupRosterItem*>(getUIRosterChildren()[0])->getChildren()[0]); + CPPUNIT_ASSERT(item); + CPPUNIT_ASSERT_EQUAL(presence->getStatus(), item->getStatusText()); + ContactRosterItem* item2 = dynamic_cast<ContactRosterItem*>(dynamic_cast<GroupRosterItem*>(getUIRosterChildren()[1])->getChildren()[0]); + CPPUNIT_ASSERT(item2); + CPPUNIT_ASSERT_EQUAL(presence->getStatus(), item2->getStatusText()); + } + + // This tests a scenario of a contact having a resource supporting Jingle File Transfer and + // one resource not supporting it, and the contact features being set correctly. + void testMultiResourceFileTransferFeature() { + JID contact("test@testdomain.com"); + xmppRoster_->addContact(contact, "Name", {}, RosterItemPayload::Both); + + auto sendPresenceAndAnswerCaps = [=](const JID& from, const DiscoInfo& discoInfo) { + auto capsInfo = capsInfoGenerator_->generateCapsInfo(discoInfo); + + auto ftClientPresence = std::make_shared<Presence>(); + ftClientPresence->setFrom(from); + ftClientPresence->setPriority(0); + ftClientPresence->setShow(StatusShow::Online); + ftClientPresence->addPayload(std::make_shared<CapsInfo>(capsInfo)); + stanzaChannel_->onPresenceReceived(ftClientPresence); + + // disco reply + auto discoRequest = channel_->iqs_.back(); + CPPUNIT_ASSERT(discoRequest); + auto discoReply = IQ::createResult(discoRequest->getFrom(), ftClientPresence->getFrom(), discoRequest->getID(), std::make_shared<DiscoInfo>(discoInfo)); + channel_->onIQReceived(discoReply); + }; + + auto ftDiscoInfo = DiscoInfo(); + ftDiscoInfo.addFeature(DiscoInfo::JingleFeature); + ftDiscoInfo.addFeature(DiscoInfo::JingleFTFeature); + ftDiscoInfo.addFeature(DiscoInfo::JingleTransportsIBBFeature); + + sendPresenceAndAnswerCaps(contact.withResource("ft-supported"), ftDiscoInfo); + + auto* item = dynamic_cast<ContactRosterItem*>(dynamic_cast<GroupRosterItem*>(getUIRosterChildren()[0])->getChildren()[0]); + CPPUNIT_ASSERT(item); + CPPUNIT_ASSERT_EQUAL(contact, item->getJID()); + CPPUNIT_ASSERT_EQUAL(true, item->supportsFeature(ContactRosterItem::FileTransferFeature)); + + sendPresenceAndAnswerCaps(contact.withResource("ft-unsupported"), DiscoInfo()); + + item = dynamic_cast<ContactRosterItem*>(dynamic_cast<GroupRosterItem*>(getUIRosterChildren()[0])->getChildren()[0]); + CPPUNIT_ASSERT(item); + CPPUNIT_ASSERT_EQUAL(contact, item->getJID()); + CPPUNIT_ASSERT_EQUAL(true, item->supportsFeature(ContactRosterItem::FileTransferFeature)); + + auto unavailablePresence = std::make_shared<Presence>(); + unavailablePresence->setFrom(contact.withResource("ft-unsupported")); + unavailablePresence->setPriority(0); + unavailablePresence->setType(Presence::Unavailable); + stanzaChannel_->onPresenceReceived(unavailablePresence); + + item = dynamic_cast<ContactRosterItem*>(dynamic_cast<GroupRosterItem*>(getUIRosterChildren()[0])->getChildren()[0]); + CPPUNIT_ASSERT(item); + CPPUNIT_ASSERT_EQUAL(contact, item->getJID()); + CPPUNIT_ASSERT_EQUAL(true, item->supportsFeature(ContactRosterItem::FileTransferFeature)); + + unavailablePresence = std::make_shared<Presence>(); + unavailablePresence->setFrom(contact.withResource("ft-supported")); + unavailablePresence->setPriority(0); + unavailablePresence->setType(Presence::Unavailable); + stanzaChannel_->onPresenceReceived(unavailablePresence); + + item = dynamic_cast<ContactRosterItem*>(dynamic_cast<GroupRosterItem*>(getUIRosterChildren()[0])->getChildren()[0]); + CPPUNIT_ASSERT(item); + CPPUNIT_ASSERT_EQUAL(contact, item->getJID()); + CPPUNIT_ASSERT_EQUAL(false, item->supportsFeature(ContactRosterItem::FileTransferFeature)); + } + + void assertVectorsEqual(const std::vector<std::string>& v1, const std::vector<std::string>& v2, int line) { + for (const auto& entry : v1) { + if (std::find(v2.begin(), v2.end(), entry) == v2.end()) { + std::stringstream stream; + stream << "Couldn't find " << entry << " in v2 (line " << line << ")"; + CPPUNIT_FAIL(stream.str()); + } + } + } + + const std::vector<RosterItem*>& getUIRosterChildren() const { + return mainWindow_->roster->getRoot()->getChildren(); + } + + private: + JID jid_; + std::unique_ptr<MemoryStorages> storages_; + XMPPRosterImpl* xmppRoster_; + MUCRegistry* mucRegistry_; + AvatarManager* avatarManager_; + MockMainWindowFactory* mainWindowFactory_; + NickManager* nickManager_; + NickResolver* nickResolver_; + RosterController* rosterController_; + DummyIQChannel* channel_; + DummyStanzaChannel* stanzaChannel_; + IQRouter* router_; + PresenceOracle* presenceOracle_; + SubscriptionManager* subscriptionManager_; + EventController* eventController_; + UIEventStream* uiEventStream_; + MockMainWindow* mainWindow_; + DummySettingsProvider* settings_; + std::unique_ptr<CapsManager> capsManager_; + EntityCapsManager* entityCapsManager_; + JingleSessionManager* jingleSessionManager_; + ClientBlockListManager* clientBlockListManager_; + CryptoProvider* crypto_; + VCardStorage* vcardStorage_; + VCardManager* vcardManager_; + std::unique_ptr<CapsInfoGenerator> capsInfoGenerator_; }; CPPUNIT_TEST_SUITE_REGISTRATION(RosterControllerTest); diff --git a/Swift/Controllers/Roster/UnitTest/RosterTest.cpp b/Swift/Controllers/Roster/UnitTest/RosterTest.cpp index d905d9f..5f500d4 100644 --- a/Swift/Controllers/Roster/UnitTest/RosterTest.cpp +++ b/Swift/Controllers/Roster/UnitTest/RosterTest.cpp @@ -1,145 +1,141 @@ /* - * Copyright (c) 2010 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ +#include <memory> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <boost/shared_ptr.hpp> - -#include <Swift/Controllers/Roster/Roster.h> #include <Swift/Controllers/Roster/GroupRosterItem.h> #include <Swift/Controllers/Roster/ItemOperations/SetPresence.h> +#include <Swift/Controllers/Roster/Roster.h> using namespace Swift; class RosterTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(RosterTest); - CPPUNIT_TEST(testGetGroup); - CPPUNIT_TEST(testRemoveContact); - CPPUNIT_TEST(testRemoveSecondContact); - CPPUNIT_TEST(testRemoveSecondContactSameBare); - CPPUNIT_TEST(testApplyPresenceLikeMUC); - CPPUNIT_TEST(testReSortLikeMUC); - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - jid1_ = JID("a@b.c"); - jid2_ = JID("b@c.d"); - jid3_ = JID("c@d.e"); - roster_ = new Roster(); - } - - void tearDown() { - delete roster_; - } - - void testGetGroup() { - roster_->addContact(jid1_, JID(), "Bert", "group1", ""); - roster_->addContact(jid2_, JID(), "Ernie", "group2", ""); - roster_->addContact(jid3_, JID(), "Cookie", "group1", ""); - - CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(roster_->getRoot()->getChildren().size())); - CPPUNIT_ASSERT_EQUAL(std::string("group1"), roster_->getRoot()->getChildren()[0]->getDisplayName()); - CPPUNIT_ASSERT_EQUAL(std::string("group2"), roster_->getRoot()->getChildren()[1]->getDisplayName()); - CPPUNIT_ASSERT_EQUAL(std::string("Bert"), static_cast<GroupRosterItem*>(roster_->getRoot()->getChildren()[0])->getChildren()[0]->getDisplayName()); - CPPUNIT_ASSERT_EQUAL(std::string("Cookie"), static_cast<GroupRosterItem*>(roster_->getRoot()->getChildren()[0])->getChildren()[1]->getDisplayName()); - CPPUNIT_ASSERT_EQUAL(std::string("Ernie"), static_cast<GroupRosterItem*>(roster_->getRoot()->getChildren()[1])->getChildren()[0]->getDisplayName()); - - } - - void testRemoveContact() { - roster_->addContact(jid1_, jid1_, "Bert", "group1", ""); - CPPUNIT_ASSERT_EQUAL(std::string("Bert"), static_cast<GroupRosterItem*>(roster_->getRoot()->getChildren()[0])->getChildren()[0]->getDisplayName()); - - roster_->removeContact(jid1_); - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(static_cast<GroupRosterItem*>(roster_->getRoot()->getChildren()[0])->getChildren().size())); - } - - void testRemoveSecondContact() { - roster_->addContact(jid1_, jid1_, "Bert", "group1", ""); - roster_->addContact(jid2_, jid2_, "Cookie", "group1", ""); - CPPUNIT_ASSERT_EQUAL(std::string("Cookie"), static_cast<GroupRosterItem*>(roster_->getRoot()->getChildren()[0])->getChildren()[1]->getDisplayName()); - - roster_->removeContact(jid2_); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(static_cast<GroupRosterItem*>(roster_->getRoot()->getChildren()[0])->getChildren().size())); - CPPUNIT_ASSERT_EQUAL(std::string("Bert"), static_cast<GroupRosterItem*>(roster_->getRoot()->getChildren()[0])->getChildren()[0]->getDisplayName()); - } - - void testRemoveSecondContactSameBare() { - JID jid4a("a@b/c"); - JID jid4b("a@b/d"); - roster_->addContact(jid4a, JID(), "Bert", "group1", ""); - roster_->addContact(jid4b, JID(), "Cookie", "group1", ""); - CPPUNIT_ASSERT_EQUAL(std::string("Cookie"), static_cast<GroupRosterItem*>(roster_->getRoot()->getChildren()[0])->getChildren()[1]->getDisplayName()); - - roster_->removeContact(jid4b); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(static_cast<GroupRosterItem*>(roster_->getRoot()->getChildren()[0])->getChildren().size())); - CPPUNIT_ASSERT_EQUAL(std::string("Bert"), static_cast<GroupRosterItem*>(roster_->getRoot()->getChildren()[0])->getChildren()[0]->getDisplayName()); - } - - void testApplyPresenceLikeMUC() { - JID jid4a("a@b/c"); - JID jid4b("a@b/d"); - JID jid4c("a@b/e"); - roster_->addContact(jid4a, JID(), "Bird", "group1", ""); - roster_->addContact(jid4b, JID(), "Cookie", "group1", ""); - roster_->removeContact(jid4b); - roster_->addContact(jid4c, JID(), "Bert", "group1", ""); - roster_->addContact(jid4b, JID(), "Ernie", "group1", ""); - boost::shared_ptr<Presence> presence(new Presence()); - presence->setShow(StatusShow::DND); - presence->setFrom(jid4a); - roster_->applyOnItems(SetPresence(presence, JID::WithResource)); - presence->setFrom(jid4b); - roster_->applyOnItems(SetPresence(presence, JID::WithResource)); - presence->setFrom(jid4c); - roster_->applyOnItems(SetPresence(presence, JID::WithResource)); - - presence = boost::make_shared<Presence>(); - presence->setFrom(jid4b); - presence->setShow(StatusShow::Online); - roster_->applyOnItems(SetPresence(presence, JID::WithResource)); - std::vector<RosterItem*> children = static_cast<GroupRosterItem*>(roster_->getRoot()->getDisplayedChildren()[0])->getDisplayedChildren(); - CPPUNIT_ASSERT_EQUAL(3, static_cast<int>(children.size())); - - /* Check order */ - CPPUNIT_ASSERT_EQUAL(std::string("Ernie"), children[0]->getDisplayName()); - CPPUNIT_ASSERT_EQUAL(std::string("Bert"), children[1]->getDisplayName()); - CPPUNIT_ASSERT_EQUAL(std::string("Bird"), children[2]->getDisplayName()); - - presence = boost::make_shared<Presence>(); - presence->setFrom(jid4c); - presence->setType(Presence::Unavailable); - roster_->removeContact(jid4c); - roster_->applyOnItems(SetPresence(presence, JID::WithResource)); - - } - - void testReSortLikeMUC() { - JID jid4a("a@b/c"); - JID jid4b("a@b/d"); - JID jid4c("a@b/e"); - roster_->addContact(jid4a, JID(), "Bird", "group1", ""); - roster_->addContact(jid4b, JID(), "Cookie", "group2", ""); - roster_->addContact(jid4b, JID(), "Ernie", "group1", ""); - roster_->getGroup("group1")->setManualSort("2"); - roster_->getGroup("group2")->setManualSort("1"); - GroupRosterItem* root = roster_->getRoot(); - const std::vector<RosterItem*> kids = root->getDisplayedChildren(); - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), kids.size()); - CPPUNIT_ASSERT_EQUAL(std::string("group2"), kids[0]->getDisplayName()); - CPPUNIT_ASSERT_EQUAL(std::string("group1"), kids[1]->getDisplayName()); - } - - private: - Roster *roster_; - JID jid1_; - JID jid2_; - JID jid3_; + CPPUNIT_TEST_SUITE(RosterTest); + CPPUNIT_TEST(testGetGroup); + CPPUNIT_TEST(testRemoveContact); + CPPUNIT_TEST(testRemoveSecondContact); + CPPUNIT_TEST(testRemoveSecondContactSameBare); + CPPUNIT_TEST(testApplyPresenceLikeMUC); + CPPUNIT_TEST(testReSortLikeMUC); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + jid1_ = JID("a@b.c"); + jid2_ = JID("b@c.d"); + jid3_ = JID("c@d.e"); + roster_ = std::unique_ptr<Roster>(new Roster()); + } + + void testGetGroup() { + roster_->addContact(jid1_, JID(), "Bert", "group1", ""); + roster_->addContact(jid2_, JID(), "Ernie", "group2", ""); + roster_->addContact(jid3_, JID(), "Cookie", "group1", ""); + + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(roster_->getRoot()->getChildren().size())); + CPPUNIT_ASSERT_EQUAL(std::string("group1"), roster_->getRoot()->getChildren()[0]->getDisplayName()); + CPPUNIT_ASSERT_EQUAL(std::string("group2"), roster_->getRoot()->getChildren()[1]->getDisplayName()); + CPPUNIT_ASSERT_EQUAL(std::string("Bert"), static_cast<GroupRosterItem*>(roster_->getRoot()->getChildren()[0])->getChildren()[0]->getDisplayName()); + CPPUNIT_ASSERT_EQUAL(std::string("Cookie"), static_cast<GroupRosterItem*>(roster_->getRoot()->getChildren()[0])->getChildren()[1]->getDisplayName()); + CPPUNIT_ASSERT_EQUAL(std::string("Ernie"), static_cast<GroupRosterItem*>(roster_->getRoot()->getChildren()[1])->getChildren()[0]->getDisplayName()); + + } + + void testRemoveContact() { + roster_->addContact(jid1_, jid1_, "Bert", "group1", ""); + CPPUNIT_ASSERT_EQUAL(std::string("Bert"), static_cast<GroupRosterItem*>(roster_->getRoot()->getChildren()[0])->getChildren()[0]->getDisplayName()); + + roster_->removeContact(jid1_); + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(static_cast<GroupRosterItem*>(roster_->getRoot()->getChildren()[0])->getChildren().size())); + } + + void testRemoveSecondContact() { + roster_->addContact(jid1_, jid1_, "Bert", "group1", ""); + roster_->addContact(jid2_, jid2_, "Cookie", "group1", ""); + CPPUNIT_ASSERT_EQUAL(std::string("Cookie"), static_cast<GroupRosterItem*>(roster_->getRoot()->getChildren()[0])->getChildren()[1]->getDisplayName()); + + roster_->removeContact(jid2_); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(static_cast<GroupRosterItem*>(roster_->getRoot()->getChildren()[0])->getChildren().size())); + CPPUNIT_ASSERT_EQUAL(std::string("Bert"), static_cast<GroupRosterItem*>(roster_->getRoot()->getChildren()[0])->getChildren()[0]->getDisplayName()); + } + + void testRemoveSecondContactSameBare() { + JID jid4a("a@b/c"); + JID jid4b("a@b/d"); + roster_->addContact(jid4a, JID(), "Bert", "group1", ""); + roster_->addContact(jid4b, JID(), "Cookie", "group1", ""); + CPPUNIT_ASSERT_EQUAL(std::string("Cookie"), static_cast<GroupRosterItem*>(roster_->getRoot()->getChildren()[0])->getChildren()[1]->getDisplayName()); + + roster_->removeContact(jid4b); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(static_cast<GroupRosterItem*>(roster_->getRoot()->getChildren()[0])->getChildren().size())); + CPPUNIT_ASSERT_EQUAL(std::string("Bert"), static_cast<GroupRosterItem*>(roster_->getRoot()->getChildren()[0])->getChildren()[0]->getDisplayName()); + } + + void testApplyPresenceLikeMUC() { + JID jid4a("a@b/c"); + JID jid4b("a@b/d"); + JID jid4c("a@b/e"); + roster_->addContact(jid4a, JID(), "Bird", "group1", ""); + roster_->addContact(jid4b, JID(), "Cookie", "group1", ""); + roster_->removeContact(jid4b); + roster_->addContact(jid4c, JID(), "Bert", "group1", ""); + roster_->addContact(jid4b, JID(), "Ernie", "group1", ""); + std::shared_ptr<Presence> presence(new Presence()); + presence->setShow(StatusShow::DND); + presence->setFrom(jid4a); + roster_->applyOnItems(SetPresence(presence, JID::WithResource)); + presence->setFrom(jid4b); + roster_->applyOnItems(SetPresence(presence, JID::WithResource)); + presence->setFrom(jid4c); + roster_->applyOnItems(SetPresence(presence, JID::WithResource)); + + presence = std::make_shared<Presence>(); + presence->setFrom(jid4b); + presence->setShow(StatusShow::Online); + roster_->applyOnItems(SetPresence(presence, JID::WithResource)); + std::vector<RosterItem*> children = static_cast<GroupRosterItem*>(roster_->getRoot()->getDisplayedChildren()[0])->getDisplayedChildren(); + CPPUNIT_ASSERT_EQUAL(3, static_cast<int>(children.size())); + + /* Check order */ + CPPUNIT_ASSERT_EQUAL(std::string("Ernie"), children[0]->getDisplayName()); + CPPUNIT_ASSERT_EQUAL(std::string("Bert"), children[1]->getDisplayName()); + CPPUNIT_ASSERT_EQUAL(std::string("Bird"), children[2]->getDisplayName()); + + presence = std::make_shared<Presence>(); + presence->setFrom(jid4c); + presence->setType(Presence::Unavailable); + roster_->removeContact(jid4c); + roster_->applyOnItems(SetPresence(presence, JID::WithResource)); + + } + + void testReSortLikeMUC() { + JID jid4a("a@b/c"); + JID jid4b("a@b/d"); + JID jid4c("a@b/e"); + roster_->addContact(jid4a, JID(), "Bird", "group1", ""); + roster_->addContact(jid4b, JID(), "Cookie", "group2", ""); + roster_->addContact(jid4b, JID(), "Ernie", "group1", ""); + roster_->getGroup("group1")->setManualSort("2"); + roster_->getGroup("group2")->setManualSort("1"); + GroupRosterItem* root = roster_->getRoot(); + const std::vector<RosterItem*> kids = root->getDisplayedChildren(); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), kids.size()); + CPPUNIT_ASSERT_EQUAL(std::string("group2"), kids[0]->getDisplayName()); + CPPUNIT_ASSERT_EQUAL(std::string("group1"), kids[1]->getDisplayName()); + } + + private: + std::unique_ptr<Roster> roster_; + JID jid1_; + JID jid2_; + JID jid3_; }; CPPUNIT_TEST_SUITE_REGISTRATION(RosterTest); diff --git a/Swift/Controllers/Roster/UnitTest/TableRosterTest.cpp b/Swift/Controllers/Roster/UnitTest/TableRosterTest.cpp index 10030ef..ddc8785 100644 --- a/Swift/Controllers/Roster/UnitTest/TableRosterTest.cpp +++ b/Swift/Controllers/Roster/UnitTest/TableRosterTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -9,14 +9,15 @@ std::ostream& operator<<(std::ostream& os, const Swift::TableRoster::Index& i); std::ostream& operator<<(std::ostream& os, const Swift::TableRoster::Index& i) { - os << "(" << i.section << ", " << i.row << ")"; - return os; + os << "(" << i.section << ", " << i.row << ")"; + return os; } +#include <memory> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <boost/shared_ptr.hpp> #include <boost/variant.hpp> #include <Swiften/Network/DummyTimerFactory.h> @@ -27,67 +28,62 @@ std::ostream& operator<<(std::ostream& os, const Swift::TableRoster::Index& i) { using namespace Swift; class TableRosterTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(TableRosterTest); - CPPUNIT_TEST(testAddContact_EmptyRoster); - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - timerFactory = new DummyTimerFactory(); - roster = new Roster(); - jid1 = JID("jid1@example.com"); - jid2 = JID("jid2@example.com"); - } - - void tearDown() { - delete roster; - delete timerFactory; - } - - void testAddContact_EmptyRoster() { - /* - boost::shared_ptr<TableRoster> tableRoster(createTestling()); - - addContact(jid1, "1", "group1"); - - CPPUNIT_ASSERT_EQUAL(4, static_cast<int>(events.size())); - CPPUNIT_ASSERT(boost::get<BeginUpdatesEvent>(&events[0])); - CPPUNIT_ASSERT(boost::get<SectionsInsertedEvent>(&events[1])); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(boost::get<SectionsInsertedEvent>(events[1]).sections.size())); - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(boost::get<SectionsInsertedEvent>(events[1]).sections[0])); - CPPUNIT_ASSERT(boost::get<RowsInsertedEvent>(&events[2])); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(boost::get<RowsInsertedEvent>(events[2]).rows.size())); - CPPUNIT_ASSERT_EQUAL(TableRoster::Index(0, 0), boost::get<RowsInsertedEvent>(events[2]).rows[0]); - CPPUNIT_ASSERT(boost::get<EndUpdatesEvent>(&events[3])); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(tableRoster->getNumberOfSections())); - CPPUNIT_ASSERT_EQUAL(std::string("group1"), tableRoster->getSectionTitle(0)); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(tableRoster->getNumberOfRowsInSection(0))); - CPPUNIT_ASSERT_EQUAL(jid1, tableRoster->getItem(TableRoster::Index(0, 0)).jid); - */ - } - - private: - void addContact(const JID& jid, const std::string& name, const std::string& group) { - roster->addContact(jid, JID(), name, group, ""); - } - - TableRoster* createTestling() { - TableRoster* result = new TableRoster(roster, timerFactory, 10); - result->onUpdate.connect(boost::bind(&TableRosterTest::handleUpdate, this, _1)); - return result; - } - - void handleUpdate(const TableRoster::Update& update) { - updates.push_back(update); - } - - private: - DummyTimerFactory* timerFactory; - Roster* roster; - JID jid1; - JID jid2; - std::vector<TableRoster::Update> updates; + CPPUNIT_TEST_SUITE(TableRosterTest); + CPPUNIT_TEST(testAddContact_EmptyRoster); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + timerFactory = std::unique_ptr<DummyTimerFactory>(new DummyTimerFactory()); + roster = std::unique_ptr<Roster>(new Roster()); + jid1 = JID("jid1@example.com"); + jid2 = JID("jid2@example.com"); + } + + void testAddContact_EmptyRoster() { + /* + std::shared_ptr<TableRoster> tableRoster(createTestling()); + + addContact(jid1, "1", "group1"); + + CPPUNIT_ASSERT_EQUAL(4, static_cast<int>(events.size())); + CPPUNIT_ASSERT(boost::get<BeginUpdatesEvent>(&events[0])); + CPPUNIT_ASSERT(boost::get<SectionsInsertedEvent>(&events[1])); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(boost::get<SectionsInsertedEvent>(events[1]).sections.size())); + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(boost::get<SectionsInsertedEvent>(events[1]).sections[0])); + CPPUNIT_ASSERT(boost::get<RowsInsertedEvent>(&events[2])); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(boost::get<RowsInsertedEvent>(events[2]).rows.size())); + CPPUNIT_ASSERT_EQUAL(TableRoster::Index(0, 0), boost::get<RowsInsertedEvent>(events[2]).rows[0]); + CPPUNIT_ASSERT(boost::get<EndUpdatesEvent>(&events[3])); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(tableRoster->getNumberOfSections())); + CPPUNIT_ASSERT_EQUAL(std::string("group1"), tableRoster->getSectionTitle(0)); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(tableRoster->getNumberOfRowsInSection(0))); + CPPUNIT_ASSERT_EQUAL(jid1, tableRoster->getItem(TableRoster::Index(0, 0)).jid); + */ + } + + private: + void addContact(const JID& jid, const std::string& name, const std::string& group) { + roster->addContact(jid, JID(), name, group, ""); + } + + TableRoster* createTestling() { + TableRoster* result = new TableRoster(roster.get(), timerFactory.get(), 10); + result->onUpdate.connect(boost::bind(&TableRosterTest::handleUpdate, this, _1)); + return result; + } + + void handleUpdate(const TableRoster::Update& update) { + updates.push_back(update); + } + + private: + std::unique_ptr<DummyTimerFactory> timerFactory; + std::unique_ptr<Roster> roster; + JID jid1; + JID jid2; + std::vector<TableRoster::Update> updates; }; CPPUNIT_TEST_SUITE_REGISTRATION(TableRosterTest); |