[Telepathy-commits] [telepathy-qt4/master] Prototype: Incorporate blocking ('deny' list) development from Stefan

Simon McVittie simon.mcvittie at collabora.co.uk
Tue Dec 2 03:37:09 PST 2008


---
 TelepathyQt4/Prototype/ContactManager.cpp |  265 ++++++++++++++++++++++-------
 TelepathyQt4/Prototype/ContactManager.h   |   62 ++++++-
 2 files changed, 259 insertions(+), 68 deletions(-)

diff --git a/TelepathyQt4/Prototype/ContactManager.cpp b/TelepathyQt4/Prototype/ContactManager.cpp
index af06ad1..372662d 100644
--- a/TelepathyQt4/Prototype/ContactManager.cpp
+++ b/TelepathyQt4/Prototype/ContactManager.cpp
@@ -56,6 +56,7 @@ public:
     Telepathy::Client::ChannelInterfaceGroupInterface*  m_groupSubscribedChannel;
     Telepathy::Client::ChannelInterfaceGroupInterface*  m_groupKnownChannel;
     Telepathy::Client::ChannelInterfaceGroupInterface*  m_groupPublishedChannel;
+    Telepathy::Client::ChannelInterfaceGroupInterface*  m_groupDeniedChannel;
     Telepathy::Client::ChannelTypeTextInterface*  m_groupTextChannel;
 
     QHash<uint, QPointer<Contact> > m_members;
@@ -63,6 +64,7 @@ public:
     QHash<uint, QPointer<Contact> > m_localPending;
     QHash<uint, QPointer<Contact> > m_remotePending;
     QHash<uint, QPointer<Contact> > m_known;
+    QHash<uint, QPointer<Contact> > m_denied;
 
     bool m_isValid;
 
@@ -76,59 +78,51 @@ public:
         m_isValid    = false;
     }
 
-    QList<uint> SubscribedHandlesToLookUp(const Telepathy::UIntList& handles)
+    // Returns a list of all <i>handles</i> already <i>contained</i> in <i>list</i>
+    QList<uint> handlesToLookUp( const QHash<uint, QPointer<Contact> >& list, const Telepathy::UIntList& handles, bool contained )
     {
-        QList<uint> subscribed_to_look_up;
+        QList<uint> to_look_up;
         foreach(uint handle, handles)
         {
-            if (!m_subscribed.contains(handle) )
-                subscribed_to_look_up.append(handle);
+            if ( contained == list.contains(handle) )
+            { to_look_up.append(handle); }
         }
-        return subscribed_to_look_up;
+        return to_look_up;
     }
-    
-    QList<uint> KnownHandlesToLookUp(const Telepathy::UIntList& handles)
+
+    QList<uint> subscribedHandlesToLookUp(const Telepathy::UIntList& handles)
     {
-        QList<uint> known_to_look_up;
-        foreach(uint handle, handles)
-        {
-            if (!m_members.contains(handle) )
-                known_to_look_up.append(handle);
-        }
-        return known_to_look_up;
-    }    
-    QList<uint> RemovedHandlesToLookUp(const Telepathy::UIntList& handles)
+        return handlesToLookUp( m_subscribed, handles, false );
+    }
+
+    QList<uint> newKnownHandlesToLookUp(const Telepathy::UIntList& handles)
     {
-        QList<uint> removed_to_look_up;
-        foreach(uint handle, handles)
-        {
-            if (m_members.contains(handle) )
-                removed_to_look_up.append(handle);
-        }
-        return removed_to_look_up;
+        return handlesToLookUp( m_members, handles, false );
     }
 
-    QList<uint> LocalPendingHandlesToLookUp(const Telepathy::UIntList& handles)
+    QList<uint> removedHandlesToLookUp(const Telepathy::UIntList& handles)
     {
-        QList<uint> localpending_to_look_up;
-        foreach(uint handle, handles)
-        {
-            if (!m_localPending.contains(handle))
-                localpending_to_look_up.append(handle);
-        }
-        return localpending_to_look_up;
+        return handlesToLookUp( m_members, handles, true );
     }
