diff options
Diffstat (limited to 'Swiften')
23 files changed, 398 insertions, 507 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 - - diff --git a/Swiften/SConscript b/Swiften/SConscript index dfda3ba..a95635a 100644 --- a/Swiften/SConscript +++ b/Swiften/SConscript @@ -54,6 +54,8 @@ if env["SCONS_STAGE"] == "build" : "Queries/Responders/DiscoInfoResponder.cpp", "Queries/Responders/SoftwareVersionResponder.cpp", "Roster/ContactRosterItem.cpp", + "Roster/GroupRosterItem.cpp", + "Roster/RosterItem.cpp", "Roster/Roster.cpp", "Roster/XMPPRoster.cpp", "Serializer/AuthRequestSerializer.cpp", @@ -191,7 +193,6 @@ if env["SCONS_STAGE"] == "build" : File("Roster/UnitTest/OfflineRosterFilterTest.cpp"), File("Roster/UnitTest/RosterTest.cpp"), File("Roster/UnitTest/XMPPRosterTest.cpp"), - File("Roster/UnitTest/MockTreeWidgetItem.cpp"), File("SASL/UnitTest/PLAINMessageTest.cpp"), File("SASL/UnitTest/PLAINClientAuthenticatorTest.cpp"), File("SASL/UnitTest/SCRAMSHA1ClientAuthenticatorTest.cpp"), |