diff options
Diffstat (limited to 'Swift/Controllers/Roster')
24 files changed, 720 insertions, 189 deletions
diff --git a/Swift/Controllers/Roster/ContactRosterItem.cpp b/Swift/Controllers/Roster/ContactRosterItem.cpp index 8c388bf..e0651bc 100644 --- a/Swift/Controllers/Roster/ContactRosterItem.cpp +++ b/Swift/Controllers/Roster/ContactRosterItem.cpp @@ -5,13 +5,20 @@ */ -#include "Swift/Controllers/Roster/ContactRosterItem.h" -#include "Swift/Controllers/Roster/GroupRosterItem.h" +#include <Swift/Controllers/Roster/ContactRosterItem.h> + +#include <boost/date_time/posix_time/posix_time.hpp> #include <Swiften/Base/foreach.h> +#include <Swiften/Base/DateTime.h> +#include <Swiften/Elements/Idle.h> +#include <Swift/Controllers/Intl.h> +#include <Swift/Controllers/Roster/GroupRosterItem.h> namespace Swift { -ContactRosterItem::ContactRosterItem(const JID& jid, const JID& displayJID, const std::string& name, GroupRosterItem* parent) : RosterItem(name, parent), jid_(jid), displayJID_(displayJID) { +ContactRosterItem::ContactRosterItem(const JID& jid, const JID& displayJID, const std::string& name, GroupRosterItem* parent) +: RosterItem(name, parent), jid_(jid), displayJID_(displayJID.toBare()), mucRole_(MUCOccupant::NoRole), mucAffiliation_(MUCOccupant::NoAffiliation), blockState_(BlockingNotSupported) +{ } @@ -25,10 +32,10 @@ StatusShow::Type ContactRosterItem::getStatusShow() const { StatusShow::Type ContactRosterItem::getSimplifiedStatusShow() const { switch (shownPresence_ ? shownPresence_->getShow() : StatusShow::None) { - case StatusShow::Online: return StatusShow::Online; break; - case StatusShow::Away: return StatusShow::Away; break; - case StatusShow::XA: return StatusShow::Away; break; - case StatusShow::FFC: return StatusShow::Online; break; - case StatusShow::DND: return StatusShow::DND; break; - case StatusShow::None: return StatusShow::None; break; + 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); @@ -40,9 +47,28 @@ std::string ContactRosterItem::getStatusText() const { } -void ContactRosterItem::setAvatarPath(const std::string& path) { +std::string ContactRosterItem::getIdleText() const { + Idle::ref idle = shownPresence_ ? shownPresence_->getPayload<Idle>() : Idle::ref(); + if (!idle || idle->getSince().is_not_a_date_time()) { + return ""; + } else { + return dateTimeToLocalString(idle->getSince()); + } +} + +std::string ContactRosterItem::getOfflineSinceText() const { + if (offlinePresence_) { + boost::optional<boost::posix_time::ptime> delay = offlinePresence_->getTimestamp(); + if (offlinePresence_->getType() == Presence::Unavailable && delay) { + return dateTimeToLocalString(*delay); + } + } + return ""; +} + +void ContactRosterItem::setAvatarPath(const boost::filesystem::path& path) { avatarPath_ = path; onDataChanged(); } -const std::string& ContactRosterItem::getAvatarPath() const { +const boost::filesystem::path& ContactRosterItem::getAvatarPath() const { return avatarPath_; } @@ -114,6 +140,41 @@ void ContactRosterItem::removeGroup(const std::string& group) { } +MUCOccupant::Role ContactRosterItem::getMUCRole() const +{ + return mucRole_; +} + +void ContactRosterItem::setMUCRole(const MUCOccupant::Role& role) +{ + mucRole_ = role; +} + +MUCOccupant::Affiliation ContactRosterItem::getMUCAffiliation() const +{ + return mucAffiliation_; +} + +void ContactRosterItem::setMUCAffiliation(const MUCOccupant::Affiliation& 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; + } + + return affiliationString; +} + void ContactRosterItem::setSupportedFeatures(const std::set<Feature>& features) { features_ = features; + onDataChanged(); } @@ -122,5 +183,21 @@ bool ContactRosterItem::supportsFeature(const Feature feature) const { } +void ContactRosterItem::setBlockState(BlockState state) { + blockState_ = state; + onDataChanged(); } +ContactRosterItem::BlockState ContactRosterItem::blockState() const { + return blockState_; +} + +VCard::ref ContactRosterItem::getVCard() const { + return vcard_; +} +void ContactRosterItem::setVCard(VCard::ref vcard) { + vcard_ = vcard; + onDataChanged(); +} + +} diff --git a/Swift/Controllers/Roster/ContactRosterItem.h b/Swift/Controllers/Roster/ContactRosterItem.h index 9932dc4..ab10c66 100644 --- a/Swift/Controllers/Roster/ContactRosterItem.h +++ b/Swift/Controllers/Roster/ContactRosterItem.h @@ -1,4 +1,4 @@ /* - * Copyright (c) 2010 Kevin Smith + * Copyright (c) 2010-2013 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. @@ -7,16 +7,22 @@ #pragma once -#include <string> -#include "Swiften/JID/JID.h" -#include "Swift/Controllers/Roster/RosterItem.h" -#include "Swiften/Elements/StatusShow.h" -#include "Swiften/Elements/Presence.h" - #include <map> #include <set> +#include <string> + #include <boost/bind.hpp> -#include "Swiften/Base/boost_bsignals.h" +#include <boost/date_time/posix_time/ptime.hpp> +#include <boost/filesystem/path.hpp> #include <boost/shared_ptr.hpp> +#include <Swiften/Base/boost_bsignals.h> +#include <Swiften/Elements/Presence.h> +#include <Swiften/Elements/StatusShow.h> +#include <Swiften/Elements/MUCOccupant.h> +#include <Swiften/Elements/VCard.h> +#include <Swiften/JID/JID.h> + +#include <Swift/Controllers/Roster/RosterItem.h> + namespace Swift { @@ -26,4 +32,12 @@ class ContactRosterItem : public RosterItem { enum Feature { FileTransferFeature, + WhiteboardFeature + }; + + enum BlockState { + BlockingNotSupported, + IsBlocked, + IsUnblocked, + IsDomainBlocked }; @@ -35,6 +49,8 @@ class ContactRosterItem : public RosterItem { StatusShow::Type getSimplifiedStatusShow() const; std::string getStatusText() const; - void setAvatarPath(const std::string& path); - const std::string& getAvatarPath() 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); @@ -48,15 +64,35 @@ class ContactRosterItem : public RosterItem { void removeGroup(const std::string& group); + 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_; - std::string avatarPath_; + boost::posix_time::ptime lastAvailableTime_; + boost::filesystem::path avatarPath_; std::map<std::string, boost::shared_ptr<Presence> > presences_; boost::shared_ptr<Presence> offlinePresence_; boost::shared_ptr<Presence> shownPresence_; 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 new file mode 100644 index 0000000..6710084 --- /dev/null +++ b/Swift/Controllers/Roster/FuzzyRosterFilter.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2013 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt 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> + +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_; +}; + +} + + diff --git a/Swift/Controllers/Roster/AppearOffline.h b/Swift/Controllers/Roster/ItemOperations/AppearOffline.h index 8bd53d7..14beaa3 100644 --- a/Swift/Controllers/Roster/AppearOffline.h +++ b/Swift/Controllers/Roster/ItemOperations/AppearOffline.h @@ -7,5 +7,5 @@ #pragma once -#include <Swift/Controllers/Roster/RosterItemOperation.h> +#include <Swift/Controllers/Roster/ItemOperations/RosterItemOperation.h> #include <Swift/Controllers/Roster/ContactRosterItem.h> diff --git a/Swift/Controllers/Roster/RosterItemOperation.h b/Swift/Controllers/Roster/ItemOperations/RosterItemOperation.h index 691c8ef..f1dff8d 100644 --- a/Swift/Controllers/Roster/RosterItemOperation.h +++ b/Swift/Controllers/Roster/ItemOperations/RosterItemOperation.h @@ -13,8 +13,8 @@ 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_;}; + 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 diff --git a/Swift/Controllers/Roster/ItemOperations/SetAvailableFeatures.h b/Swift/Controllers/Roster/ItemOperations/SetAvailableFeatures.h new file mode 100644 index 0000000..620a1ae --- /dev/null +++ b/Swift/Controllers/Roster/ItemOperations/SetAvailableFeatures.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2013 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <Swiften/JID/JID.h> + +#include <Swift/Controllers/Roster/ItemOperations/RosterItemOperation.h> +#include <Swift/Controllers/Roster/ContactRosterItem.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_; +}; + +} diff --git a/Swift/Controllers/Roster/SetAvatar.h b/Swift/Controllers/Roster/ItemOperations/SetAvatar.h index 241b741..b3ec5f3 100644 --- a/Swift/Controllers/Roster/SetAvatar.h +++ b/Swift/Controllers/Roster/ItemOperations/SetAvatar.h @@ -1,4 +1,4 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. @@ -7,8 +7,11 @@ #pragma once -#include "Swiften/Elements/Presence.h" -#include "Swiften/JID/JID.h" -#include "Swift/Controllers/Roster/RosterItemOperation.h" -#include "Swift/Controllers/Roster/ContactRosterItem.h" +#include <boost/filesystem/path.hpp> + +#include <Swiften/Elements/Presence.h> +#include <Swiften/JID/JID.h> + +#include <Swift/Controllers/Roster/ItemOperations/RosterItemOperation.h> +#include <Swift/Controllers/Roster/ContactRosterItem.h> namespace Swift { @@ -18,5 +21,5 @@ class RosterItem; class SetAvatar : public RosterItemOperation { public: - SetAvatar(const JID& jid, const std::string& path, JID::CompareType compareType = JID::WithoutResource) : RosterItemOperation(true, jid), jid_(jid), path_(path), compareType_(compareType) { + SetAvatar(const JID& jid, const boost::filesystem::path& path, JID::CompareType compareType = JID::WithoutResource) : RosterItemOperation(true, jid), jid_(jid), path_(path), compareType_(compareType) { } @@ -30,5 +33,5 @@ class SetAvatar : public RosterItemOperation { private: JID jid_; - std::string path_; + boost::filesystem::path path_; JID::CompareType compareType_; }; diff --git a/Swift/Controllers/Roster/ItemOperations/SetBlockingState.h b/Swift/Controllers/Roster/ItemOperations/SetBlockingState.h new file mode 100644 index 0000000..ddb2c7a --- /dev/null +++ b/Swift/Controllers/Roster/ItemOperations/SetBlockingState.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2013 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <Swiften/JID/JID.h> + +#include <Swift/Controllers/Roster/ItemOperations/RosterItemOperation.h> +#include <Swift/Controllers/Roster/ContactRosterItem.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_; +}; + +} diff --git a/Swift/Controllers/Roster/ItemOperations/SetMUC.h b/Swift/Controllers/Roster/ItemOperations/SetMUC.h new file mode 100644 index 0000000..598e5f5 --- /dev/null +++ b/Swift/Controllers/Roster/ItemOperations/SetMUC.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2013-2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <Swiften/JID/JID.h> + +#include <Swift/Controllers/Roster/ItemOperations/RosterItemOperation.h> +#include <Swift/Controllers/Roster/ContactRosterItem.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_; +}; + +} diff --git a/Swift/Controllers/Roster/SetName.h b/Swift/Controllers/Roster/ItemOperations/SetName.h index aefb0dc..b21e4f2 100644 --- a/Swift/Controllers/Roster/SetName.h +++ b/Swift/Controllers/Roster/ItemOperations/SetName.h @@ -7,7 +7,8 @@ #pragma once -#include "Swiften/JID/JID.h" -#include "Swift/Controllers/Roster/RosterItemOperation.h" -#include "Swift/Controllers/Roster/ContactRosterItem.h" +#include <Swiften/JID/JID.h> + +#include <Swift/Controllers/Roster/ItemOperations/RosterItemOperation.h> +#include <Swift/Controllers/Roster/ContactRosterItem.h> namespace Swift { diff --git a/Swift/Controllers/Roster/SetPresence.h b/Swift/Controllers/Roster/ItemOperations/SetPresence.h index 06adfa4..b298a88 100644 --- a/Swift/Controllers/Roster/SetPresence.h +++ b/Swift/Controllers/Roster/ItemOperations/SetPresence.h @@ -7,8 +7,9 @@ #pragma once -#include "Swiften/Elements/Presence.h" -#include "Swiften/JID/JID.h" -#include "Swift/Controllers/Roster/RosterItemOperation.h" -#include "Swift/Controllers/Roster/ContactRosterItem.h" +#include <Swiften/Elements/Presence.h> +#include <Swiften/JID/JID.h> + +#include <Swift/Controllers/Roster/ItemOperations/RosterItemOperation.h> +#include <Swift/Controllers/Roster/ContactRosterItem.h> namespace Swift { diff --git a/Swift/Controllers/Roster/ItemOperations/SetVCard.h b/Swift/Controllers/Roster/ItemOperations/SetVCard.h new file mode 100644 index 0000000..8ee73f9 --- /dev/null +++ b/Swift/Controllers/Roster/ItemOperations/SetVCard.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2013 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt 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> + +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_; +}; + +} diff --git a/Swift/Controllers/Roster/LeastCommonSubsequence.h b/Swift/Controllers/Roster/LeastCommonSubsequence.h index dd3c95a..9d45679 100644 --- a/Swift/Controllers/Roster/LeastCommonSubsequence.h +++ b/Swift/Controllers/Roster/LeastCommonSubsequence.h @@ -1,4 +1,4 @@ /* - * Copyright (c) 2011 Remko Tronçon + * Copyright (c) 2011-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. @@ -8,4 +8,5 @@ #include <vector> +#include <boost/numeric/conversion/cast.hpp> namespace Swift { @@ -15,6 +16,6 @@ namespace Swift { 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 = std::distance(xBegin, xEnd) + 1; - size_t height = std::distance(yBegin, yEnd) + 1; + 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); @@ -31,5 +32,5 @@ namespace Swift { for (size_t i = 1; i < width; ++i) { for (size_t j = 1; j < height; ++j) { - result[i + j*width] = (predicate(*(xBegin + i-1), *(yBegin + j-1)) ? result[(i-1) + (j-1)*width] + 1 : std::max(result[i + (j-1)*width], result[i-1 + (j*width)])); + 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)]); } } @@ -47,11 +48,11 @@ namespace Swift { while (xBegin < x.end() && yBegin < y.end() && insertRemovePredicate(*xBegin, *yBegin)) { if (updatePredicate(*xBegin, *yBegin)) { - updates.push_back(std::distance(x.begin(), xBegin)); - postUpdates.push_back(std::distance(y.begin(), 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 = std::distance(x.begin(), xBegin); + size_t prefixLength = static_cast<size_t>(std::distance(x.begin(), xBegin)); // Find & handle common suffix (Optimization to reduce LCS matrix size) @@ -60,6 +61,6 @@ namespace Swift { while (xEnd.base() > xBegin && yEnd.base() > yBegin && insertRemovePredicate(*xEnd, *yEnd)) { if (updatePredicate(*xEnd, *yEnd)) { - updates.push_back(std::distance(x.begin(), xEnd.base()) - 1); - postUpdates.push_back(std::distance(y.begin(), yEnd.base()) - 1); + 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; @@ -68,6 +69,6 @@ namespace Swift { // Compute lengths - size_t xLength = std::distance(xBegin, xEnd.base()); - size_t yLength = std::distance(yBegin, yEnd.base()); + 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 @@ -78,5 +79,5 @@ namespace Swift { size_t i = xLength; size_t j = yLength; - const size_t width = xLength + 1; + size_t width = xLength + 1; while (true) { if (i > 0 && j > 0 && insertRemovePredicate(x[prefixLength + i-1], y[prefixLength + j-1])) { diff --git a/Swift/Controllers/Roster/Roster.cpp b/Swift/Controllers/Roster/Roster.cpp index 65cf4d2..4dbc453 100644 --- a/Swift/Controllers/Roster/Roster.cpp +++ b/Swift/Controllers/Roster/Roster.cpp @@ -1,27 +1,28 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ -#include "Swift/Controllers/Roster/Roster.h" +#include <Swift/Controllers/Roster/Roster.h> -#include "Swiften/Base/foreach.h" #include <string> -#include "Swiften/JID/JID.h" -#include "Swift/Controllers/Roster/ContactRosterItem.h" -#include "Swift/Controllers/Roster/RosterItem.h" -#include "Swift/Controllers/Roster/GroupRosterItem.h" -#include "Swift/Controllers/Roster/RosterItemOperation.h" - -#include <boost/bind.hpp> - #include <iostream> #include <set> #include <deque> +#include <boost/bind.hpp> + +#include <Swiften/Base/foreach.h> +#include <Swiften/JID/JID.h> + +#include <Swift/Controllers/Roster/ContactRosterItem.h> +#include <Swift/Controllers/Roster/RosterItem.h> +#include <Swift/Controllers/Roster/GroupRosterItem.h> +#include <Swift/Controllers/Roster/ItemOperations/RosterItemOperation.h> + namespace Swift { -Roster::Roster(bool sortByStatus, bool fullJIDMapping) { +Roster::Roster(bool sortByStatus, bool fullJIDMapping) : blockingSupported_(false) { sortByStatus_ = sortByStatus; fullJIDMapping_ = fullJIDMapping; @@ -40,4 +41,8 @@ Roster::~Roster() { 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; } @@ -62,12 +67,13 @@ GroupRosterItem* Roster::getGroup(const std::string& groupName) { } -void Roster::setAvailableFeatures(const JID& jid, const std::set<ContactRosterItem::Feature>& features) { - ItemMap::const_iterator i = itemMap_.find(fullJIDMapping_ ? jid : jid.toBare()); - if (i == itemMap_.end()) { - return; +void Roster::setBlockingSupported(bool isSupported) { + if (!blockingSupported_) { + foreach(ItemMap::value_type i, itemMap_) { + foreach(ContactRosterItem* item, i.second) { + item->setBlockState(ContactRosterItem::IsUnblocked); + } } - foreach(ContactRosterItem* item, i->second) { - item->setSupportedFeatures(features); } + blockingSupported_ = isSupported; } @@ -84,8 +90,12 @@ void Roster::handleChildrenChanged(GroupRosterItem* item) { } -void Roster::addContact(const JID& jid, const JID& displayJID, const std::string& name, const std::string& groupName, const std::string& avatarPath) { +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; @@ -188,4 +198,10 @@ void Roster::applyOnAllItems(const RosterItemOperation& operation) { } +void Roster::addFilter(RosterFilter* filter) { + filters_.push_back(filter); + filterAll(); + onFilterAdded(filter); +} + void Roster::removeFilter(RosterFilter* filter) { for (unsigned int i = 0; i < filters_.size(); i++) { @@ -196,8 +212,9 @@ void Roster::removeFilter(RosterFilter *filter) { } filterAll(); + onFilterRemoved(filter); } void Roster::filterContact(ContactRosterItem* contact, GroupRosterItem* group) { - int oldDisplayedSize = group->getDisplayedChildren().size(); + size_t oldDisplayedSize = group->getDisplayedChildren().size(); bool hide = true; foreach (RosterFilter *filter, filters_) { @@ -205,5 +222,5 @@ void Roster::filterContact(ContactRosterItem* contact, GroupRosterItem* group) { } group->setDisplayed(contact, filters_.empty() || !hide); - int newDisplayedSize = group->getDisplayedChildren().size(); + size_t newDisplayedSize = group->getDisplayedChildren().size(); if (oldDisplayedSize == 0 && newDisplayedSize > 0) { onGroupAdded(group); diff --git a/Swift/Controllers/Roster/Roster.h b/Swift/Controllers/Roster/Roster.h index 2fcfba5..9956cb9 100644 --- a/Swift/Controllers/Roster/Roster.h +++ b/Swift/Controllers/Roster/Roster.h @@ -1,4 +1,4 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. @@ -8,14 +8,16 @@ #include <string> -#include "Swiften/JID/JID.h" -#include "Swift/Controllers/Roster/RosterItemOperation.h" -#include "Swift/Controllers/Roster/RosterFilter.h" -#include <Swift/Controllers/Roster/ContactRosterItem.h> - #include <vector> #include <map> -#include "Swiften/Base/boost_bsignals.h" + #include <boost/shared_ptr.hpp> +#include <Swiften/Base/boost_bsignals.h> +#include <Swiften/JID/JID.h> + +#include <Swift/Controllers/Roster/ItemOperations/RosterItemOperation.h> +#include <Swift/Controllers/Roster/RosterFilter.h> +#include <Swift/Controllers/Roster/ContactRosterItem.h> + namespace Swift { @@ -29,5 +31,5 @@ class Roster { ~Roster(); - void addContact(const JID& jid, const JID& displayJID, const std::string& name, const std::string& group, const std::string& avatarPath); + 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); @@ -37,13 +39,16 @@ class Roster { void applyOnAllItems(const RosterItemOperation& operation); void applyOnItem(const RosterItemOperation& operation, const JID& jid); - void addFilter(RosterFilter *filter) {filters_.push_back(filter);filterAll();}; + void addFilter(RosterFilter* filter); void removeFilter(RosterFilter* filter); GroupRosterItem* getRoot(); - std::vector<RosterFilter*> getFilters() {return filters_;}; + 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 setAvailableFeatures(const JID& jid, const std::set<ContactRosterItem::Feature>& features); + void setBlockingSupported(bool isSupported); private: @@ -59,4 +64,5 @@ class Roster { bool fullJIDMapping_; bool sortByStatus_; + bool blockingSupported_; }; diff --git a/Swift/Controllers/Roster/RosterController.cpp b/Swift/Controllers/Roster/RosterController.cpp index 170bfd0..99be985 100644 --- a/Swift/Controllers/Roster/RosterController.cpp +++ b/Swift/Controllers/Roster/RosterController.cpp @@ -1,48 +1,55 @@ /* - * Copyright (c) 2010-2012 Kevin Smith + * Copyright (c) 2010-2014 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ -#include "Swift/Controllers/Roster/RosterController.h" +#include <Swift/Controllers/Roster/RosterController.h> #include <boost/bind.hpp> #include <boost/smart_ptr/make_shared.hpp> -#include "Swiften/JID/JID.h" -#include "Swiften/Base/foreach.h" -#include "Swift/Controllers/UIInterfaces/MainWindow.h" -#include "Swift/Controllers/UIInterfaces/MainWindowFactory.h" -#include "Swiften/Client/NickResolver.h" -#include "Swiften/Roster/GetRosterRequest.h" -#include "Swiften/Roster/SetRosterRequest.h" -#include "Swift/Controllers/XMPPEvents/SubscriptionRequestEvent.h" -#include "Swift/Controllers/XMPPEvents/ErrorEvent.h" -#include "Swiften/Presence/PresenceOracle.h" -#include "Swiften/Presence/SubscriptionManager.h" -#include "Swift/Controllers/XMPPEvents/EventController.h" -#include "Swiften/Queries/IQRouter.h" -#include "Swift/Controllers/Roster/Roster.h" -#include "Swift/Controllers/Roster/SetPresence.h" -#include "Swift/Controllers/Roster/AppearOffline.h" -#include "Swift/Controllers/Roster/SetAvatar.h" -#include "Swift/Controllers/Roster/SetName.h" -#include "Swift/Controllers/Roster/OfflineRosterFilter.h" -#include "Swift/Controllers/Roster/GroupRosterItem.h" -#include "Swiften/Roster/XMPPRoster.h" -#include "Swiften/Roster/XMPPRosterItem.h" -#include "Swift/Controllers/UIEvents/AddContactUIEvent.h" -#include "Swift/Controllers/UIEvents/RemoveRosterItemUIEvent.h" -#include "Swift/Controllers/UIEvents/RenameRosterItemUIEvent.h" -#include "Swift/Controllers/UIEvents/RenameGroupUIEvent.h" -#include "Swift/Controllers/UIEvents/SendFileUIEvent.h" -#include <Swiften/FileTransfer/FileTransferManager.h> -#include <Swiften/Client/NickManager.h> -#include <Swift/Controllers/Intl.h> +#include <Swiften/Base/foreach.h> #include <Swiften/Base/format.h> -#include <Swiften/Elements/DiscoInfo.h> +#include <Swiften/Base/Path.h> +#include <Swiften/Client/ClientBlockListManager.h> +#include <Swiften/Client/NickManager.h> +#include <Swiften/Client/NickResolver.h> #include <Swiften/Disco/EntityCapsManager.h> +#include <Swiften/Elements/DiscoInfo.h> +#include <Swiften/FileTransfer/FileTransferManager.h> +#include <Swiften/JID/JID.h> #include <Swiften/Jingle/JingleSessionManager.h> +#include <Swiften/Presence/PresenceOracle.h> +#include <Swiften/Presence/SubscriptionManager.h> +#include <Swiften/Queries/IQRouter.h> +#include <Swiften/Roster/GetRosterRequest.h> +#include <Swiften/Roster/SetRosterRequest.h> +#include <Swiften/Roster/XMPPRoster.h> +#include <Swiften/Roster/XMPPRosterItem.h> + +#include <Swift/Controllers/Intl.h> +#include <Swift/Controllers/Roster/GroupRosterItem.h> +#include <Swift/Controllers/Roster/OfflineRosterFilter.h> +#include <Swift/Controllers/Roster/Roster.h> +#include <Swift/Controllers/Roster/RosterVCardProvider.h> +#include <Swift/Controllers/Roster/ItemOperations/AppearOffline.h> +#include <Swift/Controllers/Roster/ItemOperations/SetAvatar.h> +#include <Swift/Controllers/Roster/ItemOperations/SetAvailableFeatures.h> +#include <Swift/Controllers/Roster/ItemOperations/SetBlockingState.h> +#include <Swift/Controllers/Roster/ItemOperations/SetName.h> +#include <Swift/Controllers/Roster/ItemOperations/SetPresence.h> +#include <Swift/Controllers/Roster/ItemOperations/SetVCard.h> #include <Swift/Controllers/SettingConstants.h> +#include <Swift/Controllers/UIEvents/AddContactUIEvent.h> +#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> +#include <Swift/Controllers/XMPPEvents/EventController.h> +#include <Swift/Controllers/XMPPEvents/SubscriptionRequestEvent.h> namespace Swift { @@ -51,9 +58,8 @@ 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) - : myJID_(jid), xmppRoster_(xmppRoster), mainWindowFactory_(mainWindowFactory), mainWindow_(mainWindowFactory_->createMainWindow(uiEventStream)), roster_(new Roster()), offlineFilter_(new OfflineRosterFilter()), nickManager_(nickManager), nickResolver_(nickResolver), uiEventStream_(uiEventStream), entityCapsManager_(entityCapsManager), ftOverview_(fileTransferOverview) { +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; - presenceOracle_ = presenceOracle; subscriptionManager_ = subscriptionManager; eventController_ = eventController; @@ -61,4 +67,5 @@ RosterController::RosterController(const JID& jid, XMPPRoster* xmppRoster, Avata 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)); @@ -71,7 +78,9 @@ RosterController::RosterController(const JID& jid, XMPPRoster* xmppRoster, Avata presenceOracle_->onPresenceChange.connect(boost::bind(&RosterController::handleIncomingPresence, this, _1)); uiEventConnection_ = uiEventStream->onUIEvent.connect(boost::bind(&RosterController::handleUIEvent, this, _1)); - avatarManager_ = avatarManager; + + vcardManager_->onOwnVCardChanged.connect(boost::bind(&RosterController::handleOwnVCardChanged, this, _1)); avatarManager_->onAvatarChanged.connect(boost::bind(&RosterController::handleAvatarChanged, this, _1)); - mainWindow_->setMyAvatarPath(avatarManager_->getAvatarPath(myJID_).string()); + 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)); @@ -84,4 +93,9 @@ RosterController::RosterController(const JID& jid, XMPPRoster* xmppRoster, Avata 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_); } @@ -98,6 +112,6 @@ RosterController::~RosterController() { delete mainWindow_; } + delete rosterVCardProvider_; delete roster_; - } @@ -125,9 +139,9 @@ void RosterController::handleOnJIDAdded(const JID& jid) { if (!groups.empty()) { foreach(const std::string& group, groups) { - roster_->addContact(jid, jid, name, group, avatarManager_->getAvatarPath(jid).string()); + roster_->addContact(jid, jid, name, group, avatarManager_->getAvatarPath(jid)); } } else { - roster_->addContact(jid, jid, name, QT_TRANSLATE_NOOP("", "Contacts"), avatarManager_->getAvatarPath(jid).string()); + roster_->addContact(jid, jid, name, QT_TRANSLATE_NOOP("", "Contacts"), avatarManager_->getAvatarPath(jid)); } applyAllPresenceTo(jid); @@ -164,5 +178,5 @@ void RosterController::handleOnJIDUpdated(const JID& jid, const std::string& old 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).string()); + roster_->addContact(jid, jid, name, group, avatarManager_->getAvatarPath(jid)); } } @@ -184,4 +198,20 @@ void RosterController::handleSettingChanged(const std::string& settingPath) { } +void RosterController::handleBlockingStateChanged() { + if (clientBlockListManager_->getBlockList()->getState() == BlockList::Available) { + foreach(const JID& jid, clientBlockListManager_->getBlockList()->getItems()) { + roster_->applyOnItems(SetBlockingState(jid, ContactRosterItem::IsBlocked)); + } + } +} + +void RosterController::handleBlockingItemAdded(const JID& jid) { + roster_->applyOnItems(SetBlockingState(jid, ContactRosterItem::IsBlocked)); +} + +void RosterController::handleBlockingItemRemoved(const JID& jid) { + 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)) { @@ -253,8 +283,36 @@ void RosterController::updateItem(const XMPPRosterItem& item) { SetRosterRequest::ref request = SetRosterRequest::create(roster, iqRouter_); - request->onResponse.connect(boost::bind(&RosterController::handleRosterSetError, this, _1, roster)); + 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)); + } + } +} + +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::handleRosterSetError(ErrorPayload::ref error, boost::shared_ptr<RosterPayload> rosterPayload) { if (!error) { @@ -299,9 +357,23 @@ void RosterController::handleSubscriptionRequestDeclined(SubscriptionRequestEven } +void RosterController::handleOwnVCardChanged(VCard::ref vcard) { + ownContact_->setVCard(vcard); + mainWindow_->setMyContactRosterItem(ownContact_); +} + void RosterController::handleAvatarChanged(const JID& jid) { - std::string path = avatarManager_->getAvatarPath(jid).string(); + boost::filesystem::path path = avatarManager_->getAvatarPath(jid); roster_->applyOnItems(SetAvatar(jid, path)); if (jid.equals(myJID_, JID::WithoutResource)) { - mainWindow_->setMyAvatarPath(path); + 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(std::string(), presence); + mainWindow_->setMyContactRosterItem(ownContact_); } } @@ -319,8 +391,11 @@ void RosterController::handleOnCapsChanged(const JID& jid) { if (info) { std::set<ContactRosterItem::Feature> features; - if (info->hasFeature(DiscoInfo::JingleFeature) && info->hasFeature(DiscoInfo::JingleFTFeature) && info->hasFeature(DiscoInfo::JingleTransportsIBBFeature)) { + if (FileTransferManager::isSupportedBy(info)) { features.insert(ContactRosterItem::FileTransferFeature); } - roster_->setAvailableFeatures(jid, features); + if (info->hasFeature(DiscoInfo::WhiteboardFeature)) { + features.insert(ContactRosterItem::WhiteboardFeature); + } + roster_->applyOnItems(SetAvailableFeatures(jid, features)); } } diff --git a/Swift/Controllers/Roster/RosterController.h b/Swift/Controllers/Roster/RosterController.h index 5e40124..3338d7f 100644 --- a/Swift/Controllers/Roster/RosterController.h +++ b/Swift/Controllers/Roster/RosterController.h @@ -7,18 +7,21 @@ #pragma once -#include "Swiften/JID/JID.h" #include <string> #include <set> -#include "Swiften/Elements/Presence.h" -#include "Swiften/Elements/ErrorPayload.h" -#include "Swiften/Elements/RosterPayload.h" -#include "Swiften/Avatars/AvatarManager.h" -#include "Swift/Controllers/UIEvents/UIEvent.h" -#include "RosterGroupExpandinessPersister.h" -#include "Swift/Controllers/FileTransfer/FileTransferOverview.h" -#include "Swiften/Base/boost_bsignals.h" #include <boost/shared_ptr.hpp> +#include <Swiften/Base/boost_bsignals.h> +#include <Swiften/JID/JID.h> +#include <Swiften/Elements/Presence.h> +#include <Swiften/Elements/ErrorPayload.h> +#include <Swiften/Elements/RosterPayload.h> +#include <Swiften/Avatars/AvatarManager.h> +#include <Swiften/VCards/VCardManager.h> + +#include <Swift/Controllers/UIEvents/UIEvent.h> +#include <Swift/Controllers/FileTransfer/FileTransferOverview.h> +#include <Swift/Controllers/Roster/RosterGroupExpandinessPersister.h> + namespace Swift { class IQRouter; @@ -40,14 +43,19 @@ namespace Swift { class EntityCapsProvider; class FileTransferManager; + class ClientBlockListManager; + class RosterVCardProvider; 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); + 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(); - MainWindow* getWindow() {return mainWindow_;}; + 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); @@ -58,4 +66,6 @@ namespace Swift { void updateItem(const XMPPRosterItem&); + void initBlockingCommand(); + private: void handleOnJIDAdded(const JID &jid); @@ -71,4 +81,5 @@ namespace Swift { 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); @@ -77,4 +88,8 @@ namespace Swift { void handleSettingChanged(const std::string& settingPath); + void handleBlockingStateChanged(); + void handleBlockingItemAdded(const JID& jid); + void handleBlockingItemRemoved(const JID& jid); + JID myJID_; XMPPRoster* xmppRoster_; @@ -83,4 +98,5 @@ namespace Swift { Roster* roster_; OfflineRosterFilter* offlineFilter_; + VCardManager* vcardManager_; AvatarManager* avatarManager_; NickManager* nickManager_; @@ -95,5 +111,11 @@ namespace Swift { 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_; diff --git a/Swift/Controllers/Roster/RosterVCardProvider.cpp b/Swift/Controllers/Roster/RosterVCardProvider.cpp new file mode 100644 index 0000000..954ac68 --- /dev/null +++ b/Swift/Controllers/Roster/RosterVCardProvider.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2013 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt 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> + +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)); +} + +RosterVCardProvider::~RosterVCardProvider() { +} + +void RosterVCardProvider::handleVCardUpdateRequested(const JID& jid) { + 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); +} + + +} diff --git a/Swift/Controllers/Roster/RosterVCardProvider.h b/Swift/Controllers/Roster/RosterVCardProvider.h new file mode 100644 index 0000000..da41298 --- /dev/null +++ b/Swift/Controllers/Roster/RosterVCardProvider.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2013 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <boost/signals/connection.hpp> + +#include <Swiften/Base/boost_bsignals.h> +#include <Swiften/Elements/VCard.h> +#include <Swiften/JID/JID.h> + +namespace Swift { + +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; +}; + +} diff --git a/Swift/Controllers/Roster/TableRoster.cpp b/Swift/Controllers/Roster/TableRoster.cpp index c00bf4f..eb036db 100644 --- a/Swift/Controllers/Roster/TableRoster.cpp +++ b/Swift/Controllers/Roster/TableRoster.cpp @@ -10,4 +10,5 @@ #include <cassert> #include <algorithm> +#include <boost/numeric/conversion/cast.hpp> #include <Swiften/Base/foreach.h> @@ -133,11 +134,11 @@ void TableRoster::handleUpdateTimerTick() { size_t end = update.insertedRows.size(); update.insertedRows.resize(update.insertedRows.size() + itemInserts.size()); - std::transform(itemInserts.begin(), itemInserts.end(), update.insertedRows.begin() + end, CreateIndexForSection(sectionPostUpdates[i])); + 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() + end, CreateIndexForSection(sectionUpdates[i])); + 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() + end, CreateIndexForSection(sectionPostUpdates[i])); + std::transform(itemUpdates.begin(), itemUpdates.end(), update.updatedRows.begin() + boost::numeric_cast<long long>(end), CreateIndexForSection(sectionPostUpdates[i])); } diff --git a/Swift/Controllers/Roster/TableRoster.h b/Swift/Controllers/Roster/TableRoster.h index d4612ed..f447760 100644 --- a/Swift/Controllers/Roster/TableRoster.h +++ b/Swift/Controllers/Roster/TableRoster.h @@ -13,4 +13,5 @@ #include <Swiften/JID/JID.h> #include <Swiften/Elements/StatusShow.h> +#include <boost/filesystem/path.hpp> namespace Swift { @@ -22,5 +23,5 @@ namespace Swift { public: struct Item { - Item(const std::string& name, const std::string& description, const JID& jid, StatusShow::Type status, const std::string& avatarPath) : name(name), description(description), jid(jid), status(status), avatarPath(avatarPath) { + 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; @@ -28,5 +29,5 @@ namespace Swift { JID jid; StatusShow::Type status; - std::string avatarPath; + boost::filesystem::path avatarPath; }; diff --git a/Swift/Controllers/Roster/UnitTest/RosterControllerTest.cpp b/Swift/Controllers/Roster/UnitTest/RosterControllerTest.cpp index fbee894..392a426 100644 --- a/Swift/Controllers/Roster/UnitTest/RosterControllerTest.cpp +++ b/Swift/Controllers/Roster/UnitTest/RosterControllerTest.cpp @@ -9,33 +9,38 @@ #include <cppunit/extensions/TestFactoryRegistry.h> +#include <Swiften/Avatars/NullAvatarManager.h> +#include <Swiften/Base/Algorithm.h> #include <Swiften/Base/foreach.h> -#include "Swift/Controllers/Roster/RosterController.h" -#include "Swift/Controllers/UnitTest/MockMainWindowFactory.h" -// #include "Swiften/Elements/Payload.h" -// #include "Swiften/Elements/RosterItemPayload.h" -// #include "Swiften/Elements/RosterPayload.h" -#include "Swiften/Queries/DummyIQChannel.h" -#include "Swiften/Client/DummyStanzaChannel.h" -#include "Swiften/Queries/IQRouter.h" -#include "Swiften/Roster/XMPPRosterImpl.h" -#include "Swift/Controllers/Roster/Roster.h" -#include "Swift/Controllers/Roster/GroupRosterItem.h" -#include "Swift/Controllers/Roster/ContactRosterItem.h" -#include "Swift/Controllers/Settings/DummySettingsProvider.h" -#include "Swiften/Avatars/NullAvatarManager.h" -#include "Swift/Controllers/XMPPEvents/EventController.h" -#include "Swiften/Presence/PresenceOracle.h" -#include "Swiften/Presence/SubscriptionManager.h" -#include "Swiften/Client/NickResolver.h" -#include "Swift/Controllers/UIEvents/UIEventStream.h" -#include "Swift/Controllers/UIEvents/RenameRosterItemUIEvent.h" -#include "Swiften/MUC/MUCRegistry.h" +#include <Swiften/Client/ClientBlockListManager.h> #include <Swiften/Client/DummyNickManager.h> -#include <Swiften/Disco/EntityCapsManager.h> +#include <Swiften/Client/DummyStanzaChannel.h> +#include <Swiften/Client/NickResolver.h> +#include <Swiften/Crypto/CryptoProvider.h> +#include <Swiften/Crypto/PlatformCryptoProvider.h> #include <Swiften/Disco/CapsProvider.h> -#include <Swiften/Jingle/JingleSessionManager.h> -#include <Swiften/FileTransfer/UnitTest/DummyFileTransferManager.h> -#include <Swiften/Base/Algorithm.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> +#include <Swiften/Presence/SubscriptionManager.h> +#include <Swiften/Queries/DummyIQChannel.h> +#include <Swiften/Queries/IQRouter.h> +#include <Swiften/Roster/XMPPRosterImpl.h> +#include <Swiften/VCards/VCardMemoryStorage.h> +// #include <Swiften/Elements/Payload.h> +// #include <Swiften/Elements/RosterItemPayload.h> +// #include <Swiften/Elements/RosterPayload.h> + +#include <Swift/Controllers/Roster/ContactRosterItem.h> +#include <Swift/Controllers/Roster/GroupRosterItem.h> +#include <Swift/Controllers/Roster/Roster.h> +#include <Swift/Controllers/Roster/RosterController.h> +#include <Swift/Controllers/Settings/DummySettingsProvider.h> +#include <Swift/Controllers/UIEvents/RenameRosterItemUIEvent.h> +#include <Swift/Controllers/UIEvents/UIEventStream.h> +#include <Swift/Controllers/UnitTest/MockMainWindowFactory.h> +#include <Swift/Controllers/XMPPEvents/EventController.h> using namespace Swift; @@ -83,13 +88,23 @@ class RosterControllerTest : public CppUnit::TestFixture { ftManager_ = new DummyFileTransferManager(); ftOverview_ = new FileTransferOverview(ftManager_); - rosterController_ = new RosterController(jid_, xmppRoster_, avatarManager_, mainWindowFactory_, nickManager_, nickResolver_, presenceOracle_, subscriptionManager_, eventController_, uiEventStream_, router_, settings_, entityCapsManager_, ftOverview_); + 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_; @@ -106,5 +121,5 @@ class RosterControllerTest : public CppUnit::TestFixture { delete settings_; delete xmppRoster_; - }; + } GroupRosterItem* groupChild(size_t i) { @@ -134,5 +149,5 @@ class RosterControllerTest : public CppUnit::TestFixture { CPPUNIT_ASSERT_EQUAL(presence->getStatus(), item2->getStatusText()); - }; + } void testHighestPresence() { @@ -154,5 +169,5 @@ class RosterControllerTest : public CppUnit::TestFixture { CPPUNIT_ASSERT(item); CPPUNIT_ASSERT_EQUAL(highPresence->getStatus(), item->getStatusText()); - }; + } void testNotHighestPresence() { @@ -174,5 +189,5 @@ class RosterControllerTest : public CppUnit::TestFixture { CPPUNIT_ASSERT(item); CPPUNIT_ASSERT_EQUAL(highPresence->getStatus(), item->getStatusText()); - }; + } void testUnavailablePresence() { @@ -216,5 +231,5 @@ class RosterControllerTest : public CppUnit::TestFixture { CPPUNIT_ASSERT_EQUAL(StatusShow::None, item->getStatusShow()); CPPUNIT_ASSERT_EQUAL(lowPresenceOffline->getStatus(), item->getStatusText()); - }; + } void testAdd() { @@ -226,5 +241,5 @@ class RosterControllerTest : public CppUnit::TestFixture { CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(CHILDREN.size())); //CPPUNIT_ASSERT_EQUAL(std::string("Bob"), xmppRoster_->getNameForJID(JID("foo@bar.com"))); - }; + } void testAddSubscription() { @@ -243,5 +258,5 @@ class RosterControllerTest : public CppUnit::TestFixture { CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(groupChild(0)->getChildren().size())); - }; + } void testReceiveRename() { @@ -257,5 +272,5 @@ class RosterControllerTest : public CppUnit::TestFixture { CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(groupChild(0)->getChildren().size())); CPPUNIT_ASSERT_EQUAL(std::string("NewName"), groupChild(0)->getChildren()[0]->getDisplayName()); - }; + } void testReceiveRegroup() { @@ -283,5 +298,5 @@ class RosterControllerTest : public CppUnit::TestFixture { CPPUNIT_ASSERT_EQUAL(std::string("new name"), groupChild(0)->getChildren()[0]->getDisplayName()); CPPUNIT_ASSERT_EQUAL(std::string("Best Group"), groupChild(0)->getDisplayName()); - }; + } void testSendRename() { @@ -338,4 +353,8 @@ class RosterControllerTest : public CppUnit::TestFixture { FileTransferManager* ftManager_; FileTransferOverview* ftOverview_; + ClientBlockListManager* clientBlockListManager_; + CryptoProvider* crypto_; + VCardStorage* vcardStorage_; + VCardManager* vcardManager_; }; diff --git a/Swift/Controllers/Roster/UnitTest/RosterTest.cpp b/Swift/Controllers/Roster/UnitTest/RosterTest.cpp index 0c3e769..7d86aaf 100644 --- a/Swift/Controllers/Roster/UnitTest/RosterTest.cpp +++ b/Swift/Controllers/Roster/UnitTest/RosterTest.cpp @@ -7,9 +7,10 @@ #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/SetPresence.h" +#include <Swift/Controllers/Roster/Roster.h> +#include <Swift/Controllers/Roster/GroupRosterItem.h> +#include <Swift/Controllers/Roster/ItemOperations/SetPresence.h> using namespace Swift; diff --git a/Swift/Controllers/Roster/UnitTest/TableRosterTest.cpp b/Swift/Controllers/Roster/UnitTest/TableRosterTest.cpp index e433b50..f8e6a63 100644 --- a/Swift/Controllers/Roster/UnitTest/TableRosterTest.cpp +++ b/Swift/Controllers/Roster/UnitTest/TableRosterTest.cpp @@ -7,4 +7,6 @@ #include <Swift/Controllers/Roster/TableRoster.h> +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 << ")"; @@ -14,4 +16,5 @@ std::ostream& operator<<(std::ostream& os, const Swift::TableRoster::Index& i) { #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> + #include <boost/shared_ptr.hpp> #include <boost/variant.hpp> @@ -20,5 +23,5 @@ std::ostream& operator<<(std::ostream& os, const Swift::TableRoster::Index& i) { #include <Swift/Controllers/Roster/Roster.h> #include <Swift/Controllers/Roster/GroupRosterItem.h> -#include <Swift/Controllers/Roster/SetPresence.h> +#include <Swift/Controllers/Roster/ItemOperations/SetPresence.h> using namespace Swift; |