summaryrefslogtreecommitdiff
path: root/TelepathyQt4
diff options
context:
space:
mode:
authorAndre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk>2010-12-17 10:53:17 -0200
committerAndre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk>2010-12-17 10:53:19 -0200
commite07a978b22b6131b2179105b1dc0f0d553f55e4c (patch)
tree78766681651a931b412f7515fbb6f0ad39398a83 /TelepathyQt4
parent4c9d8c0e36aa6ccde48cb8595dacb08bb1ff934f (diff)
parent4362905adca6e756ca2b0bddd78a6bfc11199195 (diff)
Merge branch 'contact-sanitize'
Reviewed-by: Olli Salli (oggis) <olli.salli@collabora.co.uk>
Diffstat (limited to 'TelepathyQt4')
-rw-r--r--TelepathyQt4/contact-manager.cpp687
-rw-r--r--TelepathyQt4/contact-manager.h2
-rw-r--r--TelepathyQt4/contact.cpp102
-rw-r--r--TelepathyQt4/contact.h4
4 files changed, 402 insertions, 393 deletions
diff --git a/TelepathyQt4/contact-manager.cpp b/TelepathyQt4/contact-manager.cpp
index d868880c..21e47cdf 100644
--- a/TelepathyQt4/contact-manager.cpp
+++ b/TelepathyQt4/contact-manager.cpp
@@ -25,11 +25,7 @@
#include "TelepathyQt4/_gen/contact-manager.moc.hpp"
#include "TelepathyQt4/_gen/contact-manager-internal.moc.hpp"
-#include <QMap>
-#include <QPointer>
-#include <QString>
-#include <QSet>
-#include <QWeakPointer>
+#include "TelepathyQt4/debug-internal.h"
#include <TelepathyQt4/AvatarData>
#include <TelepathyQt4/Connection>
@@ -42,7 +38,8 @@
#include <TelepathyQt4/ReferencedHandles>
#include <TelepathyQt4/Utils>
-#include "TelepathyQt4/debug-internal.h"
+#include <QMap>
+#include <QWeakPointer>
namespace Tp
{
@@ -57,51 +54,34 @@ namespace Tp
struct TELEPATHY_QT4_NO_EXPORT ContactManager::Private
{
- Private(ContactManager *parent, Connection *connection)
- : parent(parent), connection(connection), requestAvatarsIdle(false)
- {
- }
+ Private(ContactManager *parent, Connection *connection);
- QString addContactListGroupChannel(const ChannelPtr &contactListGroupChannel)
- {
- QString id = contactListGroupChannel->immutableProperties().value(
- QLatin1String(TELEPATHY_INTERFACE_CHANNEL ".TargetID")).toString();
- contactListGroupChannels.insert(id, contactListGroupChannel);
- parent->connect(contactListGroupChannel.data(),
- SIGNAL(groupMembersChanged(
- Tp::Contacts,
- Tp::Contacts,
- Tp::Contacts,
- Tp::Contacts,
- Tp::Channel::GroupMemberChangeDetails)),
- SLOT(onContactListGroupMembersChanged(
- Tp::Contacts,
- Tp::Contacts,
- Tp::Contacts,
- Tp::Contacts,
- Tp::Channel::GroupMemberChangeDetails)));
- parent->connect(contactListGroupChannel.data(),
- SIGNAL(invalidated(Tp::DBusProxy*,QString,QString)),
- SLOT(onContactListGroupRemoved(Tp::DBusProxy*,QString,QString)));
-
- foreach (const ContactPtr &contact, contactListGroupChannel->groupContacts()) {
- contact->setAddedToGroup(id);
- }
- return id;
- }
+ void ensureTracking(const Feature &feature);
+
+ // roster specific methods
+ Contacts allKnownContacts() const;
+ void computeKnownContactsChanges(const Contacts &added,
+ const Contacts &pendingAdded, const Contacts &remotePendingAdded,
+ const Contacts &removed, const Channel::GroupMemberChangeDetails &details);
+ void updateContactsPresenceState();
- class PendingContactManagerRemoveContactListGroup;
+ // roster group specific methods
+ QString addContactListGroupChannel(const ChannelPtr &contactListGroupChannel);
+
+ // avatar specific methods
+ bool buildAvatarFileName(QString token, bool createDir,
+ QString &avatarFileName, QString &mimeTypeFileName);
ContactManager *parent;
QWeakPointer<Connection> connection;
+
QMap<uint, QWeakPointer<Contact> > contacts;
- Contacts cachedAllKnownContacts;
QMap<Feature, bool> tracking;
- void ensureTracking(const Feature &feature);
-
Features supportedFeatures;
+ // roster
+ Contacts cachedAllKnownContacts;
QMap<uint, ContactListChannel> contactListChannels;
ChannelPtr subscribeChannel;
ChannelPtr publishChannel;
@@ -109,23 +89,245 @@ struct TELEPATHY_QT4_NO_EXPORT ContactManager::Private
ChannelPtr denyChannel;
QMap<QString, ChannelPtr> contactListGroupChannels;
- Contacts allKnownContacts() const;
- void updateContactsPresenceState();
- void computeKnownContactsChanges(const Contacts &added,
- const Contacts &pendingAdded,
- const Contacts &remotePendingAdded,
- const Contacts &removed,
- const Channel::GroupMemberChangeDetails &details);
-
- bool buildAvatarFileName(QString token, bool createDir,
- QString &avatarFileName, QString &mimeTypeFileName);
+ // avatar
UIntList requestAvatarsQueue;
bool requestAvatarsIdle;
};
-ConnectionPtr ContactManager::connection() const
+ContactManager::Private::Private(ContactManager *parent, Connection *connection)
+ : parent(parent),
+ connection(connection),
+ requestAvatarsIdle(false)
{
- return ConnectionPtr(mPriv->connection);
+}
+
+void ContactManager::Private::ensureTracking(const Feature &feature)
+{
+ if (tracking[feature]) {
+ return;
+ }
+
+ ConnectionPtr conn(parent->connection());
+
+ if (feature == Contact::FeatureAlias) {
+ Client::ConnectionInterfaceAliasingInterface *aliasingInterface =
+ conn->interface<Client::ConnectionInterfaceAliasingInterface>();
+
+ parent->connect(
+ aliasingInterface,
+ SIGNAL(AliasesChanged(Tp::AliasPairList)),
+ SLOT(onAliasesChanged(Tp::AliasPairList)));
+ } else if (feature == Contact::FeatureAvatarData) {
+ Client::ConnectionInterfaceAvatarsInterface *avatarsInterface =
+ conn->interface<Client::ConnectionInterfaceAvatarsInterface>();
+
+ parent->connect(
+ avatarsInterface,
+ SIGNAL(AvatarRetrieved(uint,QString,QByteArray,QString)),
+ SLOT(onAvatarRetrieved(uint,QString,QByteArray,QString)));
+ } else if (feature == Contact::FeatureAvatarToken) {
+ Client::ConnectionInterfaceAvatarsInterface *avatarsInterface =
+ conn->interface<Client::ConnectionInterfaceAvatarsInterface>();
+
+ parent->connect(
+ avatarsInterface,
+ SIGNAL(AvatarUpdated(uint,QString)),
+ SLOT(onAvatarUpdated(uint,QString)));
+ } else if (feature == Contact::FeatureCapabilities) {
+ Client::ConnectionInterfaceContactCapabilitiesInterface *contactCapabilitiesInterface =
+ conn->interface<Client::ConnectionInterfaceContactCapabilitiesInterface>();
+
+ parent->connect(
+ contactCapabilitiesInterface,
+ SIGNAL(ContactCapabilitiesChanged(Tp::ContactCapabilitiesMap)),
+ SLOT(onCapabilitiesChanged(Tp::ContactCapabilitiesMap)));
+ } else if (feature == Contact::FeatureInfo) {
+ Client::ConnectionInterfaceContactInfoInterface *contactInfoInterface =
+ conn->interface<Client::ConnectionInterfaceContactInfoInterface>();
+
+ parent->connect(
+ contactInfoInterface,
+ SIGNAL(ContactInfoChanged(uint,Tp::ContactInfoFieldList)),
+ SLOT(onContactInfoChanged(uint,Tp::ContactInfoFieldList)));
+ } else if (feature == Contact::FeatureLocation) {
+ Client::ConnectionInterfaceLocationInterface *locationInterface =
+ conn->interface<Client::ConnectionInterfaceLocationInterface>();
+
+ parent->connect(
+ locationInterface,
+ SIGNAL(LocationUpdated(uint,QVariantMap)),
+ SLOT(onLocationUpdated(uint,QVariantMap)));
+ } else if (feature == Contact::FeatureSimplePresence) {
+ Client::ConnectionInterfaceSimplePresenceInterface *simplePresenceInterface =
+ conn->interface<Client::ConnectionInterfaceSimplePresenceInterface>();
+
+ parent->connect(
+ simplePresenceInterface,
+ SIGNAL(PresencesChanged(Tp::SimpleContactPresences)),
+ SLOT(onPresencesChanged(Tp::SimpleContactPresences)));
+ } else {
+ warning() << " Unknown feature" << feature
+ << "when trying to figure out how to connect change notification!";
+ }
+
+ tracking[feature] = true;
+}
+
+Contacts ContactManager::Private::allKnownContacts() const
+{
+ Contacts contacts;
+ foreach (const ContactListChannel &contactListChannel, contactListChannels) {
+ ChannelPtr channel = contactListChannel.channel;
+ if (!channel) {
+ continue;
+ }
+ contacts.unite(channel->groupContacts());
+ contacts.unite(channel->groupLocalPendingContacts());
+ contacts.unite(channel->groupRemotePendingContacts());
+ }
+ return contacts;
+}
+
+void ContactManager::Private::computeKnownContactsChanges(const Tp::Contacts& added,
+ const Tp::Contacts& pendingAdded, const Tp::Contacts& remotePendingAdded,
+ const Tp::Contacts& removed, const Channel::GroupMemberChangeDetails &details)
+{
+ // First of all, compute the real additions/removals based upon our cache
+ Tp::Contacts realAdded;
+ realAdded.unite(added);
+ realAdded.unite(pendingAdded);
+ realAdded.unite(remotePendingAdded);
+ realAdded.subtract(cachedAllKnownContacts);
+ Tp::Contacts realRemoved = removed;
+ realRemoved.intersect(cachedAllKnownContacts);
+
+ // Check if realRemoved have been _really_ removed from all lists
+ foreach (const ContactListChannel &contactListChannel, contactListChannels) {
+ ChannelPtr channel = contactListChannel.channel;
+ if (!channel) {
+ continue;
+ }
+ realRemoved.subtract(channel->groupContacts());
+ realRemoved.subtract(channel->groupLocalPendingContacts());
+ realRemoved.subtract(channel->groupRemotePendingContacts());
+ }
+
+ // Are there any real changes?
+ if (!realAdded.isEmpty() || !realRemoved.isEmpty()) {
+ // Yes, update our "cache" and emit the signal
+ cachedAllKnownContacts.unite(realAdded);
+ cachedAllKnownContacts.subtract(realRemoved);
+ emit parent->allKnownContactsChanged(realAdded, realRemoved, details);
+ }
+}
+
+void ContactManager::Private::updateContactsPresenceState()
+{
+ Contacts subscribeContacts;
+ Contacts subscribeContactsRP;
+
+ if (subscribeChannel) {
+ subscribeContacts = subscribeChannel->groupContacts();
+ subscribeContactsRP = subscribeChannel->groupRemotePendingContacts();
+ }
+
+ Contacts publishContacts;
+ Contacts publishContactsLP;
+ if (publishChannel) {
+ publishContacts = publishChannel->groupContacts();
+ publishContactsLP = publishChannel->groupLocalPendingContacts();
+ }
+
+ Contacts denyContacts;
+ if (denyChannel) {
+ denyContacts = denyChannel->groupContacts();
+ }
+
+ if (!subscribeChannel && !publishChannel && !denyChannel) {
+ return;
+ }
+
+ Contacts contacts = allKnownContacts();
+ foreach (ContactPtr contact, contacts) {
+ if (subscribeChannel) {
+ // not in "subscribe" -> No, in "subscribe" lp -> Ask, in "subscribe" current -> Yes
+ if (subscribeContacts.contains(contact)) {
+ contact->setSubscriptionState(Contact::PresenceStateYes);
+ } else if (subscribeContactsRP.contains(contact)) {
+ contact->setSubscriptionState(Contact::PresenceStateAsk);
+ } else {
+ contact->setSubscriptionState(Contact::PresenceStateNo);
+ }
+ }
+
+ if (publishChannel) {
+ // not in "publish" -> No, in "subscribe" rp -> Ask, in "publish" current -> Yes
+ if (publishContacts.contains(contact)) {
+ contact->setPublishState(Contact::PresenceStateYes);
+ } else if (publishContactsLP.contains(contact)) {
+ contact->setPublishState(Contact::PresenceStateAsk);
+ } else {
+ contact->setPublishState(Contact::PresenceStateNo);
+ }
+ }
+
+ if (denyChannel) {
+ if (denyContacts.contains(contact)) {
+ contact->setBlocked(true);
+ }
+ }
+ }
+}
+
+QString ContactManager::Private::addContactListGroupChannel(
+ const ChannelPtr &contactListGroupChannel)
+{
+ QString id = contactListGroupChannel->immutableProperties().value(
+ QLatin1String(TELEPATHY_INTERFACE_CHANNEL ".TargetID")).toString();
+ contactListGroupChannels.insert(id, contactListGroupChannel);
+ parent->connect(contactListGroupChannel.data(),
+ SIGNAL(groupMembersChanged(
+ Tp::Contacts,
+ Tp::Contacts,
+ Tp::Contacts,
+ Tp::Contacts,
+ Tp::Channel::GroupMemberChangeDetails)),
+ SLOT(onContactListGroupMembersChanged(
+ Tp::Contacts,
+ Tp::Contacts,
+ Tp::Contacts,
+ Tp::Contacts,
+ Tp::Channel::GroupMemberChangeDetails)));
+ parent->connect(contactListGroupChannel.data(),
+ SIGNAL(invalidated(Tp::DBusProxy*,QString,QString)),
+ SLOT(onContactListGroupRemoved(Tp::DBusProxy*,QString,QString)));
+
+ foreach (const ContactPtr &contact, contactListGroupChannel->groupContacts()) {
+ contact->setAddedToGroup(id);
+ }
+ return id;
+}
+
+bool ContactManager::Private::buildAvatarFileName(QString token, bool createDir,
+ QString &avatarFileName, QString &mimeTypeFileName)
+{
+ QString cacheDir = QString(QLatin1String(qgetenv("XDG_CACHE_HOME")));
+ if (cacheDir.isEmpty()) {
+ cacheDir = QString(QLatin1String("%1/.cache")).arg(QLatin1String(qgetenv("HOME")));
+ }
+
+ ConnectionPtr conn(parent->connection());
+ QString path = QString(QLatin1String("%1/telepathy/avatars/%2/%3")).
+ arg(cacheDir).arg(conn->cmName()).arg(conn->protocolName());
+
+ if (createDir && !QDir().mkpath(path)) {
+ return false;
+ }
+
+ avatarFileName = QString(QLatin1String("%1/%2")).arg(path).arg(escapeAsIdentifier(token));
+ mimeTypeFileName = QString(QLatin1String("%1.mime")).arg(avatarFileName);
+
+ return true;
}
namespace
@@ -156,6 +358,22 @@ QString featureToInterface(const Feature &feature)
}
+ContactManager::ContactManager(Connection *connection)
+ : Object(),
+ mPriv(new Private(this, connection))
+{
+}
+
+ContactManager::~ContactManager()
+{
+ delete mPriv;
+}
+
+ConnectionPtr ContactManager::connection() const
+{
+ return ConnectionPtr(mPriv->connection);
+}
+
Features ContactManager::supportedFeatures() const
{
if (mPriv->supportedFeatures.isEmpty() &&
@@ -943,55 +1161,19 @@ PendingContacts *ContactManager::upgradeContacts(const QList<ContactPtr> &contac
return new PendingContacts(ContactManagerPtr(this), contacts, features);
}
-void ContactManager::onAliasesChanged(const AliasPairList &aliases)
+ContactPtr ContactManager::lookupContactByHandle(uint handle)
{
- debug() << "Got AliasesChanged for" << aliases.size() << "contacts";
-
- foreach (AliasPair pair, aliases) {
- ContactPtr contact = lookupContactByHandle(pair.handle);
+ ContactPtr contact;
- if (contact) {
- contact->receiveAlias(pair.alias);
+ if (mPriv->contacts.contains(handle)) {
+ contact = ContactPtr(mPriv->contacts.value(handle));
+ if (!contact) {
+ // Dangling weak pointer, remove it
+ mPriv->contacts.remove(handle);
}
}
-}
-bool ContactManager::Private::buildAvatarFileName(QString token, bool createDir,
- QString &avatarFileName, QString &mimeTypeFileName)
-{
- QString cacheDir = QString(QLatin1String(qgetenv("XDG_CACHE_HOME")));
- if (cacheDir.isEmpty()) {
- cacheDir = QString(QLatin1String("%1/.cache")).arg(QLatin1String(qgetenv("HOME")));
- }
-
- ConnectionPtr conn(parent->connection());
- QString path = QString(QLatin1String("%1/telepathy/avatars/%2/%3")).
- arg(cacheDir).arg(conn->cmName()).arg(conn->protocolName());
-
- if (createDir && !QDir().mkpath(path)) {
- return false;
- }
-
- avatarFileName = QString(QLatin1String("%1/%2")).arg(path).arg(escapeAsIdentifier(token));
- mimeTypeFileName = QString(QLatin1String("%1.mime")).arg(avatarFileName);
-
- return true;
-}
-
-void ContactManager::doRequestAvatars()
-{
- debug() << "Request" << mPriv->requestAvatarsQueue.size() << "avatar(s)";
-
- Client::ConnectionInterfaceAvatarsInterface *avatarsInterface =
- connection()->interface<Client::ConnectionInterfaceAvatarsInterface>();
- QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(
- avatarsInterface->RequestAvatars(mPriv->requestAvatarsQueue),
- this);
- connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), watcher,
- SLOT(deleteLater()));
-
- mPriv->requestAvatarsQueue = UIntList();
- mPriv->requestAvatarsIdle = false;
+ return contact;
}
void ContactManager::requestContactAvatar(Contact *contact)
@@ -1029,6 +1211,35 @@ void ContactManager::requestContactAvatar(Contact *contact)
mPriv->requestAvatarsQueue.append(contact->handle()[0]);
}
+void ContactManager::onAliasesChanged(const AliasPairList &aliases)
+{
+ debug() << "Got AliasesChanged for" << aliases.size() << "contacts";
+
+ foreach (AliasPair pair, aliases) {
+ ContactPtr contact = lookupContactByHandle(pair.handle);
+
+ if (contact) {
+ contact->receiveAlias(pair.alias);
+ }
+ }
+}
+
+void ContactManager::doRequestAvatars()
+{
+ debug() << "Request" << mPriv->requestAvatarsQueue.size() << "avatar(s)";
+
+ Client::ConnectionInterfaceAvatarsInterface *avatarsInterface =
+ connection()->interface<Client::ConnectionInterfaceAvatarsInterface>();
+ QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(
+ avatarsInterface->RequestAvatars(mPriv->requestAvatarsQueue),
+ this);
+ connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), watcher,
+ SLOT(deleteLater()));
+
+ mPriv->requestAvatarsQueue = UIntList();
+ mPriv->requestAvatarsIdle = false;
+}
+
void ContactManager::onAvatarUpdated(uint handle, const QString &token)
{
debug() << "Got AvatarUpdate for contact with handle" << handle;
@@ -1289,17 +1500,6 @@ void ContactManager::onContactListGroupRemoved(Tp::DBusProxy *proxy,
emit groupRemoved(id);
}
-ContactManager::ContactManager(Connection *connection)
- : Object(),
- mPriv(new Private(this, connection))
-{
-}
-
-ContactManager::~ContactManager()
-{
- delete mPriv;
-}
-
ContactPtr ContactManager::ensureContact(const ReferencedHandles &handle,
const Features &features, const QVariantMap &attributes)
{
@@ -1413,199 +1613,6 @@ void ContactManager::addContactListGroupChannel(
emit groupAdded(id);
}
-ContactPtr ContactManager::lookupContactByHandle(uint handle)
-{
- ContactPtr contact;
-
- if (mPriv->contacts.contains(handle)) {
- contact = ContactPtr(mPriv->contacts.value(handle));
- if (!contact) {
- // Dangling weak pointer, remove it
- mPriv->contacts.remove(handle);
- }
- }
-
- return contact;
-}
-
-void ContactManager::Private::ensureTracking(const Feature &feature)
-{
- if (tracking[feature]) {
- return;
- }
-
- ConnectionPtr conn(parent->connection());
-
- if (feature == Contact::FeatureAlias) {
- Client::ConnectionInterfaceAliasingInterface *aliasingInterface =
- conn->interface<Client::ConnectionInterfaceAliasingInterface>();
-
- parent->connect(
- aliasingInterface,
- SIGNAL(AliasesChanged(Tp::AliasPairList)),
- SLOT(onAliasesChanged(Tp::AliasPairList)));
- } else if (feature == Contact::FeatureAvatarData) {
- Client::ConnectionInterfaceAvatarsInterface *avatarsInterface =
- conn->interface<Client::ConnectionInterfaceAvatarsInterface>();
-
- parent->connect(
- avatarsInterface,
- SIGNAL(AvatarRetrieved(uint,QString,QByteArray,QString)),
- SLOT(onAvatarRetrieved(uint,QString,QByteArray,QString)));
- } else if (feature == Contact::FeatureAvatarToken) {
- Client::ConnectionInterfaceAvatarsInterface *avatarsInterface =
- conn->interface<Client::ConnectionInterfaceAvatarsInterface>();
-
- parent->connect(
- avatarsInterface,
- SIGNAL(AvatarUpdated(uint,QString)),
- SLOT(onAvatarUpdated(uint,QString)));
- } else if (feature == Contact::FeatureCapabilities) {
- Client::ConnectionInterfaceContactCapabilitiesInterface *contactCapabilitiesInterface =
- conn->interface<Client::ConnectionInterfaceContactCapabilitiesInterface>();
-
- parent->connect(
- contactCapabilitiesInterface,
- SIGNAL(ContactCapabilitiesChanged(Tp::ContactCapabilitiesMap)),
- SLOT(onCapabilitiesChanged(Tp::ContactCapabilitiesMap)));
- } else if (feature == Contact::FeatureInfo) {
- Client::ConnectionInterfaceContactInfoInterface *contactInfoInterface =
- conn->interface<Client::ConnectionInterfaceContactInfoInterface>();
-
- parent->connect(
- contactInfoInterface,
- SIGNAL(ContactInfoChanged(uint,Tp::ContactInfoFieldList)),
- SLOT(onContactInfoChanged(uint,Tp::ContactInfoFieldList)));
- } else if (feature == Contact::FeatureLocation) {
- Client::ConnectionInterfaceLocationInterface *locationInterface =
- conn->interface<Client::ConnectionInterfaceLocationInterface>();
-
- parent->connect(
- locationInterface,
- SIGNAL(LocationUpdated(uint,QVariantMap)),
- SLOT(onLocationUpdated(uint,QVariantMap)));
- } else if (feature == Contact::FeatureSimplePresence) {
- Client::ConnectionInterfaceSimplePresenceInterface *simplePresenceInterface =
- conn->interface<Client::ConnectionInterfaceSimplePresenceInterface>();
-
- parent->connect(
- simplePresenceInterface,
- SIGNAL(PresencesChanged(Tp::SimpleContactPresences)),
- SLOT(onPresencesChanged(Tp::SimpleContactPresences)));
- } else {
- warning() << " Unknown feature" << feature
- << "when trying to figure out how to connect change notification!";
- }
-
- tracking[feature] = true;
-}
-
-Contacts ContactManager::Private::allKnownContacts() const
-{
- Contacts contacts;
- foreach (const ContactListChannel &contactListChannel, contactListChannels) {
- ChannelPtr channel = contactListChannel.channel;
- if (!channel) {
- continue;
- }
- contacts.unite(channel->groupContacts());
- contacts.unite(channel->groupLocalPendingContacts());
- contacts.unite(channel->groupRemotePendingContacts());
- }
- return contacts;
-}
-
-void ContactManager::Private::computeKnownContactsChanges(const Tp::Contacts& added,
- const Tp::Contacts& pendingAdded, const Tp::Contacts& remotePendingAdded,
- const Tp::Contacts& removed, const Channel::GroupMemberChangeDetails &details)
-{
- // First of all, compute the real additions/removals based upon our cache
- Tp::Contacts realAdded;
- realAdded.unite(added);
- realAdded.unite(pendingAdded);
- realAdded.unite(remotePendingAdded);
- realAdded.subtract(cachedAllKnownContacts);
- Tp::Contacts realRemoved = removed;
- realRemoved.intersect(cachedAllKnownContacts);
-
- // Check if realRemoved have been _really_ removed from all lists
- foreach (const ContactListChannel &contactListChannel, contactListChannels) {
- ChannelPtr channel = contactListChannel.channel;
- if (!channel) {
- continue;
- }
- realRemoved.subtract(channel->groupContacts());
- realRemoved.subtract(channel->groupLocalPendingContacts());
- realRemoved.subtract(channel->groupRemotePendingContacts());
- }
-
- // Are there any real changes?
- if (!realAdded.isEmpty() || !realRemoved.isEmpty()) {
- // Yes, update our "cache" and emit the signal
- cachedAllKnownContacts.unite(realAdded);
- cachedAllKnownContacts.subtract(realRemoved);
- emit parent->allKnownContactsChanged(realAdded, realRemoved, details);
- }
-}
-
-void ContactManager::Private::updateContactsPresenceState()
-{
- Contacts subscribeContacts;
- Contacts subscribeContactsRP;
-
- if (subscribeChannel) {
- subscribeContacts = subscribeChannel->groupContacts();
- subscribeContactsRP = subscribeChannel->groupRemotePendingContacts();
- }
-
- Contacts publishContacts;
- Contacts publishContactsLP;
- if (publishChannel) {
- publishContacts = publishChannel->groupContacts();
- publishContactsLP = publishChannel->groupLocalPendingContacts();
- }
-
- Contacts denyContacts;
- if (denyChannel) {
- denyContacts = denyChannel->groupContacts();
- }
-
- if (!subscribeChannel && !publishChannel && !denyChannel) {
- return;
- }
-
- Contacts contacts = allKnownContacts();
- foreach (ContactPtr contact, contacts) {
- if (subscribeChannel) {
- // not in "subscribe" -> No, in "subscribe" lp -> Ask, in "subscribe" current -> Yes
- if (subscribeContacts.contains(contact)) {
- contact->setSubscriptionState(Contact::PresenceStateYes);
- } else if (subscribeContactsRP.contains(contact)) {
- contact->setSubscriptionState(Contact::PresenceStateAsk);
- } else {
- contact->setSubscriptionState(Contact::PresenceStateNo);
- }
- }
-
- if (publishChannel) {
- // not in "publish" -> No, in "subscribe" rp -> Ask, in "publish" current -> Yes
- if (publishContacts.contains(contact)) {
- contact->setPublishState(Contact::PresenceStateYes);
- } else if (publishContactsLP.contains(contact)) {
- contact->setPublishState(Contact::PresenceStateAsk);
- } else {
- contact->setPublishState(Contact::PresenceStateNo);
- }
- }
-
- if (denyChannel) {
- if (denyContacts.contains(contact)) {
- contact->setBlocked(true);
- }
- }
- }
-}
-
QString ContactManager::ContactListChannel::identifierForType(Type type)
{
static QString identifiers[LastType] = {
@@ -1632,45 +1639,6 @@ uint ContactManager::ContactListChannel::typeForIdentifier(const QString &identi
return (uint) -1;
}
-PendingContactManagerRemoveContactListGroup::PendingContactManagerRemoveContactListGroup(
- const ChannelPtr &channel)
- : PendingOperation(channel)
-{
- Contacts contacts = channel->groupContacts();
- if (!contacts.isEmpty()) {
- connect(channel->groupRemoveContacts(contacts.toList()),
- SIGNAL(finished(Tp::PendingOperation*)),
- SLOT(onContactsRemoved(Tp::PendingOperation*)));
- } else {
- connect(channel->requestClose(),
- SIGNAL(finished(Tp::PendingOperation*)),
- SLOT(onChannelClosed(Tp::PendingOperation*)));
- }
-}
-
-void PendingContactManagerRemoveContactListGroup::onContactsRemoved(PendingOperation *op)
-{
- if (op->isError()) {
- setFinishedWithError(op->errorName(), op->errorMessage());
- return;
- }
-
- // Let's ignore possible errors and try to remove the group
- ChannelPtr channel = ChannelPtr(qobject_cast<Channel*>((Channel *) object().data()));
- connect(channel->requestClose(),
- SIGNAL(finished(Tp::PendingOperation*)),
- SLOT(onChannelClosed(Tp::PendingOperation*)));
-}
-
-void PendingContactManagerRemoveContactListGroup::onChannelClosed(PendingOperation *op)
-{
- if (!op->isError()) {
- setFinished();
- } else {
- setFinishedWithError(op->errorName(), op->errorMessage());
- }
-}
-
/**
* \fn void ContactManager::presencePublicationRequested(const Tp::Contacts &contacts);
* const Tp::Channel::GroupMemberChangeDetails &details);
@@ -1714,4 +1682,43 @@ void PendingContactManagerRemoveContactListGroup::onChannelClosed(PendingOperati
* over publication and/or subscription state changes if that is the case.
*/
+PendingContactManagerRemoveContactListGroup::PendingContactManagerRemoveContactListGroup(
+ const ChannelPtr &channel)
+ : PendingOperation(channel)
+{
+ Contacts contacts = channel->groupContacts();
+ if (!contacts.isEmpty()) {
+ connect(channel->groupRemoveContacts(contacts.toList()),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(onContactsRemoved(Tp::PendingOperation*)));
+ } else {
+ connect(channel->requestClose(),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(onChannelClosed(Tp::PendingOperation*)));
+ }
+}
+
+void PendingContactManagerRemoveContactListGroup::onContactsRemoved(PendingOperation *op)
+{
+ if (op->isError()) {
+ setFinishedWithError(op->errorName(), op->errorMessage());
+ return;
+ }
+
+ // Let's ignore possible errors and try to remove the group
+ ChannelPtr channel = ChannelPtr(qobject_cast<Channel*>((Channel *) object().data()));
+ connect(channel->requestClose(),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(onChannelClosed(Tp::PendingOperation*)));
+}
+
+void PendingContactManagerRemoveContactListGroup::onChannelClosed(PendingOperation *op)
+{
+ if (!op->isError()) {
+ setFinished();
+ } else {
+ setFinishedWithError(op->errorName(), op->errorMessage());
+ }
+}
+
} // Tp
diff --git a/TelepathyQt4/contact-manager.h b/TelepathyQt4/contact-manager.h
index 72e72d43..2055f868 100644
--- a/TelepathyQt4/contact-manager.h
+++ b/TelepathyQt4/contact-manager.h
@@ -134,9 +134,9 @@ Q_SIGNALS:
private Q_SLOTS:
void onAliasesChanged(const Tp::AliasPairList &);
+ void doRequestAvatars();
void onAvatarUpdated(uint, const QString &);
void onAvatarRetrieved(uint, const QString &, const QByteArray &, const QString &);
- void doRequestAvatars();
void onPresencesChanged(const Tp::SimpleContactPresences &);
void onCapabilitiesChanged(const Tp::ContactCapabilitiesMap &);
void onLocationUpdated(uint, const QVariantMap &);
diff --git a/TelepathyQt4/contact.cpp b/TelepathyQt4/contact.cpp
index ee99594f..8da6f5a8 100644
--- a/TelepathyQt4/contact.cpp
+++ b/TelepathyQt4/contact.cpp
@@ -1,8 +1,8 @@
/*
* This file is part of TelepathyQt4
*
- * Copyright (C) 2008 Collabora Ltd. <http://www.collabora.co.uk/>
- * Copyright (C) 2008 Nokia Corporation
+ * Copyright (C) 2008-2010 Collabora Ltd. <http://www.collabora.co.uk/>
+ * Copyright (C) 2008-2010 Nokia Corporation
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -20,22 +20,23 @@
*/
#include <TelepathyQt4/Contact>
+
#include "TelepathyQt4/_gen/contact.moc.hpp"
+#include "TelepathyQt4/debug-internal.h"
+
#include <TelepathyQt4/AvatarData>
#include <TelepathyQt4/Connection>
#include <TelepathyQt4/ConnectionCapabilities>
#include <TelepathyQt4/Constants>
#include <TelepathyQt4/ContactCapabilities>
-#include <TelepathyQt4/LocationInfo>
#include <TelepathyQt4/ContactManager>
+#include <TelepathyQt4/LocationInfo>
#include <TelepathyQt4/PendingContactInfo>
#include <TelepathyQt4/PendingVoid>
#include <TelepathyQt4/Presence>
#include <TelepathyQt4/ReferencedHandles>
-#include "TelepathyQt4/debug-internal.h"
-
namespace Tp
{
@@ -56,6 +57,8 @@ struct TELEPATHY_QT4_NO_EXPORT Contact::Private
{
}
+ void updateAvatarData();
+
Contact *parent;
QWeakPointer<ContactManager> manager;
@@ -74,7 +77,6 @@ struct TELEPATHY_QT4_NO_EXPORT Contact::Private
bool isAvatarTokenKnown;
QString avatarToken;
AvatarData avatarData;
- void updateAvatarData();
PresenceState subscriptionState;
PresenceState publishState;
@@ -83,6 +85,27 @@ struct TELEPATHY_QT4_NO_EXPORT Contact::Private
QSet<QString> groups;
};
+void Contact::Private::updateAvatarData()
+{
+ /* If token is NULL, it means that CM doesn't know the token. In that case we
+ * have to request the avatar data to get the token. This happens with XMPP
+ * for offline contacts. We don't want to bypass the avatar cache, so we won't
+ * update avatar. */
+ if (avatarToken.isNull()) {
+ return;
+ }
+
+ /* If token is empty (""), it means the contact has no avatar. */
+ if (avatarToken.isEmpty()) {
+ debug() << "Contact" << parent->id() << "has no avatar";
+ avatarData = AvatarData();
+ emit parent->avatarDataChanged(avatarData);
+ return;
+ }
+
+ parent->manager()->requestContactAvatar(parent);
+}
+
struct TELEPATHY_QT4_NO_EXPORT Contact::InfoFields::Private : public QSharedData
{
Private(const ContactInfoFieldList &allFields)
@@ -143,6 +166,20 @@ const Feature Contact::FeatureInfo = Feature(QLatin1String(Contact::staticMetaOb
const Feature Contact::FeatureLocation = Feature(QLatin1String(Contact::staticMetaObject.className()), 5, false);
const Feature Contact::FeatureSimplePresence = Feature(QLatin1String(Contact::staticMetaObject.className()), 6, false);
+Contact::Contact(ContactManager *manager, const ReferencedHandles &handle,
+ const Features &requestedFeatures, const QVariantMap &attributes)
+ : Object(),
+ mPriv(new Private(this, manager, handle))
+{
+ augment(requestedFeatures, attributes);
+}
+
+Contact::~Contact()
+{
+ debug() << "Contact" << id() << "destroyed";
+ delete mPriv;
+}
+
ContactManagerPtr Contact::manager() const
{
return ContactManagerPtr(mPriv->manager);
@@ -445,20 +482,6 @@ PendingOperation *Contact::removeFromGroup(const QString &group)
return manager()->removeContactsFromGroup(group, QList<ContactPtr>() << self);
}
-Contact::~Contact()
-{
- debug() << "Contact" << id() << "destroyed";
- delete mPriv;
-}
-
-Contact::Contact(ContactManager *manager, const ReferencedHandles &handle,
- const Features &requestedFeatures, const QVariantMap &attributes)
- : Object(),
- mPriv(new Private(this, manager, handle))
-{
- augment(requestedFeatures, attributes);
-}
-
void Contact::augment(const Features &requestedFeatures, const QVariantMap &attributes)
{
mPriv->requestedFeatures.unite(requestedFeatures);
@@ -577,6 +600,15 @@ void Contact::receiveAlias(const QString &alias)
}
}
+void Contact::receiveAvatarToken(const QString &token)
+{
+ setAvatarToken(token);
+
+ if (mPriv->actualFeatures.contains(FeatureAvatarData)) {
+ mPriv->updateAvatarData();
+ }
+}
+
void Contact::setAvatarToken(const QString &token)
{
if (!mPriv->requestedFeatures.contains(FeatureAvatarToken)) {
@@ -592,36 +624,6 @@ void Contact::setAvatarToken(const QString &token)
}
}
-void Contact::Private::updateAvatarData()
-{
- /* If token is NULL, it means that CM doesn't know the token. In that case we
- * have to request the avatar data to get the token. This happens with XMPP
- * for offline contacts. We don't want to bypass the avatar cache, so we won't
- * update avatar. */
- if (avatarToken.isNull()) {
- return;
- }
-
- /* If token is empty (""), it means the contact has no avatar. */
- if (avatarToken.isEmpty()) {
- debug() << "Contact" << parent->id() << "has no avatar";
- avatarData = AvatarData();
- emit parent->avatarDataChanged(avatarData);
- return;
- }
-
- parent->manager()->requestContactAvatar(parent);
-}
-
-void Contact::receiveAvatarToken(const QString &token)
-{
- setAvatarToken(token);
-
- if (mPriv->actualFeatures.contains(FeatureAvatarData)) {
- mPriv->updateAvatarData();
- }
-}
-
void Contact::receiveAvatarData(const AvatarData &avatar)
{
mPriv->avatarData = avatar;
diff --git a/TelepathyQt4/contact.h b/TelepathyQt4/contact.h
index 867ad488..fa9097cf 100644
--- a/TelepathyQt4/contact.h
+++ b/TelepathyQt4/contact.h
@@ -1,8 +1,8 @@
/*
* This file is part of TelepathyQt4
*
- * Copyright (C) 2008 Collabora Ltd. <http://www.collabora.co.uk/>
- * Copyright (C) 2008 Nokia Corporation
+ * Copyright (C) 2008-2010 Collabora Ltd. <http://www.collabora.co.uk/>
+ * Copyright (C) 2008-2010 Nokia Corporation
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public