-    
-    QList<uint> RemotePendingHandlesToLookUp(const Telepathy::UIntList& handles)
+
+    QList<uint> localPendingHandlesToLookUp(const Telepathy::UIntList& handles)
     {
-        QList<uint> remotepending_to_look_up;
-        foreach(uint handle, handles)
-        {
-            if (!m_remotePending.contains(handle))
-                remotepending_to_look_up.append(handle); 
-            
-        }
-        return remotepending_to_look_up;
+        return handlesToLookUp( m_localPending, handles, false );
+    }
+
+    QList<uint> remotePendingHandlesToLookUp(const Telepathy::UIntList& handles)
+    {
+        return handlesToLookUp( m_remotePending, handles, false );
+    }
+
+    QList<uint> newDeniedHandles( const Telepathy::UIntList& handles )
+    {
+        return handlesToLookUp( m_denied, handles, false );
+    }
+
+    QList<uint> removedDeniedHandles( const Telepathy::UIntList& handles )
+    {
+        return handlesToLookUp( m_denied, handles, true );
     }
 
     QList<QPointer<TpPrototype::Contact> > mapHashToList( QHash<uint, QPointer<Contact> > hash )
@@ -187,6 +181,8 @@ QList<QPointer<Contact> > ContactManager::toAuthorizeList()
 QList<QPointer<Contact> > ContactManager::remoteAuthorizationPendingList()
 { return d->m_remotePending.values();}
 
+QList<QPointer<Contact> > ContactManager::blockedContacts()
+{ return d->m_denied.values(); }
 
 void ContactManager::init( Telepathy::Client::ConnectionInterface* connection )
 {
@@ -257,6 +253,40 @@ bool ContactManager::removeContact( const Contact* contact_toremove )
     return true;
 }
 
