diff options
author | Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> | 2010-12-17 10:53:17 -0200 |
---|---|---|
committer | Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> | 2010-12-17 10:53:19 -0200 |
commit | e07a978b22b6131b2179105b1dc0f0d553f55e4c (patch) | |
tree | 78766681651a931b412f7515fbb6f0ad39398a83 /TelepathyQt4 | |
parent | 4c9d8c0e36aa6ccde48cb8595dacb08bb1ff934f (diff) | |
parent | 4362905adca6e756ca2b0bddd78a6bfc11199195 (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.cpp | 687 | ||||
-rw-r--r-- | TelepathyQt4/contact-manager.h | 2 | ||||
-rw-r--r-- | TelepathyQt4/contact.cpp | 102 | ||||
-rw-r--r-- | TelepathyQt4/contact.h | 4 |
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 |