summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'Swift/Controllers')
-rw-r--r--Swift/Controllers/Chat/ChatController.cpp22
-rw-r--r--Swift/Controllers/Chat/ChatsManager.cpp4
-rw-r--r--Swift/Controllers/Chat/UserSearchController.cpp2
-rw-r--r--Swift/Controllers/ContactsFromXMPPRoster.cpp7
-rw-r--r--Swift/Controllers/Roster/ContactRosterItem.cpp52
-rw-r--r--Swift/Controllers/Roster/ContactRosterItem.h13
-rw-r--r--Swift/Controllers/Roster/RosterController.cpp7
-rw-r--r--Swift/Controllers/Roster/UnitTest/RosterControllerTest.cpp37
8 files changed, 64 insertions, 80 deletions
diff --git a/Swift/Controllers/Chat/ChatController.cpp b/Swift/Controllers/Chat/ChatController.cpp
index bedc427..51c7349 100644
--- a/Swift/Controllers/Chat/ChatController.cpp
+++ b/Swift/Controllers/Chat/ChatController.cpp
@@ -69,11 +69,11 @@ ChatController::ChatController(const JID& self, StanzaChannel* stanzaChannel, IQ
69 if (isInMUC) { 69 if (isInMUC) {
70 startMessage = str(format(QT_TRANSLATE_NOOP("", "Starting chat with %1% in chatroom %2%")) % nick % contact.toBare().toString()); 70 startMessage = str(format(QT_TRANSLATE_NOOP("", "Starting chat with %1% in chatroom %2%")) % nick % contact.toBare().toString());
71 theirPresence = presenceOracle->getLastPresence(contact); 71 theirPresence = presenceOracle->getLastPresence(contact);
72 } else { 72 } else {
73 startMessage = str(format(QT_TRANSLATE_NOOP("", "Starting chat with %1% - %2%")) % nick % contact.toBare().toString()); 73 startMessage = str(format(QT_TRANSLATE_NOOP("", "Starting chat with %1% - %2%")) % nick % contact.toBare().toString());
74 theirPresence = contact.isBare() ? presenceOracle->getHighestPriorityPresence(contact.toBare()) : presenceOracle->getLastPresence(contact); 74 theirPresence = contact.isBare() ? presenceOracle->getAccountPresence(contact) : presenceOracle->getLastPresence(contact);
75 } 75 }
76 Idle::ref idle; 76 Idle::ref idle;
77 if (theirPresence && (idle = theirPresence->getPayload<Idle>())) { 77 if (theirPresence && (idle = theirPresence->getPayload<Idle>())) {
78 startMessage += str(format(QT_TRANSLATE_NOOP("", ", who has been idle since %1%")) % dateTimeToLocalString(idle->getSince())); 78 startMessage += str(format(QT_TRANSLATE_NOOP("", ", who has been idle since %1%")) % dateTimeToLocalString(idle->getSince()));
79 } 79 }
@@ -141,11 +141,11 @@ void ChatController::setToJID(const JID& jid) {
141 ChatControllerBase::setToJID(jid); 141 ChatControllerBase::setToJID(jid);
142 Presence::ref presence; 142 Presence::ref presence;
143 if (isInMUC_) { 143 if (isInMUC_) {
144 presence = presenceOracle_->getLastPresence(jid); 144 presence = presenceOracle_->getLastPresence(jid);
145 } else { 145 } else {
146 presence = jid.isBare() ? presenceOracle_->getHighestPriorityPresence(jid.toBare()) : presenceOracle_->getLastPresence(jid); 146 presence = jid.isBare() ? presenceOracle_->getAccountPresence(jid.toBare()) : presenceOracle_->getLastPresence(jid);
147 } 147 }
148 chatStateNotifier_->setContactIsOnline(presence && presence->getType() == Presence::Available); 148 chatStateNotifier_->setContactIsOnline(presence && presence->getType() == Presence::Available);
149 handleBareJIDCapsChanged(toJID_); 149 handleBareJIDCapsChanged(toJID_);
150} 150}
151 151
@@ -462,22 +462,22 @@ std::string ChatController::getStatusChangeString(boost::shared_ptr<Presence> pr
462 } 462 }
463 return response + "."; 463 return response + ".";
464} 464}
465 465
466void ChatController::handlePresenceChange(boost::shared_ptr<Presence> newPresence) { 466void ChatController::handlePresenceChange(boost::shared_ptr<Presence> newPresence) {
467 bool me = false; 467 bool relevantPresence = false;
468 if (toJID_.isBare()) { 468
469 newPresence = presenceOracle_->getHighestPriorityPresence(toJID_); 469 if (toJID_.equals(newPresence->getFrom(), JID::WithoutResource)) {
470 if ((newPresence ? newPresence->getShow() : StatusShow::None) != lastShownStatus_) { 470 // Presence matches ChatController JID.
471 me = true; 471 newPresence = presenceOracle_->getAccountPresence(toJID_);
472 } 472 relevantPresence = true;
473 } else if (toJID_.equals(newPresence->getFrom(), JID::WithResource)) {
474 me = true;
475 } 473 }
476 if (!me) { 474
475 if (!relevantPresence) {
477 return; 476 return;
478 } 477 }
478
479 if (!newPresence) { 479 if (!newPresence) {
480 newPresence = boost::make_shared<Presence>(); 480 newPresence = boost::make_shared<Presence>();
481 newPresence->setType(Presence::Unavailable); 481 newPresence->setType(Presence::Unavailable);
482 } 482 }
483 lastShownStatus_ = newPresence->getShow(); 483 lastShownStatus_ = newPresence->getShow();
diff --git a/Swift/Controllers/Chat/ChatsManager.cpp b/Swift/Controllers/Chat/ChatsManager.cpp
index 343f490..8a06333 100644
--- a/Swift/Controllers/Chat/ChatsManager.cpp
+++ b/Swift/Controllers/Chat/ChatsManager.cpp
@@ -285,11 +285,11 @@ ChatListWindow::Chat ChatsManager::updateChatStatusAndAvatarHelper(const ChatLis
285 } 285 }
286 } else { 286 } else {
287 if (avatarManager_) { 287 if (avatarManager_) {
288 fixedChat.avatarPath = avatarManager_->getAvatarPath(fixedChat.jid); 288 fixedChat.avatarPath = avatarManager_->getAvatarPath(fixedChat.jid);
289 } 289 }
290 Presence::ref presence = presenceOracle_->getHighestPriorityPresence(fixedChat.jid.toBare()); 290 Presence::ref presence = presenceOracle_->getAccountPresence(fixedChat.jid.toBare());
291 fixedChat.statusType = presence ? presence->getShow() : StatusShow::None; 291 fixedChat.statusType = presence ? presence->getShow() : StatusShow::None;
292 } 292 }
293 return fixedChat; 293 return fixedChat;
294} 294}
295 295
@@ -407,11 +407,11 @@ ChatListWindow::Chat ChatsManager::createChatListChatItem(const JID& jid, const
407 ChatController* controller = getChatControllerIfExists(jid, false); 407 ChatController* controller = getChatControllerIfExists(jid, false);
408 if (controller) { 408 if (controller) {
409 unreadCount = controller->getUnreadCount(); 409 unreadCount = controller->getUnreadCount();
410 } 410 }
411 JID bareishJID = mucRegistry_->isMUC(jid.toBare()) ? jid : jid.toBare(); 411 JID bareishJID = mucRegistry_->isMUC(jid.toBare()) ? jid : jid.toBare();
412 Presence::ref presence = presenceOracle_->getHighestPriorityPresence(bareishJID); 412 Presence::ref presence = presenceOracle_->getAccountPresence(bareishJID);
413 StatusShow::Type type = presence ? presence->getShow() : StatusShow::None; 413 StatusShow::Type type = presence ? presence->getShow() : StatusShow::None;
414 boost::filesystem::path avatarPath = avatarManager_ ? avatarManager_->getAvatarPath(bareishJID) : boost::filesystem::path(); 414 boost::filesystem::path avatarPath = avatarManager_ ? avatarManager_->getAvatarPath(bareishJID) : boost::filesystem::path();
415 return ChatListWindow::Chat(bareishJID, nickResolver_->jidToNick(bareishJID), activity, unreadCount, type, avatarPath, false, privateMessage); 415 return ChatListWindow::Chat(bareishJID, nickResolver_->jidToNick(bareishJID), activity, unreadCount, type, avatarPath, false, privateMessage);
416 } 416 }
417} 417}
diff --git a/Swift/Controllers/Chat/UserSearchController.cpp b/Swift/Controllers/Chat/UserSearchController.cpp
index 454a110..291472f 100644
--- a/Swift/Controllers/Chat/UserSearchController.cpp
+++ b/Swift/Controllers/Chat/UserSearchController.cpp
@@ -303,11 +303,11 @@ Contact::ref UserSearchController::convertJIDtoContact(const JID& jid) {
303 contact->name = jid.toString(); 303 contact->name = jid.toString();
304 } 304 }
305 } 305 }
306 306
307 // presence lookup 307 // presence lookup
308 Presence::ref presence = presenceOracle_->getHighestPriorityPresence(jid); 308 Presence::ref presence = presenceOracle_->getAccountPresence(jid);
309 if (presence) { 309 if (presence) {
310 contact->statusType = presence->getShow(); 310 contact->statusType = presence->getShow();
311 } else { 311 } else {
312 contact->statusType = StatusShow::None; 312 contact->statusType = StatusShow::None;
313 } 313 }
diff --git a/Swift/Controllers/ContactsFromXMPPRoster.cpp b/Swift/Controllers/ContactsFromXMPPRoster.cpp
index d3d7364..1cab9b1 100644
--- a/Swift/Controllers/ContactsFromXMPPRoster.cpp
+++ b/Swift/Controllers/ContactsFromXMPPRoster.cpp
@@ -3,20 +3,19 @@
3 * Licensed under the simplified BSD license. 3 * Licensed under the simplified BSD license.
4 * See Documentation/Licenses/BSD-simplified.txt for more information. 4 * See Documentation/Licenses/BSD-simplified.txt for more information.
5 */ 5 */
6 6
7/* 7/*
8 * Copyright (c) 2014 Isode Limited. 8 * Copyright (c) 2014-2015 Isode Limited.
9 * All rights reserved. 9 * All rights reserved.
10 * See the COPYING file for more information. 10 * See the COPYING file for more information.
11 */ 11 */
12 12
13#include <Swift/Controllers/ContactsFromXMPPRoster.h> 13#include <Swift/Controllers/ContactsFromXMPPRoster.h>
14 14
15#include <Swiften/Base/foreach.h>
16
17#include <Swiften/Avatars/AvatarManager.h> 15#include <Swiften/Avatars/AvatarManager.h>
16#include <Swiften/Base/foreach.h>
18#include <Swiften/Presence/PresenceOracle.h> 17#include <Swiften/Presence/PresenceOracle.h>
19#include <Swiften/Roster/XMPPRoster.h> 18#include <Swiften/Roster/XMPPRoster.h>
20#include <Swiften/Roster/XMPPRosterItem.h> 19#include <Swiften/Roster/XMPPRosterItem.h>
21 20
22namespace Swift { 21namespace Swift {
@@ -30,11 +29,11 @@ ContactsFromXMPPRoster::~ContactsFromXMPPRoster() {
30std::vector<Contact::ref> ContactsFromXMPPRoster::getContacts(bool /*withMUCNicks*/) { 29std::vector<Contact::ref> ContactsFromXMPPRoster::getContacts(bool /*withMUCNicks*/) {
31 std::vector<Contact::ref> results; 30 std::vector<Contact::ref> results;
32 std::vector<XMPPRosterItem> rosterItems = roster_->getItems(); 31 std::vector<XMPPRosterItem> rosterItems = roster_->getItems();
33 foreach(const XMPPRosterItem& rosterItem, rosterItems) { 32 foreach(const XMPPRosterItem& rosterItem, rosterItems) {
34 Contact::ref contact = boost::make_shared<Contact>(rosterItem.getName().empty() ? rosterItem.getJID().toString() : rosterItem.getName(), rosterItem.getJID(), StatusShow::None,""); 33 Contact::ref contact = boost::make_shared<Contact>(rosterItem.getName().empty() ? rosterItem.getJID().toString() : rosterItem.getName(), rosterItem.getJID(), StatusShow::None,"");
35 contact->statusType = presenceOracle_->getHighestPriorityPresence(contact->jid) ? presenceOracle_->getHighestPriorityPresence(contact->jid)->getShow() : StatusShow::None; 34 contact->statusType = presenceOracle_->getAccountPresence(contact->jid) ? presenceOracle_->getAccountPresence(contact->jid)->getShow() : StatusShow::None;
36 contact->avatarPath = avatarManager_->getAvatarPath(contact->jid); 35 contact->avatarPath = avatarManager_->getAvatarPath(contact->jid);
37 results.push_back(contact); 36 results.push_back(contact);
38 } 37 }
39 return results; 38 return results;
40} 39}
diff --git a/Swift/Controllers/Roster/ContactRosterItem.cpp b/Swift/Controllers/Roster/ContactRosterItem.cpp
index fd6d1cd..ae05aee 100644
--- a/Swift/Controllers/Roster/ContactRosterItem.cpp
+++ b/Swift/Controllers/Roster/ContactRosterItem.cpp
@@ -1,18 +1,19 @@
1/* 1/*
2 * Copyright (c) 2010 Isode Limited. 2 * Copyright (c) 2010-2015 Isode Limited.
3 * All rights reserved. 3 * All rights reserved.
4 * See the COPYING file for more information. 4 * See the COPYING file for more information.
5 */ 5 */
6 6
7#include <Swift/Controllers/Roster/ContactRosterItem.h> 7#include <Swift/Controllers/Roster/ContactRosterItem.h>
8 8
9#include <boost/date_time/posix_time/posix_time.hpp> 9#include <boost/date_time/posix_time/posix_time.hpp>
10 10
11#include <Swiften/Base/foreach.h>
12#include <Swiften/Base/DateTime.h> 11#include <Swiften/Base/DateTime.h>
12#include <Swiften/Base/foreach.h>
13#include <Swiften/Elements/Idle.h> 13#include <Swiften/Elements/Idle.h>
14
14#include <Swift/Controllers/Intl.h> 15#include <Swift/Controllers/Intl.h>
15#include <Swift/Controllers/Roster/GroupRosterItem.h> 16#include <Swift/Controllers/Roster/GroupRosterItem.h>
16 17
17namespace Swift { 18namespace Swift {
18 19
@@ -24,15 +25,15 @@ ContactRosterItem::ContactRosterItem(const JID& jid, const JID& displayJID, cons
24 25
25ContactRosterItem::~ContactRosterItem() { 26ContactRosterItem::~ContactRosterItem() {
26} 27}
27 28
28StatusShow::Type ContactRosterItem::getStatusShow() const { 29StatusShow::Type ContactRosterItem::getStatusShow() const {
29 return shownPresence_ ? shownPresence_->getShow() : StatusShow::None; 30 return presence_ ? presence_->getShow() : StatusShow::None;
30} 31}
31 32
32StatusShow::Type ContactRosterItem::getSimplifiedStatusShow() const { 33StatusShow::Type ContactRosterItem::getSimplifiedStatusShow() const {
33 switch (shownPresence_ ? shownPresence_->getShow() : StatusShow::None) { 34 switch (presence_ ? presence_->getShow() : StatusShow::None) {
34 case StatusShow::Online: return StatusShow::Online; 35 case StatusShow::Online: return StatusShow::Online;
35 case StatusShow::Away: return StatusShow::Away; 36 case StatusShow::Away: return StatusShow::Away;
36 case StatusShow::XA: return StatusShow::Away; 37 case StatusShow::XA: return StatusShow::Away;
37 case StatusShow::FFC: return StatusShow::Online; 38 case StatusShow::FFC: return StatusShow::Online;
38 case StatusShow::DND: return StatusShow::DND; 39 case StatusShow::DND: return StatusShow::DND;
@@ -41,26 +42,26 @@ StatusShow::Type ContactRosterItem::getSimplifiedStatusShow() const {
41 assert(false); 42 assert(false);
42 return StatusShow::None; 43 return StatusShow::None;
43} 44}
44 45
45std::string ContactRosterItem::getStatusText() const { 46std::string ContactRosterItem::getStatusText() const {
46 return shownPresence_ ? shownPresence_->getStatus() : ""; 47 return presence_ ? presence_->getStatus() : "";
47} 48}
48 49
49std::string ContactRosterItem::getIdleText() const { 50std::string ContactRosterItem::getIdleText() const {
50 Idle::ref idle = shownPresence_ ? shownPresence_->getPayload<Idle>() : Idle::ref(); 51 Idle::ref idle = presence_ ? presence_->getPayload<Idle>() : Idle::ref();
51 if (!idle || idle->getSince().is_not_a_date_time()) { 52 if (!idle || idle->getSince().is_not_a_date_time()) {
52 return ""; 53 return "";
53 } else { 54 } else {
54 return dateTimeToLocalString(idle->getSince()); 55 return dateTimeToLocalString(idle->getSince());
55 } 56 }
56} 57}
57 58
58std::string ContactRosterItem::getOfflineSinceText() const { 59std::string ContactRosterItem::getOfflineSinceText() const {
59 if (offlinePresence_) { 60 if (presence_ && presence_->getType() == Presence::Unavailable) {
60 boost::optional<boost::posix_time::ptime> delay = offlinePresence_->getTimestamp(); 61 boost::optional<boost::posix_time::ptime> delay = presence_->getTimestamp();
61 if (offlinePresence_->getType() == Presence::Unavailable && delay) { 62 if (delay) {
62 return dateTimeToLocalString(*delay); 63 return dateTimeToLocalString(*delay);
63 } 64 }
64 } 65 }
65 return ""; 66 return "";
66} 67}
@@ -86,46 +87,17 @@ const JID& ContactRosterItem::getDisplayJID() const {
86} 87}
87 88
88 89
89typedef std::pair<std::string, boost::shared_ptr<Presence> > StringPresencePair; 90typedef std::pair<std::string, boost::shared_ptr<Presence> > StringPresencePair;
90 91
91void ContactRosterItem::calculateShownPresence() {
92 shownPresence_ = offlinePresence_;
93 foreach (StringPresencePair presencePair, presences_) {
94 boost::shared_ptr<Presence> presence = presencePair.second;
95 if (!shownPresence_ || presence->getPriority() > shownPresence_->getPriority() || presence->getShow() < shownPresence_->getShow()) {
96 shownPresence_ = presence;
97 }
98 }
99}
100
101void ContactRosterItem::clearPresence() { 92void ContactRosterItem::clearPresence() {
102 presences_.clear(); 93 presence_.reset();
103 calculateShownPresence();
104 onDataChanged(); 94 onDataChanged();
105} 95}
106 96
107void ContactRosterItem::applyPresence(const std::string& resource, boost::shared_ptr<Presence> presence) { 97void ContactRosterItem::applyPresence(const std::string& resource, boost::shared_ptr<Presence> presence) {
108 if (offlinePresence_) { 98 presence_ = presence;
109 offlinePresence_ = boost::shared_ptr<Presence>();
110 }
111 if (presence->getType() == Presence::Unavailable) {
112 if (resource.empty()) {
113 /* Unavailable from the bare JID means all resources are offline.*/
114 presences_.clear();
115 } else {
116 if (presences_.find(resource) != presences_.end()) {
117 presences_.erase(resource);
118 }
119 }
120 if (presences_.empty()) {
121 offlinePresence_ = presence;
122 }
123 } else {
124 presences_[resource] = presence;
125 }
126 calculateShownPresence();
127 onDataChanged(); 99 onDataChanged();
128} 100}
129 101
130const std::vector<std::string>& ContactRosterItem::getGroups() const { 102const std::vector<std::string>& ContactRosterItem::getGroups() const {
131 return groups_; 103 return groups_;
diff --git a/Swift/Controllers/Roster/ContactRosterItem.h b/Swift/Controllers/Roster/ContactRosterItem.h
index 54a6b60..ec04a8c 100644
--- a/Swift/Controllers/Roster/ContactRosterItem.h
+++ b/Swift/Controllers/Roster/ContactRosterItem.h
@@ -1,26 +1,26 @@
1/* 1/*
2 * Copyright (c) 2010-2013 Isode Limited. 2 * Copyright (c) 2010-2015 Isode Limited.
3 * All rights reserved. 3 * All rights reserved.
4 * See the COPYING file for more information. 4 * See the COPYING file for more information.
5 */ 5 */
6 6
7#pragma once 7#pragma once
8 8
9#include <map>
10#include <set> 9#include <set>
11#include <string> 10#include <string>
11#include <vector>
12 12
13#include <boost/bind.hpp> 13#include <boost/bind.hpp>
14#include <boost/date_time/posix_time/ptime.hpp> 14#include <boost/date_time/posix_time/ptime.hpp>
15#include <boost/filesystem/path.hpp> 15#include <boost/filesystem/path.hpp>
16#include <boost/shared_ptr.hpp> 16#include <boost/shared_ptr.hpp>
17 17
18#include <Swiften/Base/boost_bsignals.h> 18#include <Swiften/Base/boost_bsignals.h>
19#include <Swiften/Elements/MUCOccupant.h>
19#include <Swiften/Elements/Presence.h> 20#include <Swiften/Elements/Presence.h>
20#include <Swiften/Elements/StatusShow.h> 21#include <Swiften/Elements/StatusShow.h>
21#include <Swiften/Elements/MUCOccupant.h>
22#include <Swiften/Elements/VCard.h> 22#include <Swiften/Elements/VCard.h>
23#include <Swiften/JID/JID.h> 23#include <Swiften/JID/JID.h>
24 24
25#include <Swift/Controllers/Roster/RosterItem.h> 25#include <Swift/Controllers/Roster/RosterItem.h>
26 26
@@ -54,16 +54,15 @@ class ContactRosterItem : public RosterItem {
54 const boost::filesystem::path& getAvatarPath() const; 54 const boost::filesystem::path& getAvatarPath() const;
55 const JID& getJID() const; 55 const JID& getJID() const;
56 void setDisplayJID(const JID& jid); 56 void setDisplayJID(const JID& jid);
57 const JID& getDisplayJID() const; 57 const JID& getDisplayJID() const;
58 void applyPresence(const std::string& resource, boost::shared_ptr<Presence> presence); 58 void applyPresence(const std::string& resource, boost::shared_ptr<Presence> presence);
59 void clearPresence();
60 void calculateShownPresence();
61 const std::vector<std::string>& getGroups() const; 59 const std::vector<std::string>& getGroups() const;
62 /** Only used so a contact can know about the groups it's in*/ 60 /** Only used so a contact can know about the groups it's in*/
63 void addGroup(const std::string& group); 61 void addGroup(const std::string& group);
64 void removeGroup(const std::string& group); 62 void removeGroup(const std::string& group);
63 void clearPresence();
65 64
66 MUCOccupant::Role getMUCRole() const; 65 MUCOccupant::Role getMUCRole() const;
67 void setMUCRole(const MUCOccupant::Role& role); 66 void setMUCRole(const MUCOccupant::Role& role);
68 MUCOccupant::Affiliation getMUCAffiliation() const; 67 MUCOccupant::Affiliation getMUCAffiliation() const;
69 void setMUCAffiliation(const MUCOccupant::Affiliation& affiliation); 68 void setMUCAffiliation(const MUCOccupant::Affiliation& affiliation);
@@ -83,13 +82,11 @@ class ContactRosterItem : public RosterItem {
83 private: 82 private:
84 JID jid_; 83 JID jid_;
85 JID displayJID_; 84 JID displayJID_;
86 boost::posix_time::ptime lastAvailableTime_; 85 boost::posix_time::ptime lastAvailableTime_;
87 boost::filesystem::path avatarPath_; 86 boost::filesystem::path avatarPath_;
88 std::map<std::string, boost::shared_ptr<Presence> > presences_; 87 boost::shared_ptr<Presence> presence_;
89 boost::shared_ptr<Presence> offlinePresence_;
90 boost::shared_ptr<Presence> shownPresence_;
91 std::vector<std::string> groups_; 88 std::vector<std::string> groups_;
92 MUCOccupant::Role mucRole_; 89 MUCOccupant::Role mucRole_;
93 MUCOccupant::Affiliation mucAffiliation_; 90 MUCOccupant::Affiliation mucAffiliation_;
94 std::set<Feature> features_; 91 std::set<Feature> features_;
95 BlockState blockState_; 92 BlockState blockState_;
diff --git a/Swift/Controllers/Roster/RosterController.cpp b/Swift/Controllers/Roster/RosterController.cpp
index 73efa43..751ca32 100644
--- a/Swift/Controllers/Roster/RosterController.cpp
+++ b/Swift/Controllers/Roster/RosterController.cpp
@@ -77,11 +77,10 @@ RosterController::RosterController(const JID& jid, XMPPRoster* xmppRoster, Avata
77 xmppRoster_->onJIDAdded.connect(boost::bind(&RosterController::handleOnJIDAdded, this, _1)); 77 xmppRoster_->onJIDAdded.connect(boost::bind(&RosterController::handleOnJIDAdded, this, _1));
78 xmppRoster_->onJIDUpdated.connect(boost::bind(&RosterController::handleOnJIDUpdated, this, _1, _2, _3)); 78 xmppRoster_->onJIDUpdated.connect(boost::bind(&RosterController::handleOnJIDUpdated, this, _1, _2, _3));
79 xmppRoster_->onJIDRemoved.connect(boost::bind(&RosterController::handleOnJIDRemoved, this, _1)); 79 xmppRoster_->onJIDRemoved.connect(boost::bind(&RosterController::handleOnJIDRemoved, this, _1));
80 xmppRoster_->onRosterCleared.connect(boost::bind(&RosterController::handleRosterCleared, this)); 80 xmppRoster_->onRosterCleared.connect(boost::bind(&RosterController::handleRosterCleared, this));
81 subscriptionManager_->onPresenceSubscriptionRequest.connect(boost::bind(&RosterController::handleSubscriptionRequest, this, _1, _2)); 81 subscriptionManager_->onPresenceSubscriptionRequest.connect(boost::bind(&RosterController::handleSubscriptionRequest, this, _1, _2));
82 presenceOracle_->onPresenceChange.connect(boost::bind(&RosterController::handleIncomingPresence, this, _1));
83 uiEventConnection_ = uiEventStream->onUIEvent.connect(boost::bind(&RosterController::handleUIEvent, this, _1)); 82 uiEventConnection_ = uiEventStream->onUIEvent.connect(boost::bind(&RosterController::handleUIEvent, this, _1));
84 83
85 vcardManager_->onOwnVCardChanged.connect(boost::bind(&RosterController::handleOwnVCardChanged, this, _1)); 84 vcardManager_->onOwnVCardChanged.connect(boost::bind(&RosterController::handleOwnVCardChanged, this, _1));
86 avatarManager_->onAvatarChanged.connect(boost::bind(&RosterController::handleAvatarChanged, this, _1)); 85 avatarManager_->onAvatarChanged.connect(boost::bind(&RosterController::handleAvatarChanged, this, _1));
87 presenceOracle_->onPresenceChange.connect(boost::bind(&RosterController::handlePresenceChanged, this, _1)); 86 presenceOracle_->onPresenceChange.connect(boost::bind(&RosterController::handlePresenceChanged, this, _1));
@@ -332,11 +331,12 @@ void RosterController::handleRosterSetError(ErrorPayload::ref error, boost::shar
332 331
333void RosterController::handleIncomingPresence(Presence::ref newPresence) { 332void RosterController::handleIncomingPresence(Presence::ref newPresence) {
334 if (newPresence->getType() == Presence::Error) { 333 if (newPresence->getType() == Presence::Error) {
335 return; 334 return;
336 } 335 }
337 roster_->applyOnItems(SetPresence(newPresence)); 336 Presence::ref accountPresence = presenceOracle_->getAccountPresence(newPresence->getFrom().toBare());
337 roster_->applyOnItems(SetPresence(accountPresence));
338} 338}
339 339
340void RosterController::handleSubscriptionRequest(const JID& jid, const std::string& message) { 340void RosterController::handleSubscriptionRequest(const JID& jid, const std::string& message) {
341 if (xmppRoster_->containsJID(jid) && (xmppRoster_->getSubscriptionStateForJID(jid) == RosterItemPayload::To || xmppRoster_->getSubscriptionStateForJID(jid) == RosterItemPayload::Both)) { 341 if (xmppRoster_->containsJID(jid) && (xmppRoster_->getSubscriptionStateForJID(jid) == RosterItemPayload::To || xmppRoster_->getSubscriptionStateForJID(jid) == RosterItemPayload::Both)) {
342 subscriptionManager_->confirmSubscription(jid); 342 subscriptionManager_->confirmSubscription(jid);
@@ -378,10 +378,13 @@ void RosterController::handleAvatarChanged(const JID& jid) {
378void RosterController::handlePresenceChanged(Presence::ref presence) { 378void RosterController::handlePresenceChanged(Presence::ref presence) {
379 if (presence->getFrom().equals(myJID_, JID::WithResource)) { 379 if (presence->getFrom().equals(myJID_, JID::WithResource)) {
380 ownContact_->applyPresence(std::string(), presence); 380 ownContact_->applyPresence(std::string(), presence);
381 mainWindow_->setMyContactRosterItem(ownContact_); 381 mainWindow_->setMyContactRosterItem(ownContact_);
382 } 382 }
383 else {
384 handleIncomingPresence(presence);
385 }
383} 386}
384 387
385boost::optional<XMPPRosterItem> RosterController::getItem(const JID& jid) const { 388boost::optional<XMPPRosterItem> RosterController::getItem(const JID& jid) const {
386 return xmppRoster_->getItem(jid); 389 return xmppRoster_->getItem(jid);
387} 390}
diff --git a/Swift/Controllers/Roster/UnitTest/RosterControllerTest.cpp b/Swift/Controllers/Roster/UnitTest/RosterControllerTest.cpp
index 9320af1..d774e6d 100644
--- a/Swift/Controllers/Roster/UnitTest/RosterControllerTest.cpp
+++ b/Swift/Controllers/Roster/UnitTest/RosterControllerTest.cpp
@@ -192,43 +192,56 @@ class RosterControllerTest : public CppUnit::TestFixture {
192 void testUnavailablePresence() { 192 void testUnavailablePresence() {
193 std::vector<std::string> groups; 193 std::vector<std::string> groups;
194 groups.push_back("testGroup1"); 194 groups.push_back("testGroup1");
195 JID from("test@testdomain.com"); 195 JID from("test@testdomain.com");
196 xmppRoster_->addContact(from, "name", groups, RosterItemPayload::Both); 196 xmppRoster_->addContact(from, "name", groups, RosterItemPayload::Both);
197
197 Presence::ref lowPresence(new Presence()); 198 Presence::ref lowPresence(new Presence());
198 lowPresence->setFrom(withResource(from, "bob")); 199 lowPresence->setFrom(withResource(from, "bob"));
199 lowPresence->setPriority(2); 200 lowPresence->setPriority(2);
201 lowPresence->setShow(StatusShow::Away);
200 lowPresence->setStatus("Not here"); 202 lowPresence->setStatus("Not here");
203 Presence::ref lowPresenceOffline(new Presence());
204 lowPresenceOffline->setFrom(withResource(from, "bob"));
205 lowPresenceOffline->setStatus("Signing out");
206 lowPresenceOffline->setType(Presence::Unavailable);
207
201 Presence::ref highPresence(new Presence()); 208 Presence::ref highPresence(new Presence());
202 highPresence->setFrom(withResource(from, "bert")); 209 highPresence->setFrom(withResource(from, "bert"));
203 highPresence->setPriority(10); 210 highPresence->setPriority(10);
204 highPresence->setStatus("So totally here"); 211 highPresence->setStatus("So totally here");
205 Presence::ref highPresenceOffline(new Presence()); 212 Presence::ref highPresenceOffline(new Presence());
206 highPresenceOffline->setFrom(withResource(from, "bert")); 213 highPresenceOffline->setFrom(withResource(from, "bert"));
207 highPresenceOffline->setType(Presence::Unavailable); 214 highPresenceOffline->setType(Presence::Unavailable);
208 Presence::ref lowPresenceOffline(new Presence()); 215
209 lowPresenceOffline->setFrom(withResource(from, "bob"));
210 lowPresenceOffline->setStatus("Signing out");
211 lowPresenceOffline->setType(Presence::Unavailable);
212 stanzaChannel_->onPresenceReceived(lowPresence); 216 stanzaChannel_->onPresenceReceived(lowPresence);
217 Presence::ref accountPresence = presenceOracle_->getAccountPresence(from);
218 CPPUNIT_ASSERT_EQUAL(StatusShow::Away, accountPresence->getShow());
219
213 stanzaChannel_->onPresenceReceived(highPresence); 220 stanzaChannel_->onPresenceReceived(highPresence);
221 accountPresence = presenceOracle_->getAccountPresence(from);
222 CPPUNIT_ASSERT_EQUAL(StatusShow::Online, accountPresence->getShow());
223
214 stanzaChannel_->onPresenceReceived(highPresenceOffline); 224 stanzaChannel_->onPresenceReceived(highPresenceOffline);
225
226 // After this, the roster should show the low presence.
215 ContactRosterItem* item = dynamic_cast<ContactRosterItem*>(dynamic_cast<GroupRosterItem*>(CHILDREN[0])->getChildren()[0]); 227 ContactRosterItem* item = dynamic_cast<ContactRosterItem*>(dynamic_cast<GroupRosterItem*>(CHILDREN[0])->getChildren()[0]);
216 CPPUNIT_ASSERT(item); 228 CPPUNIT_ASSERT(item);
217 /* A verification that if the test fails, it's the RosterController, not the PresenceOracle. */ 229
218 Presence::ref high = presenceOracle_->getHighestPriorityPresence(from); 230 Presence::ref low = presenceOracle_->getAccountPresence(from);
219 CPPUNIT_ASSERT_EQUAL(Presence::Available, high->getType()); 231
220 CPPUNIT_ASSERT_EQUAL(lowPresence->getStatus(), high->getStatus()); 232 CPPUNIT_ASSERT_EQUAL(Presence::Available, low->getType());
221 CPPUNIT_ASSERT_EQUAL(StatusShow::Online, item->getStatusShow()); 233 CPPUNIT_ASSERT_EQUAL(lowPresence->getStatus(), low->getStatus());
234 CPPUNIT_ASSERT_EQUAL(lowPresence->getShow(), item->getStatusShow());
222 CPPUNIT_ASSERT_EQUAL(lowPresence->getStatus(), item->getStatusText()); 235 CPPUNIT_ASSERT_EQUAL(lowPresence->getStatus(), item->getStatusText());
223 stanzaChannel_->onPresenceReceived(lowPresenceOffline); 236 stanzaChannel_->onPresenceReceived(lowPresenceOffline);
224 item = dynamic_cast<ContactRosterItem*>(dynamic_cast<GroupRosterItem*>(CHILDREN[0])->getChildren()[0]); 237 item = dynamic_cast<ContactRosterItem*>(dynamic_cast<GroupRosterItem*>(CHILDREN[0])->getChildren()[0]);
225 CPPUNIT_ASSERT(item); 238 CPPUNIT_ASSERT(item);
226 /* A verification that if the test fails, it's the RosterController, not the PresenceOracle. */ 239 /* A verification that if the test fails, it's the RosterController, not the PresenceOracle. */
227 high = presenceOracle_->getHighestPriorityPresence(from); 240 low = presenceOracle_->getHighestPriorityPresence(from);
228 CPPUNIT_ASSERT_EQUAL(Presence::Unavailable, high->getType()); 241 CPPUNIT_ASSERT_EQUAL(Presence::Unavailable, low->getType());
229 CPPUNIT_ASSERT_EQUAL(lowPresenceOffline->getStatus(), high->getStatus()); 242 CPPUNIT_ASSERT_EQUAL(lowPresenceOffline->getStatus(), low->getStatus());
230 CPPUNIT_ASSERT_EQUAL(StatusShow::None, item->getStatusShow()); 243 CPPUNIT_ASSERT_EQUAL(StatusShow::None, item->getStatusShow());
231 CPPUNIT_ASSERT_EQUAL(lowPresenceOffline->getStatus(), item->getStatusText()); 244 CPPUNIT_ASSERT_EQUAL(lowPresenceOffline->getStatus(), item->getStatusText());
232 } 245 }
233 246
234 void testAdd() { 247 void testAdd() {