+bool ContactManager::blockContact( const Contact* contactToBlock )
+{
+    if ( !contactToBlock || !d->m_groupDeniedChannel )
+    { return false; }
+
+#ifdef ENABLE_DEBUG_OUTPUT_
+    qDebug() << "ContactManager: Try to block a contact";
+#endif
+    QList<uint> handle_list;
+    handle_list.append( contactToBlock->telepathyHandle() );
+
+    d->m_groupDeniedChannel->AddMembers( handle_list, "Block" );
+
+    return true;
+    // The list of blocked users (d->m_denied()) will be updated by a signal after this point
+}
+
+bool ContactManager::unblockContact( const Contact* contactToUnblock )
+{
+    if ( !contactToUnblock || !d->m_groupDeniedChannel )
+    { return false; }
+
+#ifdef ENABLE_DEBUG_OUTPUT_
+    qDebug() << "ContactManager: Try to unblock a contact";
+#endif
+    QList<uint> handle_list;
+    handle_list.append( contactToUnblock->telepathyHandle() );
+
+    d->m_groupDeniedChannel->RemoveMembers( handle_list, "Unblock" );
+
+    return true;
+    // The list of blocked users (d->m_denied()) will be updated by a signal after this point
+}
+
 QPointer<TpPrototype::Contact> ContactManager::contactForHandle( uint handle )
 {
     return d->m_members.value( handle );
@@ -286,13 +316,11 @@ uint ContactManager::localHandle()
 
 void ContactManager::openSubscribedContactsChannel(uint handle, const QDBusObjectPath& channelPath, const QString& channelType)
 {
-    Telepathy::registerTypes();
-
     QString channel_service_name(d->m_pInterface->service());
 #ifdef ENABLE_DEBUG_OUTPUT_
     qDebug() << "ContactManager Channel Services Name" << channel_service_name;
     qDebug() << "ContactManager Channel Path" << channelPath.path();
-#endif        
+#endif
     // This channel may never be closed!
     d->m_groupSubscribedChannel = new Telepathy::Client::ChannelInterfaceGroupInterface(channel_service_name,channelPath.path(),
             this);
@@ -344,8 +372,6 @@ void ContactManager::openSubscribedContactsChannel(uint handle, const QDBusObjec
 
 void ContactManager::openKnownContactsChannel(uint handle, const QDBusObjectPath& channelPath, const QString& channelType)
 {
-    Telepathy::registerTypes();
-
     QString channel_service_name(d->m_pInterface->service());
 #ifdef ENABLE_DEBUG_OUTPUT_   
     qDebug() << "ContactManager Channel Services Name" << channel_service_name;
@@ -382,11 +408,7 @@ void ContactManager::openKnownContactsChannel(uint handle, const QDBusObjectPath
                         mlist3,
                         mlist4,
                         0, 0);
-    
-   // qDebug() << "Number of current members" << mlist1.size();
-   // qDebug() << "Number of local pending members" << mlist2.size();
-   // qDebug() << "Number of remote pending members" << mlist3.size();
-    
+
     // All lists are empty when the channel is created, so it suffices to connect
     // the MembersChanged signal.
     connect(d->m_groupKnownChannel, SIGNAL(MembersChanged(const QString&,
@@ -404,6 +426,63 @@ void ContactManager::openKnownContactsChannel(uint handle, const QDBusObjectPath
 
 }
 
+void ContactManager::openDenyContactsChannel(uint handle, const QDBusObjectPath& channelPath, const QString& channelType)
+{
+    QString channel_service_name(d->m_pInterface->service());
+#ifdef ENABLE_DEBUG_OUTPUT_
+    qDebug() << "ContactManager Channel Services Name" << channel_service_name;
+    qDebug() << "ContactManager Channel Path" << channelPath.path();
+#endif
+    // This channel may never be closed!
+    d->m_groupDeniedChannel = new Telepathy::Client::ChannelInterfaceGroupInterface(channel_service_name,channelPath.path(),
+                                                                                    this);
+    if (!d->m_groupDeniedChannel->isValid())
+    {
+#ifdef ENABLE_DEBUG_OUTPUT_
+        qDebug() << "Failed to connect Group channel interface class to D-Bus object.";
+#endif
+        delete d->m_groupDeniedChannel;
+        d->m_groupDeniedChannel = NULL;
+        return;
+    }
+
+    QDBusPendingReply<Telepathy::UIntList, Telepathy::UIntList, Telepathy::UIntList> reply2=d->m_groupKnownChannel->GetAllMembers();
+    reply2.waitForFinished();
+
+    const Telepathy::UIntList current        = QList< quint32 > (reply2.argumentAt<0>());
+    const Telepathy::UIntList local_pending  = QList< quint32 > (reply2.argumentAt<1>());
+    const Telepathy::UIntList remote_pending = QList< quint32 > (reply2.argumentAt<2>());
+#ifdef ENABLE_DEBUG_OUTPUT_
+    qDebug() << "Denied-Members: Number of current members" << current.size();
+    qDebug() << "Denied-Members: Number of local pending members" << local_pending.size();
+    qDebug() << "Denied-Members: Number of remote pending members" << remote_pending.size();
+#endif
+    if (( current.size()>0) || ( local_pending.size()>0) || ( remote_pending.size()>0))
+        slotDeniedMembersChanged("",
+                                current,
+                                Telepathy::UIntList(),
+                                local_pending,
+                                remote_pending,
+                                0, 0);
+
+    // All lists are empty when the channel is created, so it suffices to connect
+    // the MembersChanged signal.
+    connect(d->m_groupDeniedChannel, SIGNAL(MembersChanged(const QString&,
+                                                            const Telepathy::UIntList&, // added to members list
+                                                            const Telepathy::UIntList&, // removed from members list
+                                                            const Telepathy::UIntList&, // local pending list
+                                                            const Telepathy::UIntList&, // remote pending list
+                                                            uint,                       // actor
+                                                            uint)),                     // reason
+            this, SLOT(slotDeniedMembersChanged(const QString&,
+                                                const Telepathy::UIntList&,
+                                                const Telepathy::UIntList&,
+                                                const Telepathy::UIntList&,
+                                                const Telepathy::UIntList&,
+                                                uint, uint)));
+
+}
+
 void ContactManager::openTextChannel( uint handle, uint handleType, const QString& channelPath, const QString& channelTyp )
 {
     Contact* contact = d->m_members.value( handle );
@@ -464,8 +543,6 @@ void ContactManager::openStreamedMediaChannel( uint handle, uint handleType, con
 
 void ContactManager::openPublishContactsChannel(uint handle, const QDBusObjectPath& channelPath, const QString& channelType)
 {
-    Telepathy::registerTypes();
-
     QString channel_service_name(d->m_pInterface->service());
 #ifdef ENABLE_DEBUG_OUTPUT_    
     qDebug() << "ContactManager Channel Services Name" << channel_service_name;
@@ -569,7 +646,75 @@ void ContactManager::slotSubscribedMembersChanged(const QString& message,
                        actor, reason);
 }
 
-// TODO: This function is a real beast. It should be split into separate functions. Rething whether it is a good idea
+void ContactManager::slotDeniedMembersChanged(const QString& message,
+                                                const Telepathy::UIntList& members_added,
+                                                const Telepathy::UIntList& members_removed,
+                                                const Telepathy::UIntList& local_pending,
+                                                const Telepathy::UIntList& remote_pending,
+                                                uint actor,
+                                                uint reason)
+{
+    QList<uint> added_members   = d->newDeniedHandles( members_added );        // members added to the list of denied.
+    QList<uint> removed_members = d->removedDeniedHandles( members_removed );  // members removed from the list of denied.
+    QList<uint> new_members     = d->newKnownHandlesToLookUp( members_added ); // new members that are not yet in the list of members
+
+    // Remove all removed members from the denied list
+    foreach( uint member_handle, removed_members )
+    {
+        Contact* contact = d->m_denied.value( member_handle );
+        if ( !contact )
+        { continue; }
+        contact->setType( Contact::CT_Known );
+        d->m_denied.remove( member_handle );
+    }
+
+    // Members that are not already known (in list of members): create new contact.
+    QDBusPendingReply<QStringList> handle_names_reply = d->m_pInterface->InspectHandles( Telepathy::HandleTypeContact, new_members );
+    handle_names_reply.waitForFinished();
+    if ( !handle_names_reply.isValid() )
+    {
+        QDBusError error = handle_names_reply.error();
+
+        qWarning() << "InspectHandles (new denied handles=: error type:" << error.type()
+                   << "error name:" << error.name()
+                   << "error message:" << error.message();
+        return;
+    }
+    Q_ASSERT( handle_names_reply.value().size() == new_members.size() );
+
+    // Create Contacts for the looked up handles:
+    for (int i = 0; i < new_members.size(); ++i)
+    {
+        QPointer<Contact> contact = new Contact( new_members.at(i), handle_names_reply.value().at(i), Contact::CT_Blocked, d->m_pInterface, this );
+#ifdef ENABLE_DEBUG_OUTPUT_
+        qDebug() << "Create contact for known Handle" << handle_names.value().at(i);
+#endif
+        Q_ASSERT(contact->isValid());
+        d->m_members.insert( new_members.at( i ), contact );
+    }
+    // end: create new contact
+
+    // Now update list of blocked members and emit signals.
+    foreach( uint member_handle, added_members )
+    {
+        Contact* contact = d->m_members.value( member_handle );
+        if ( !contact )
+        { continue; }
+        contact->setType( Contact::CT_Blocked );
+        d->m_denied.insert( member_handle, contact );
+
+        emit signalContactBlocked( this, contact );
+    }
+    // Emit signals for the removed members
+    foreach( uint member_handle, removed_members )
+    {
+
+        emit signalContactUnblocked( this, d->m_members.value( member_handle ) );
+    }
+}
+
+
+// TODO: This function is a real beast. It should be split into separate functions. Rethink whether it is a good idea
 //       to map all slots to this functions!?
 void ContactManager::slotMembersChanged(const QString& message,
                                         const Telepathy::UIntList& members_added,
@@ -597,7 +742,7 @@ void ContactManager::slotMembersChanged(const QString& message,
     {
         if (message==QString("Known"))
         {        
-            QList<uint> known_to_look_up(d->KnownHandlesToLookUp(members_added));
+            QList<uint> known_to_look_up(d->newKnownHandlesToLookUp(members_added));
         // look up 'missing' handles:
             QDBusPendingReply<QStringList> handle_names =
                     d->m_pInterface->InspectHandles(Telepathy::HandleTypeContact, known_to_look_up);
@@ -666,7 +811,7 @@ void ContactManager::slotMembersChanged(const QString& message,
         else //message!="Known"
         {
            
-            QList<uint> subscribed_to_look_up(d->SubscribedHandlesToLookUp(members_added));
+            QList<uint> subscribed_to_look_up(d->subscribedHandlesToLookUp(members_added));
     
         // look up 'missing' handles:
             QDBusPendingReply<QStringList> handle_names =
@@ -742,7 +887,7 @@ void ContactManager::slotMembersChanged(const QString& message,
                                     d->m_localPending.remove(handle);
                                   
                             }
-                            delete current_contact;
+                            current_contact->deleteLater();
                         }
 
                         emit signalContactSubscribed( this,  d->m_members[handle] );
@@ -754,7 +899,7 @@ void ContactManager::slotMembersChanged(const QString& message,
     }
     if (local_pending.size()!=0)
     {
-        QList<uint> localPending_to_look_up(d->LocalPendingHandlesToLookUp(local_pending));
+        QList<uint> localPending_to_look_up(d->localPendingHandlesToLookUp(local_pending));
     // look up 'missing' handles:
         QDBusPendingReply<QStringList> handle_names =
                 d->m_pInterface->InspectHandles(Telepathy::HandleTypeContact, localPending_to_look_up);
@@ -822,7 +967,7 @@ void ContactManager::slotMembersChanged(const QString& message,
         
     if (remote_pending.size()!=0)
     {
-        QList<uint> remotePending_to_look_up(d->RemotePendingHandlesToLookUp(remote_pending));
+        QList<uint> remotePending_to_look_up(d->remotePendingHandlesToLookUp(remote_pending));
 
     // look up 'missing' handles:
         QDBusPendingReply<QStringList> handle_names =
@@ -897,7 +1042,7 @@ void ContactManager::slotMembersChanged(const QString& message,
 #ifdef ENABLE_DEBUG_OUTPUT_
         qDebug() << "SlotMembers Changed Removed Called";
 #endif
-        QList<uint> removed_to_look_up(d->RemovedHandlesToLookUp(members_removed));
+        QList<uint> removed_to_look_up(d->removedHandlesToLookUp(members_removed));
     // look up 'missing' handles:
         QDBusPendingReply<QStringList> handle_names =
                 d->m_pInterface->InspectHandles(Telepathy::HandleTypeContact, removed_to_look_up);
diff --git a/TelepathyQt4/Prototype/ContactManager.h b/TelepathyQt4/Prototype/ContactManager.h
index f396985..d609872 100644
--- a/TelepathyQt4/Prototype/ContactManager.h
+++ b/TelepathyQt4/Prototype/ContactManager.h
@@ -110,7 +110,13 @@ public:
       * @todo: Return ContactGroup here, instead of a list of pointer.
       */
      QList<QPointer<TpPrototype ::Contact> > remoteAuthorizationPendingList();
-     
+
+     /**
+      * List of contacts that are blocked.
+      * @todo: Return ContactGroup here, instead of a list of pointer.
+      */
+     QList<QPointer<TpPrototype::Contact> > blockedContacts();
+
      /**
       * Request a contact.
       * A remote contact should be added to the list of known contacts.
@@ -134,6 +140,26 @@ public:
       */
      bool removeContact( const TpPrototype ::Contact* contactToRemove );
 
+      /**
+      * Block a contact.
+      * The contact is moved to the list of blocked contacts. This may not be supported by the protocol/contact manager. In this case false is returned.
+      * A blocked contact will not receive any presence information from the local account. Messages from this contact are ignored.
+      * The signal signalContactBlocked() is emitted if this call was successful.<br>
+      * <b>Hint:</b>Blocking support is currently available with the connection manager Gabble and GoogleTalk.
+      * @return true if blocking is supported.
+      */
+     bool blockContact( const Contact* contactToBlock );
+
+     /**
+      * Block a contact.
+      * The contact is moved to the list of blocked contacts. This may not be supported by the protocol/contact manager. In this case false is returned.
+      * A blocked contact will not receive any presence information from the local account. Messages from this contact are ignored.<br>
+      * The signal signalContactUnblocked() is emitted if this call was successful.<br>
+      * <b>Hint:</b>Blocking support is currently available with the connection manager Gabble and GoogleTalk.
+      * @return true if blocking is supported
+      */
+     bool unblockContact( const Contact* contactToUnblock );
+
      /**
       * Returns a contact pointer for handle id.
       * This function provides a fast lookup of a contact if a valid handle is provided.
@@ -142,7 +168,7 @@ public:
      QPointer<TpPrototype ::Contact> contactForHandle( uint handle );
 
      /**
-      * The local use handle.
+      * The local handle.
       * The local user has a handle that is returned by this function. The local handle cannot be used to get
       * a valid contact with contactForHandle()!
       */
@@ -195,8 +221,9 @@ signals:
     void signalContactSubscribed( TpPrototype ::ContactManager* contactManager, TpPrototype ::Contact* contact );
     
     /**
-     * A Contact was removed.    
-     * This signal is emitted if a new contact was removed.
+     * A Contact was removed.
+     * This signal is emitted if a contact was removed.
+     * @param contact The removed contact. This object will be delted after this call!
      */
     void signalContactRemoved( TpPrototype ::ContactManager* contactManager, TpPrototype ::Contact* contact );
     
@@ -204,12 +231,25 @@ signals:
      * @todo: Add doc! (seil)
      */
     void signalContactKnown( TpPrototype ::ContactManager* contactManager, TpPrototype ::Contact* contact );
-    
+
+    /**
+     * @todo: Add doc!
+     * Contact was blocked.
+     * This signal is emitted after a contact was blocked.
+     */
+    void signalContactBlocked( TpPrototype::ContactManager* contactManager, TpPrototype::Contact* contact );
+
+    /**
+     * Contact was unblocked.
+     * This signal is emitted after a contact was unblocked.
+     */
+    void signalContactUnblocked( TpPrototype::ContactManager* contactManager, TpPrototype::Contact* contact );
+
     /**
      * @todo: Add doc! (seil)
      */
     void signalForModelContactSubscribed( TpPrototype ::ContactManager* contactManager, TpPrototype ::Contact* contact );
-    
+
     /**
      * @todo: Add doc! (seil)
      */
@@ -255,9 +295,9 @@ protected:
       */
     void openKnownContactsChannel(uint handle, const QDBusObjectPath& objectPath, const QString& channelType);
 
-     /**
+    /**
      * ..
-      */
+     */
     void openDenyContactsChannel(uint handle, const QDBusObjectPath& objectPath, const QString& channelType);
 
     void openTextChannel( uint handle, uint handleType, const QString& channelPath, const QString& channelType );
@@ -290,6 +330,12 @@ protected slots:
                                      const Telepathy::UIntList& local_pending,
                                      const Telepathy::UIntList& remote_pending,
                                      uint actor, uint reason);       
+    void slotDeniedMembersChanged(const QString& message,
+                                      const Telepathy::UIntList& members_added,
+                                      const Telepathy::UIntList& members_removed,
+                                      const Telepathy::UIntList& local_pending,
+                                      const Telepathy::UIntList& remote_pending,
+                                      uint actor, uint reason);
 private:
     void init( Telepathy::Client::ConnectionInterface* connection );
 
-- 
1.5.6.5




More information about the Telepathy-commits mailing list