summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'Swiften/Roster')
-rw-r--r--Swiften/Roster/AppearOffline.h2
-rw-r--r--Swiften/Roster/ContactRosterItem.cpp76
-rw-r--r--Swiften/Roster/ContactRosterItem.h37
-rw-r--r--Swiften/Roster/GroupRosterItem.cpp140
-rw-r--r--Swiften/Roster/GroupRosterItem.h69
-rw-r--r--Swiften/Roster/OpenChatRosterAction.h26
-rw-r--r--Swiften/Roster/Roster.cpp128
-rw-r--r--Swiften/Roster/Roster.h32
-rw-r--r--Swiften/Roster/RosterItem.cpp44
-rw-r--r--Swiften/Roster/RosterItem.h30
-rw-r--r--Swiften/Roster/RosterItemOperation.h5
-rw-r--r--Swiften/Roster/SetName.h2
-rw-r--r--Swiften/Roster/SetPresence.h12
-rw-r--r--Swiften/Roster/TreeWidget.h19
-rw-r--r--Swiften/Roster/TreeWidgetFactory.h26
-rw-r--r--Swiften/Roster/TreeWidgetItem.h40
-rw-r--r--Swiften/Roster/UnitTest/MockTreeWidget.h20
-rw-r--r--Swiften/Roster/UnitTest/MockTreeWidgetFactory.h74
-rw-r--r--Swiften/Roster/UnitTest/MockTreeWidgetItem.cpp19
-rw-r--r--Swiften/Roster/UnitTest/MockTreeWidgetItem.h38
-rw-r--r--Swiften/Roster/UnitTest/RosterTest.cpp25
-rw-r--r--Swiften/Roster/UserRosterAction.h38
22 files changed, 396 insertions, 506 deletions
diff --git a/Swiften/Roster/AppearOffline.h b/Swiften/Roster/AppearOffline.h
index 792cec1..8e14190 100644
--- a/Swiften/Roster/AppearOffline.h
+++ b/Swiften/Roster/AppearOffline.h
@@ -21,7 +21,7 @@ class AppearOffline : public RosterItemOperation {
virtual void operator() (RosterItem* item) const {
ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(item);
if (contact) {
- contact->setStatusShow(StatusShow::None);
+ contact->clearPresence();
}
}
diff --git a/Swiften/Roster/ContactRosterItem.cpp b/Swiften/Roster/ContactRosterItem.cpp
index 39e96bd..2d5082c 100644
--- a/Swiften/Roster/ContactRosterItem.cpp
+++ b/Swiften/Roster/ContactRosterItem.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
@@ -10,49 +10,77 @@
namespace Swift {
-ContactRosterItem::ContactRosterItem(const JID& jid, const String& name, GroupRosterItem* parent, TreeWidgetFactory* factory) : jid_(jid), name_(name) {
- parent->addChild(this);
- widget_ = factory->createTreeWidgetItem(parent->getWidget());
- widget_->setText(name.isEmpty() ? jid.toString() : name);
- widget_->onUserAction.connect(boost::bind(&ContactRosterItem::handleUserAction, this, _1));
- setStatusShow(StatusShow::None);
+ContactRosterItem::ContactRosterItem(const JID& jid, const String& name, GroupRosterItem* parent) : RosterItem(name, parent), jid_(jid) {
}
ContactRosterItem::~ContactRosterItem() {
- delete widget_;
}
-void ContactRosterItem::setName(const String& name) {
- widget_->setText(name);
+StatusShow::Type ContactRosterItem::getStatusShow() const {
+ return shownPresence_ ? shownPresence_->getShow() : StatusShow::None;
}
-StatusShow::Type ContactRosterItem::getStatusShow() {
- return statusShow_;
+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;
+ }
+ assert(false);
}
-void ContactRosterItem::setStatusShow(StatusShow::Type show) {
- statusShow_ = show;
- widget_->setStatusShow(show);
-}
-
-void ContactRosterItem::setStatusText(const String& status) {
- widget_->setStatusText(status);
+String ContactRosterItem::getStatusText() const {
+ return shownPresence_ ? shownPresence_->getStatus() : "";
}
void ContactRosterItem::setAvatarPath(const String& path) {
- widget_->setAvatarPath(path);
+ avatarPath_ = path;
+ onDataChanged();
+}
+const String& ContactRosterItem::getAvatarPath() const {
+ return avatarPath_;
}
const JID& ContactRosterItem::getJID() const {
return jid_;
}
-void ContactRosterItem::show() {
- widget_->show();
+typedef std::pair<String, boost::shared_ptr<Presence> > StringPresencePair;
+
+void ContactRosterItem::calculateShownPresence() {
+ shownPresence_ = offlinePresence_;
+ foreach (StringPresencePair presencePair, presences_) {
+ boost::shared_ptr<Presence> presence = presencePair.second;
+ if (!shownPresence_ || presence->getPriority() > shownPresence_->getPriority() || presence->getShow() < shownPresence_->getShow()) {
+ shownPresence_ = presence;
+ }
+ }
+}
+
+void ContactRosterItem::clearPresence() {
+ presences_.clear();
+ calculateShownPresence();
}
-void ContactRosterItem::hide() {
- widget_->hide();
+void ContactRosterItem::applyPresence(const String& resource, boost::shared_ptr<Presence> presence) {
+ if (offlinePresence_) {
+ offlinePresence_ = boost::shared_ptr<Presence>();
+ }
+ if (presence->getType() == Presence::Unavailable) {
+ if (presences_.find(resource) != presences_.end()) {
+ presences_.erase(resource);
+ }
+ if (presences_.size() > 0) {
+ offlinePresence_ = presence;
+ }
+ } else {
+ presences_[resource] = presence;
+ }
+ calculateShownPresence();
+ onDataChanged();
}
}
diff --git a/Swiften/Roster/ContactRosterItem.h b/Swiften/Roster/ContactRosterItem.h
index 92b3056..bd49e05 100644
--- a/Swiften/Roster/ContactRosterItem.h
+++ b/Swiften/Roster/ContactRosterItem.h
@@ -1,48 +1,47 @@
/*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
-#ifndef SWIFTEN_ContactRosterItem_H
-#define SWIFTEN_ContactRosterItem_H
+#pragma once
#include "Swiften/Base/String.h"
#include "Swiften/JID/JID.h"
-#include "Swiften/Roster/TreeWidgetFactory.h"
#include "Swiften/Roster/RosterItem.h"
-#include "Swiften/Roster/UserRosterAction.h"
#include "Swiften/Elements/StatusShow.h"
+#include "Swiften/Elements/Presence.h"
+#include <map>
#include <boost/bind.hpp>
#include <boost/signal.hpp>
#include <boost/shared_ptr.hpp>
namespace Swift {
-class TreeWidgetItem;
class GroupRosterItem;
class ContactRosterItem : public RosterItem {
public:
- ContactRosterItem(const JID& jid, const String& name, GroupRosterItem* parent, TreeWidgetFactory* factory);
- ~ContactRosterItem();
+ ContactRosterItem(const JID& jid, const String& name, GroupRosterItem* parent);
+ virtual ~ContactRosterItem();
- StatusShow::Type getStatusShow();
- void setStatusShow(StatusShow::Type show);
- void setStatusText(const String& status);
+ StatusShow::Type getStatusShow() const;
+ StatusShow::Type getSimplifiedStatusShow() const;
+ String getStatusText() const;
void setAvatarPath(const String& path);
+ const String& getAvatarPath() const;
const JID& getJID() const;
- void setName(const String& name);
- void show();
- void hide();
-
+ void applyPresence(const String& resource, boost::shared_ptr<Presence> presence);
+ void clearPresence();
+ void calculateShownPresence();
private:
JID jid_;
- String name_;
- TreeWidgetItem *widget_;
- StatusShow::Type statusShow_;
+ String avatarPath_;
+ bool hidden_;
+ std::map<String, boost::shared_ptr<Presence> > presences_;
+ boost::shared_ptr<Presence> offlinePresence_;
+ boost::shared_ptr<Presence> shownPresence_;
};
}
-#endif
diff --git a/Swiften/Roster/GroupRosterItem.cpp b/Swiften/Roster/GroupRosterItem.cpp
new file mode 100644
index 0000000..05530ec
--- /dev/null
+++ b/Swiften/Roster/GroupRosterItem.cpp
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2010 Kevin Smith
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include "Swiften/Roster/GroupRosterItem.h"
+
+#include <boost/bind.hpp>
+#include <iostream>
+
+namespace Swift {
+
+GroupRosterItem::GroupRosterItem(const String& name, GroupRosterItem* parent) : RosterItem(name, parent) {
+
+}
+
+GroupRosterItem::~GroupRosterItem() {
+
+}
+
+const std::vector<RosterItem*>& GroupRosterItem::getChildren() const {
+ return children_;
+}
+
+const std::vector<RosterItem*>& GroupRosterItem::getDisplayedChildren() const {
+// std::cout << "Fetching displayed children for " << getDisplayName() << " and found " << displayedChildren_.size() << std::endl;
+ return displayedChildren_;
+}
+
+void GroupRosterItem::addChild(RosterItem* item) {
+ children_.push_back(item);
+ GroupRosterItem* group = dynamic_cast<GroupRosterItem*>(item);
+ if (group) {
+ group->onChildrenChanged.connect(boost::bind(&GroupRosterItem::handleChildrenChanged, this, group));
+ }
+ onChildrenChanged();
+ onDataChanged();
+}
+
+/**
+ * Returns the removed item - but only if it's the only one, otherwise
+ * the return result is undefined.
+ */
+ContactRosterItem* GroupRosterItem::removeChild(const JID& jid) {
+ std::vector<RosterItem*>::iterator it = children_.begin();
+ ContactRosterItem* removed = NULL;
+ while (it != children_.end()) {
+ ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(*it);
+ if (contact && contact->getJID() == jid) {
+ displayedChildren_.erase(std::remove(displayedChildren_.begin(), displayedChildren_.end(), contact), displayedChildren_.end());
+ removed = contact;
+ delete contact;
+ it = children_.erase(it);
+ continue;
+ }
+ GroupRosterItem* group = dynamic_cast<GroupRosterItem*>(*it);
+ if (group) {
+ ContactRosterItem* groupRemoved = group->removeChild(jid);
+ if (groupRemoved) {
+ removed = groupRemoved;
+ }
+ }
+ it++;
+ }
+ onChildrenChanged();
+ onDataChanged();
+ return removed;
+}
+
+void GroupRosterItem::sortDisplayed() {
+ std::stable_sort(displayedChildren_.begin(), displayedChildren_.end(), itemLessThan);
+}
+
+bool GroupRosterItem::itemLessThan(const RosterItem* left, const RosterItem* right) {
+ const ContactRosterItem* leftContact = dynamic_cast<const ContactRosterItem*>(left);
+ const ContactRosterItem* rightContact = dynamic_cast<const ContactRosterItem*>(right);
+ if (leftContact) {
+ if (rightContact) {
+ return false;
+ }
+ StatusShow::Type leftType = leftContact->getSimplifiedStatusShow();
+ StatusShow::Type rightType = rightContact->getSimplifiedStatusShow();
+ if (leftType == rightType) {
+ return left->getSortableDisplayName() < right->getSortableDisplayName();
+ } else {
+ return leftType < rightType;
+ }
+ } else {
+ if (rightContact) {
+ return true;
+ }
+ return left->getSortableDisplayName() < right->getSortableDisplayName();
+ }
+}
+
+void GroupRosterItem::setDisplayed(RosterItem* item, bool displayed) {
+ bool found = false;
+ for (size_t i = 0; i < displayedChildren_.size(); i++) {
+ if (displayedChildren_[i] == item) {
+ found = true;
+ }
+ }
+ if (found == displayed) {
+ return;
+ }
+ if (displayed) {
+ displayedChildren_.push_back(item);
+ sortDisplayed();
+ } else {
+ displayedChildren_.erase(std::remove(displayedChildren_.begin(), displayedChildren_.end(), item), displayedChildren_.end());
+ }
+ onDataChanged();
+ onChildrenChanged();
+}
+
+void GroupRosterItem::handleChildrenChanged(GroupRosterItem* group) {
+ size_t oldSize = getDisplayedChildren().size();
+ if (group->getDisplayedChildren().size() > 0) {
+ bool found = false;
+ for (size_t i = 0; i < displayedChildren_.size(); i++) {
+ if (displayedChildren_[i] == group) {
+ found = true;
+ }
+ }
+ if (!found) {
+ displayedChildren_.push_back(group);
+ sortDisplayed();
+ }
+ } else {
+ displayedChildren_.erase(std::remove(displayedChildren_.begin(), displayedChildren_.end(), group), displayedChildren_.end());
+ }
+ if (oldSize != getDisplayedChildren().size()) {
+ onDataChanged();
+ onChildrenChanged();
+ }
+}
+
+
+}
diff --git a/Swiften/Roster/GroupRosterItem.h b/Swiften/Roster/GroupRosterItem.h
index 83128a5..5e16b2b 100644
--- a/Swiften/Roster/GroupRosterItem.h
+++ b/Swiften/Roster/GroupRosterItem.h
@@ -1,74 +1,37 @@
/*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
-#ifndef SWIFTEN_GroupRosterItem_H
-#define SWIFTEN_GroupRosterItem_H
+#pragma once
#include "Swiften/Roster/RosterItem.h"
#include "Swiften/Base/String.h"
-#include "Swiften/Roster/TreeWidget.h"
-#include "Swiften/Roster/TreeWidgetFactory.h"
-#include "Swiften/Roster/TreeWidgetItem.h"
#include "Swiften/Roster/ContactRosterItem.h"
-#include <list>
+#include <vector>
namespace Swift {
class GroupRosterItem : public RosterItem {
public:
- GroupRosterItem(const String& name, TreeWidget* tree, TreeWidgetFactory* factory) : name_(name) {
- widget_ = factory->createTreeWidgetItem(tree);
- widget_->setExpanded(true);
- widget_->setText(name);
- }
-
- ~GroupRosterItem() {
- delete widget_;
- }
-
- const String& getName() const {
- return name_;
- }
-
- TreeWidgetItem* getWidget() const {
- return widget_;
- }
-
- const std::list<RosterItem*>& getChildren() const {
- return children_;
- }
-
- void addChild(RosterItem* item) {
- children_.push_back(item);
- }
-
- void removeChild(const JID& jid) {
- std::list<RosterItem*>::iterator it = children_.begin();
- while (it != children_.end()) {
- ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(*it);
- if (contact && contact->getJID() == jid) {
- delete contact;
- it = children_.erase(it);
- continue;
- }
- GroupRosterItem* group = dynamic_cast<GroupRosterItem*>(*it);
- if (group) {
- group->removeChild(jid);
- }
- it++;
- }
- }
-
+ GroupRosterItem(const String& name, GroupRosterItem* parent);
+ virtual ~GroupRosterItem();
+ const std::vector<RosterItem*>& getChildren() const;
+ const std::vector<RosterItem*>& getDisplayedChildren() const;
+ void addChild(RosterItem* item);
+ ContactRosterItem* removeChild(const JID& jid);
+ void setDisplayed(RosterItem* item, bool displayed);
+ boost::signal<void ()> onChildrenChanged;
+ static bool itemLessThan(const RosterItem* left, const RosterItem* right);
private:
+ void handleChildrenChanged(GroupRosterItem* group);
+ void sortDisplayed();
String name_;
- TreeWidgetItem* widget_;
- std::list<RosterItem*> children_;
+ std::vector<RosterItem*> children_;
+ std::vector<RosterItem*> displayedChildren_;
};
}
-#endif
diff --git a/Swiften/Roster/OpenChatRosterAction.h b/Swiften/Roster/OpenChatRosterAction.h
deleted file mode 100644
index b0784f5..0000000
--- a/Swiften/Roster/OpenChatRosterAction.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2010 Remko Tronçon
- * Licensed under the GNU General Public License v3.
- * See Documentation/Licenses/GPLv3.txt for more information.
- */
-
-#ifndef SWIFTEN_OpenChatRosterAction_H
-#define SWIFTEN_OpenChatRosterAction_H
-
-#include "Swiften/Roster/UserRosterAction.h"
-
-namespace Swift {
-class RosterItem;
-class TreeWidgetItem;
-
-class OpenChatRosterAction : public UserRosterAction {
- public:
- virtual ~OpenChatRosterAction() {};
-
-};
-
-}
-#endif
-
-
-
diff --git a/Swiften/Roster/Roster.cpp b/Swiften/Roster/Roster.cpp
index 8c2aa0e..c25fd41 100644
--- a/Swiften/Roster/Roster.cpp
+++ b/Swiften/Roster/Roster.cpp
@@ -13,79 +13,93 @@
#include "Swiften/Roster/RosterItem.h"
#include "Swiften/Roster/GroupRosterItem.h"
#include "Swiften/Roster/RosterItemOperation.h"
-#include "Swiften/Roster/TreeWidget.h"
-#include "Swiften/Roster/TreeWidgetFactory.h"
#include <boost/bind.hpp>
+#include <iostream>
#include <deque>
namespace Swift {
-Roster::Roster(TreeWidget *treeWidget, TreeWidgetFactory *widgetFactory) : treeWidget_(treeWidget), widgetFactory_(widgetFactory) {
+Roster::Roster() {
+ root_ = new GroupRosterItem("Dummy-Root", NULL);
}
Roster::~Roster() {
- foreach (RosterItem* item, items_) {
+ std::deque<RosterItem*> queue;
+ queue.push_back(root_);
+ while (!queue.empty()) {
+ RosterItem* item = *queue.begin();
+ queue.pop_front();
+ GroupRosterItem* group = dynamic_cast<GroupRosterItem*>(item);
+ if (group) {
+ queue.insert(queue.begin(), group->getChildren().begin(), group->getChildren().end());
+ }
delete item;
}
- delete treeWidget_;
}
-TreeWidget* Roster::getWidget() {
- return treeWidget_;
+GroupRosterItem* Roster::getRoot() {
+ return root_;
}
GroupRosterItem* Roster::getGroup(const String& groupName) {
- foreach (RosterItem *item, children_) {
+ foreach (RosterItem *item, root_->getChildren()) {
GroupRosterItem *group = dynamic_cast<GroupRosterItem*>(item);
- if (group && group->getName() == groupName) {
+ if (group && group->getDisplayName() == groupName) {
return group;
}
}
- GroupRosterItem* group = new GroupRosterItem(groupName, treeWidget_, widgetFactory_);
- children_.push_back(group);
- items_.push_back(group);
+ GroupRosterItem* group = new GroupRosterItem(groupName, root_);
+ root_->addChild(group);
+// std::cout << "Added " << groupName << " to root" << std::endl;
+ group->onChildrenChanged.connect(boost::bind(&Roster::handleChildrenChanged, this, group));
+ group->onDataChanged.connect(boost::bind(&Roster::handleDataChanged, this, group));
return group;
}
-void Roster::handleUserAction(boost::shared_ptr<UserRosterAction> action) {
- onUserAction(action);
+void Roster::handleDataChanged(RosterItem* item) {
+ onDataChanged(item);
}
-void Roster::addContact(const JID& jid, const String& name, const String& group) {
- ContactRosterItem *item = new ContactRosterItem(jid, name, getGroup(group), widgetFactory_);
- items_.push_back(item);
- itemMap_[jid.toBare()].push_back(item);
- item->onUserAction.connect(boost::bind(&Roster::handleUserAction, this, _1));
- filterItem(item);
+void Roster::handleChildrenChanged(GroupRosterItem* item) {
+ onChildrenChanged(item);
+}
+void Roster::addContact(const JID& jid, const String& name, const String& groupName) {
+ GroupRosterItem* group(getGroup(groupName));
+ ContactRosterItem *item = new ContactRosterItem(jid, name, group);
+ group->addChild(item);
+ itemMap_[jid.toBare()].push_back(item);
+ item->onDataChanged.connect(boost::bind(&Roster::handleDataChanged, this, item));
+ filterContact(item, group);
}
+
void Roster::removeContact(const JID& jid) {
- itemMap_.erase(jid.toBare());
- std::vector<RosterItem*>::iterator it = children_.begin();
- while (it != children_.end()) {
- ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(*it);
- if (contact && contact->getJID() == jid) {
- delete contact;
- it = children_.erase(it);
- continue;
- }
- GroupRosterItem* group = dynamic_cast<GroupRosterItem*>(*it);
- if (group) {
- group->removeChild(jid);
+ std::vector<ContactRosterItem*> items = itemMap_[jid.toBare()];
+ std::vector<ContactRosterItem*>::iterator it = items.begin();
+ while (it != items.end()) {
+ if (jid == (*it)->getJID()) {
+ it = items.erase(it);
}
- it++;
}
+ if (items.size() == 0) {
+ itemMap_.erase(jid.toBare());
+ }
+ //Causes the delete
+ root_->removeChild(jid);
}
void Roster::removeContactFromGroup(const JID& jid, const String& groupName) {
- std::vector<RosterItem*>::iterator it = children_.begin();
- while (it != children_.end()) {
+ std::vector<RosterItem*> children = root_->getChildren();
+ std::vector<RosterItem*>::iterator it = children.begin();
+ while (it != children.end()) {
GroupRosterItem* group = dynamic_cast<GroupRosterItem*>(*it);
- if (group && group->getName() == groupName) {
- group->removeChild(jid);
+ if (group && group->getDisplayName() == groupName) {
+ ContactRosterItem* deleted = group->removeChild(jid);
+ std::vector<ContactRosterItem*> items = itemMap_[jid.toBare()];
+ items.erase(std::remove(items.begin(), items.end(), deleted), items.end());
}
it++;
}
@@ -101,14 +115,15 @@ void Roster::applyOnItems(const RosterItemOperation& operation) {
}
void Roster::applyOnItem(const RosterItemOperation& operation, const JID& jid) {
- foreach (RosterItem* item, itemMap_[jid]) {
+ foreach (ContactRosterItem* item, itemMap_[jid.toBare()]) {
operation(item);
- filterItem(item);
+ filterContact(item, item->getParent());
}
}
void Roster::applyOnAllItems(const RosterItemOperation& operation) {
- std::deque<RosterItem*> queue(children_.begin(), children_.end());
+ std::deque<RosterItem*> queue;
+ queue.push_back(root_);
while (!queue.empty()) {
RosterItem* item = *queue.begin();
queue.pop_front();
@@ -131,29 +146,40 @@ void Roster::removeFilter(RosterFilter *filter) {
filterAll();
}
-
-void Roster::filterItem(RosterItem* rosterItem) {
- ContactRosterItem *item = dynamic_cast<ContactRosterItem*>(rosterItem);
- if (!item) {
- return;
- }
+void Roster::filterContact(ContactRosterItem* contact, GroupRosterItem* group) {
+ int oldDisplayedSize = group->getDisplayedChildren().size();
bool hide = true;
foreach (RosterFilter *filter, filters_) {
- hide &= (*filter)(item);
+ hide &= (*filter)(contact);
+ }
+ group->setDisplayed(contact, filters_.size() == 0 || !hide);
+ int newDisplayedSize = group->getDisplayedChildren().size();
+// std::cout << ", new size = " << newDisplayedSize << std::endl;
+ if (oldDisplayedSize == 0 && newDisplayedSize > 0) {
+// std::cout << "Newly created" << std::endl;
+ onGroupAdded(group);
+ }
+}
+
+void Roster::filterGroup(GroupRosterItem* group) {
+ foreach (RosterItem* child, group->getChildren()) {
+ ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(child);
+ if (contact) {
+ filterContact(contact, group);
+ }
}
- filters_.size() > 0 && hide ? item->hide() : item->show();
}
void Roster::filterAll() {
- std::deque<RosterItem*> queue(children_.begin(), children_.end());
+ std::deque<RosterItem*> queue;
+ queue.push_back(root_);
while (!queue.empty()) {
RosterItem *item = *queue.begin();
queue.pop_front();
GroupRosterItem* group = dynamic_cast<GroupRosterItem*>(item);
if (group) {
queue.insert(queue.begin(), group->getChildren().begin(), group->getChildren().end());
- } else {
- filterItem(item);
+ filterGroup(group);
}
}
}
diff --git a/Swiften/Roster/Roster.h b/Swiften/Roster/Roster.h
index 5fc3cfb..3af89d7 100644
--- a/Swiften/Roster/Roster.h
+++ b/Swiften/Roster/Roster.h
@@ -10,7 +10,6 @@
#include "Swiften/Base/String.h"
#include "Swiften/JID/JID.h"
#include "Swiften/Roster/RosterItemOperation.h"
-#include "Swiften/Roster/UserRosterAction.h"
#include "Swiften/Roster/RosterFilter.h"
#include <vector>
@@ -20,39 +19,38 @@
namespace Swift {
-class TreeWidgetFactory;
-class TreeWidget;
class RosterItem;
class GroupRosterItem;
+class ContactRosterItem;
class Roster {
public:
- Roster(TreeWidget *treeWidget, TreeWidgetFactory *widgetFactory);
+ Roster();
~Roster();
- TreeWidget* getWidget();
- GroupRosterItem* getGroup(const String& groupName);
void addContact(const JID& jid, const String& name, const String& group);
void removeContact(const JID& jid);
void removeContactFromGroup(const JID& jid, const String& group);
void applyOnItems(const RosterItemOperation& operation);
void applyOnAllItems(const RosterItemOperation& operation);
void applyOnItem(const RosterItemOperation& operation, const JID& jid);
- boost::signal<void (boost::shared_ptr<UserRosterAction>)> onUserAction;
- void addFilter(RosterFilter *filter) {filters_.push_back(filter);filterAll();}
+ void addFilter(RosterFilter *filter) {filters_.push_back(filter);filterAll();};
void removeFilter(RosterFilter *filter);
- std::vector<RosterFilter*> getFilters() {return filters_;}
-
+ GroupRosterItem* getRoot();
+ std::vector<RosterFilter*> getFilters() {return filters_;};
+ boost::signal<void (GroupRosterItem*)> onChildrenChanged;
+ boost::signal<void (GroupRosterItem*)> onGroupAdded;
+ boost::signal<void (RosterItem*)> onDataChanged;
private:
- void filterItem(RosterItem* item);
+ GroupRosterItem* getGroup(const String& groupName);
+ void handleDataChanged(RosterItem* item);
+ void handleChildrenChanged(GroupRosterItem* item);
+ void filterGroup(GroupRosterItem* item);
+ void filterContact(ContactRosterItem* contact, GroupRosterItem* group);
void filterAll();
- void handleUserAction(boost::shared_ptr<UserRosterAction> action);
- TreeWidget *treeWidget_;
- TreeWidgetFactory *widgetFactory_;
- std::vector<RosterItem*> children_;
- std::vector<RosterItem*> items_;
+ GroupRosterItem* root_;
std::vector<RosterFilter*> filters_;
- std::map<JID, std::vector<RosterItem*> > itemMap_;
+ std::map<JID, std::vector<ContactRosterItem*> > itemMap_;
};
}
diff --git a/Swiften/Roster/RosterItem.cpp b/Swiften/Roster/RosterItem.cpp
new file mode 100644
index 0000000..7229199
--- /dev/null
+++ b/Swiften/Roster/RosterItem.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2010 Kevin Smith
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include "Swiften/Roster/RosterItem.h"
+
+#include "Swiften/Roster/GroupRosterItem.h"
+
+namespace Swift {
+
+RosterItem::RosterItem(const String& name, GroupRosterItem* parent) : name_(name), parent_(parent) {
+ /* The following would be good, but because of C++'s inheritance not working in constructors, it's not going to work. */
+ //if (parent) {
+ // parent_->addChild(this);
+ //}
+}
+
+RosterItem::~RosterItem() {
+
+}
+
+GroupRosterItem* RosterItem::getParent() const {
+ return parent_;
+}
+
+void RosterItem::setDisplayName(const String& name) {
+ name_ = name;
+ sortableDisplayName_ = name_.getLowerCase();
+ onDataChanged();
+}
+
+String RosterItem::getDisplayName() const {
+ return name_;
+}
+
+String RosterItem::getSortableDisplayName() const {
+ return sortableDisplayName_;
+}
+
+
+}
+
diff --git a/Swiften/Roster/RosterItem.h b/Swiften/Roster/RosterItem.h
index 2c2a7e4..3a1a1b1 100644
--- a/Swiften/Roster/RosterItem.h
+++ b/Swiften/Roster/RosterItem.h
@@ -1,30 +1,32 @@
/*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
-#ifndef SWIFTEN_RosterItem_H
-#define SWIFTEN_RosterItem_H
-
-#include "Swiften/Roster/UserRosterAction.h"
+#pragma once
#include <boost/signal.hpp>
#include <boost/shared_ptr.hpp>
-namespace Swift {
+#include "Swiften/Base/String.h"
+namespace Swift {
+class GroupRosterItem;
class RosterItem {
public:
- virtual ~RosterItem() {};
- boost::signal<void (boost::shared_ptr<UserRosterAction>)> onUserAction;
- protected:
- void handleUserAction(boost::shared_ptr<UserRosterAction> action) {
- action->setRosterItem(this);
- onUserAction(action);
- }
+ RosterItem(const String& name, GroupRosterItem* parent);
+ virtual ~RosterItem();
+ boost::signal<void ()> onDataChanged;
+ GroupRosterItem* getParent() const;
+ void setDisplayName(const String& name);
+ String getDisplayName() const;
+ String getSortableDisplayName() const;
+ private:
+ String name_;
+ String sortableDisplayName_;
+ GroupRosterItem* parent_;
};
}
-#endif
diff --git a/Swiften/Roster/RosterItemOperation.h b/Swiften/Roster/RosterItemOperation.h
index a901fb4..e27e68b 100644
--- a/Swiften/Roster/RosterItemOperation.h
+++ b/Swiften/Roster/RosterItemOperation.h
@@ -17,6 +17,11 @@ class RosterItemOperation {
virtual ~RosterItemOperation() {};
bool requiresLookup() const {return requiresLookup_;};
const JID& lookupJID() const {return lookupJID_;};
+ /**
+ * This is called when iterating over possible subjects, so must check it's
+ * applying to the right items - even if requiresLookup() is true an item
+ * with the same bare JID but different full JID may be passed.
+ */
virtual void operator() (RosterItem*) const = 0;
private:
bool requiresLookup_;
diff --git a/Swiften/Roster/SetName.h b/Swiften/Roster/SetName.h
index 33dd521..d3f7749 100644
--- a/Swiften/Roster/SetName.h
+++ b/Swiften/Roster/SetName.h
@@ -22,7 +22,7 @@ class SetName : public RosterItemOperation {
virtual void operator() (RosterItem* item) const {
ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(item);
if (contact && contact->getJID().equals(jid_, compareType_)) {
- contact->setName(name_);
+ contact->setDisplayName(name_);
}
}
diff --git a/Swiften/Roster/SetPresence.h b/Swiften/Roster/SetPresence.h
index 9cc3ba9..134a63d 100644
--- a/Swiften/Roster/SetPresence.h
+++ b/Swiften/Roster/SetPresence.h
@@ -4,8 +4,7 @@
* See Documentation/Licenses/GPLv3.txt for more information.
*/
-#ifndef SWIFTEN_SetPresence_H
-#define SWIFTEN_SetPresence_H
+#pragma once
#include "Swiften/Elements/Presence.h"
#include "Swiften/JID/JID.h"
@@ -24,13 +23,7 @@ class SetPresence : public RosterItemOperation {
virtual void operator() (RosterItem* item) const {
ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(item);
if (contact && contact->getJID().equals(presence_->getFrom(), compareType_)) {
- if (presence_->getType() != Presence::Available) {
- contact->setStatusShow(StatusShow::None);
- contact->setStatusText(presence_->getStatus());
- } else {
- contact->setStatusShow(presence_->getShow());
- contact->setStatusText(presence_->getStatus());
- }
+ contact->applyPresence(presence_->getFrom().getResource(), presence_);
}
}
@@ -40,5 +33,4 @@ class SetPresence : public RosterItemOperation {
};
}
-#endif
diff --git a/Swiften/Roster/TreeWidget.h b/Swiften/Roster/TreeWidget.h
deleted file mode 100644
index 78b67b7..0000000
--- a/Swiften/Roster/TreeWidget.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (c) 2010 Remko Tronçon
- * Licensed under the GNU General Public License v3.
- * See Documentation/Licenses/GPLv3.txt for more information.
- */
-
-#ifndef SWIFTEN_TreeWidget_H
-#define SWIFTEN_TreeWidget_H
-
-namespace Swift {
-
-class TreeWidget {
- public:
- virtual ~TreeWidget() {}
-};
-
-}
-#endif
-
diff --git a/Swiften/Roster/TreeWidgetFactory.h b/Swiften/Roster/TreeWidgetFactory.h
deleted file mode 100644
index fbc4417..0000000
--- a/Swiften/Roster/TreeWidgetFactory.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2010 Remko Tronçon
- * Licensed under the GNU General Public License v3.
- * See Documentation/Licenses/GPLv3.txt for more information.
- */
-
-#ifndef SWIFTEN_TreeWidgetFactory_H
-#define SWIFTEN_TreeWidgetFactory_H
-
-namespace Swift {
-
-class TreeWidgetItem;
-class TreeWidget;
-
-class TreeWidgetFactory {
- public:
- virtual ~TreeWidgetFactory() {}
- virtual TreeWidget* createTreeWidget() = 0;
- virtual TreeWidgetItem* createTreeWidgetItem(TreeWidgetItem* item) = 0;
- virtual TreeWidgetItem* createTreeWidgetItem(TreeWidget* item) = 0;
-};
-
-}
-
-#endif
-
diff --git a/Swiften/Roster/TreeWidgetItem.h b/Swiften/Roster/TreeWidgetItem.h
deleted file mode 100644
index 1718776..0000000
--- a/Swiften/Roster/TreeWidgetItem.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2010 Remko Tronçon
- * Licensed under the GNU General Public License v3.
- * See Documentation/Licenses/GPLv3.txt for more information.
- */
-
-#ifndef SWIFTEN_TreeWidgetItem_H
-#define SWIFTEN_TreeWidgetItem_H
-
-#include "Swiften/Base/String.h"
-#include "Swiften/Roster/UserRosterAction.h"
-#include "Swiften/Elements/StatusShow.h"
-
-#include <boost/signal.hpp>
-#include <boost/shared_ptr.hpp>
-
-namespace Swift {
-
-class TreeWidgetItem {
- public:
- virtual ~TreeWidgetItem() {}
- virtual void setText(const String& text) = 0;
- virtual void setStatusText(const String& text) = 0;
- virtual void setAvatarPath(const String& path) = 0;
- virtual void setExpanded(bool b) = 0;
- //virtual void setTextColor(unsigned long color) = 0;
- virtual void setStatusShow(StatusShow::Type show) = 0;
- //virtual void setBackgroundColor(unsigned long color) = 0;
- boost::signal<void (boost::shared_ptr<UserRosterAction>)> onUserAction;
- virtual void show() = 0;
- virtual void hide() = 0;
- void performUserAction(boost::shared_ptr<UserRosterAction> action) {
- action->setTreeWidgetItem(this);
- onUserAction(action);
- }
-};
-
-}
-#endif
-
diff --git a/Swiften/Roster/UnitTest/MockTreeWidget.h b/Swiften/Roster/UnitTest/MockTreeWidget.h
deleted file mode 100644
index 97dd796..0000000
--- a/Swiften/Roster/UnitTest/MockTreeWidget.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (c) 2010 Kevin Smith
- * Licensed under the GNU General Public License v3.
- * See Documentation/Licenses/GPLv3.txt for more information.
- */
-
-#ifndef SWIFTEN_MockTreeWidget_H
-#define SWIFTEN_MockTreeWidget_H
-
-#include "Swiften/Roster/TreeWidget.h"
-
-namespace Swift {
-
-class MockTreeWidget : public TreeWidget {
- public:
- virtual ~MockTreeWidget() {}
-};
-
-}
-#endif
diff --git a/Swiften/Roster/UnitTest/MockTreeWidgetFactory.h b/Swiften/Roster/UnitTest/MockTreeWidgetFactory.h
deleted file mode 100644
index d94c859..0000000
--- a/Swiften/Roster/UnitTest/MockTreeWidgetFactory.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (c) 2010 Kevin Smith
- * Licensed under the GNU General Public License v3.
- * See Documentation/Licenses/GPLv3.txt for more information.
- */
-
-#ifndef SWIFTEN_MockTreeWidgetFactory_H
-#define SWIFTEN_MockTreeWidgetFactory_H
-
-#include "Swiften/Roster/TreeWidgetFactory.h"
-
-#include <vector>
-#include "Swiften/Base/foreach.h"
-#include "Swiften/Roster/UnitTest/MockTreeWidget.h"
-#include "Swiften/Roster/UnitTest/MockTreeWidgetItem.h"
-
-namespace Swift {
-
-class MockTreeWidgetItem;
-class MockTreeWidget;
-
-class MockTreeWidgetFactory : public TreeWidgetFactory {
- public:
- virtual ~MockTreeWidgetFactory() {}
- virtual TreeWidget* createTreeWidget() {
- root_ = new MockTreeWidget();
- return root_;
- };
- virtual TreeWidgetItem* createTreeWidgetItem(TreeWidgetItem* group) {
- MockTreeWidgetItem* entry = new MockTreeWidgetItem(this);
- groupMembers_[group].push_back(entry);
- return entry;
- };
- virtual TreeWidgetItem* createTreeWidgetItem(TreeWidget*) {
- MockTreeWidgetItem* group = new MockTreeWidgetItem(this);
- groups_.push_back(group);
- return group;
- };
- virtual std::vector<String> getGroups() {
- std::vector<String> groupNames;
- foreach (MockTreeWidgetItem* group, groups_) {
- groupNames.push_back(group->getText());
- }
- return groupNames;
- };
-
- typedef std::map<TreeWidgetItem*, std::vector<MockTreeWidgetItem*> > itemMap;
-
- virtual std::vector<MockTreeWidgetItem*> getGroupMembers(const String& group) {
- for (itemMap::iterator it = groupMembers_.begin(); it != groupMembers_.end(); it++) {
- if (((MockTreeWidgetItem*)(it->first))->getText() == group) {
- return it->second;
- }
- }
- return std::vector<MockTreeWidgetItem*>();
- };
-
- virtual void removeItem(MockTreeWidgetItem* item) {
- foreach (TreeWidgetItem* groupItem, groups_) {
- std::vector<MockTreeWidgetItem*>& members = groupMembers_[groupItem];
- members.erase(std::remove(members.begin(), members.end(), item), members.end());
- }
- };
- private:
- std::vector<MockTreeWidgetItem*> groups_;
- std::map<TreeWidgetItem*, std::vector<MockTreeWidgetItem*> > groupMembers_;
- MockTreeWidget* root_;
-};
-
-}
-
-#endif
-
-
diff --git a/Swiften/Roster/UnitTest/MockTreeWidgetItem.cpp b/Swiften/Roster/UnitTest/MockTreeWidgetItem.cpp
deleted file mode 100644
index 4238ead..0000000
--- a/Swiften/Roster/UnitTest/MockTreeWidgetItem.cpp
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (c) 2010 Kevin Smith
- * Licensed under the GNU General Public License v3.
- * See Documentation/Licenses/GPLv3.txt for more information.
- */
-#include "Swiften/Roster/UnitTest/MockTreeWidgetItem.h"
-
-#include "Swiften/Roster/UnitTest/MockTreeWidgetFactory.h"
-
-namespace Swift {
-
-MockTreeWidgetItem::~MockTreeWidgetItem() {
- factory_->removeItem(this);
-}
-
-}
-
-
-
diff --git a/Swiften/Roster/UnitTest/MockTreeWidgetItem.h b/Swiften/Roster/UnitTest/MockTreeWidgetItem.h
deleted file mode 100644
index 08b9f1a..0000000
--- a/Swiften/Roster/UnitTest/MockTreeWidgetItem.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2010 Kevin Smith
- * Licensed under the GNU General Public License v3.
- * See Documentation/Licenses/GPLv3.txt for more information.
- */
-
-#ifndef SWIFTEN_MockTreeWidgetItem_H
-#define SWIFTEN_MockTreeWidgetItem_H
-
-#include "Swiften/Base/String.h"
-#include "Swiften/Roster/TreeWidgetItem.h"
-
-#include <boost/signal.hpp>
-#include <boost/shared_ptr.hpp>
-
-namespace Swift {
- class MockTreeWidgetFactory;
-class MockTreeWidgetItem : public TreeWidgetItem {
- public:
- MockTreeWidgetItem(MockTreeWidgetFactory* factory) {factory_ = factory;};
- virtual ~MockTreeWidgetItem();
- virtual void setText(const String& text) {text_ = text;};
- String getText() {return text_;};
- virtual void setStatusText(const String&) {};
- virtual void setAvatarPath(const String&) {};
- virtual void setExpanded(bool) {};
- virtual void setStatusShow(StatusShow::Type /*show*/) {};
- virtual void show() {};
- virtual void hide() {};
- private:
- String text_;
- MockTreeWidgetFactory* factory_;
-};
-
-}
-#endif
-
-
diff --git a/Swiften/Roster/UnitTest/RosterTest.cpp b/Swiften/Roster/UnitTest/RosterTest.cpp
index 5a2a3e3..f9dff33 100644
--- a/Swiften/Roster/UnitTest/RosterTest.cpp
+++ b/Swiften/Roster/UnitTest/RosterTest.cpp
@@ -9,9 +9,7 @@
#include <boost/shared_ptr.hpp>
#include "Swiften/Roster/Roster.h"
-#include "Swiften/Roster/UnitTest/MockTreeWidget.h"
-#include "Swiften/Roster/UnitTest/MockTreeWidgetFactory.h"
-#include "Swiften/Roster/UnitTest/MockTreeWidgetItem.h"
+#include "Swiften/Roster/GroupRosterItem.h"
using namespace Swift;
@@ -23,8 +21,6 @@ class RosterTest : public CppUnit::TestFixture
private:
Roster *roster_;
- TreeWidget *widget_;
- TreeWidgetFactory *factory_;
JID jid1_;
JID jid2_;
JID jid3_;
@@ -34,15 +30,11 @@ class RosterTest : public CppUnit::TestFixture
RosterTest() : jid1_(JID("a@b.c")), jid2_(JID("b@c.d")), jid3_(JID("c@d.e")) {}
void setUp() {
- factory_ = new MockTreeWidgetFactory();
- widget_ = factory_->createTreeWidget();
- roster_ = new Roster(widget_, factory_);
+ roster_ = new Roster();
}
void tearDown() {
delete roster_;
- //delete widget_;
- delete factory_;
}
void testGetGroup() {
@@ -50,12 +42,13 @@ class RosterTest : public CppUnit::TestFixture
roster_->addContact(jid2_, "Ernie", "group2");
roster_->addContact(jid3_, "Cookie", "group1");
- CPPUNIT_ASSERT_EQUAL(roster_->getGroup("group1"), roster_->getGroup("group1"));
- CPPUNIT_ASSERT_EQUAL(roster_->getGroup("group2"), roster_->getGroup("group2"));
- CPPUNIT_ASSERT_EQUAL(roster_->getGroup("group3"), roster_->getGroup("group3"));
- CPPUNIT_ASSERT(roster_->getGroup("group1") != roster_->getGroup("group2"));
- CPPUNIT_ASSERT(roster_->getGroup("group2") != roster_->getGroup("group3"));
- CPPUNIT_ASSERT(roster_->getGroup("group3") != roster_->getGroup("group1"));
+ CPPUNIT_ASSERT_EQUAL(2, (int)roster_->getRoot()->getChildren().size());
+ CPPUNIT_ASSERT_EQUAL(String("group1"), roster_->getRoot()->getChildren()[0]->getDisplayName());
+ CPPUNIT_ASSERT_EQUAL(String("group2"), roster_->getRoot()->getChildren()[1]->getDisplayName());
+ CPPUNIT_ASSERT_EQUAL(String("Bert"), ((GroupRosterItem*)roster_->getRoot()->getChildren()[0])->getChildren()[0]->getDisplayName());
+ CPPUNIT_ASSERT_EQUAL(String("Cookie"), ((GroupRosterItem*)roster_->getRoot()->getChildren()[0])->getChildren()[1]->getDisplayName());
+ CPPUNIT_ASSERT_EQUAL(String("Ernie"), ((GroupRosterItem*)roster_->getRoot()->getChildren()[1])->getChildren()[0]->getDisplayName());
+
}
};
diff --git a/Swiften/Roster/UserRosterAction.h b/Swiften/Roster/UserRosterAction.h
deleted file mode 100644
index b869530..0000000
--- a/Swiften/Roster/UserRosterAction.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2010 Remko Tronçon
- * Licensed under the GNU General Public License v3.
- * See Documentation/Licenses/GPLv3.txt for more information.
- */
-
-#ifndef SWIFTEN_UserRosterAction_H
-#define SWIFTEN_UserRosterAction_H
-
-namespace Swift {
-class RosterItem;
-class TreeWidgetItem;
-
-class UserRosterAction {
- public:
- virtual ~UserRosterAction() {};
- void setRosterItem(RosterItem *item) {
- rosterItem_ = item;
- };
- void setTreeWidgetItem(TreeWidgetItem *item) {
- treeWidgetItem_ = item;
- }
- RosterItem* getRosterItem() {
- return rosterItem_;
- }
- TreeWidgetItem* getTreeWidgetItem() {
- return treeWidgetItem_;
- }
-
- private:
- RosterItem *rosterItem_;
- TreeWidgetItem *treeWidgetItem_;
-};
-
-}
-#endif
-
-