From 86a7572cf73d21dcd9469b6c892bfd5001d4b295 Mon Sep 17 00:00:00 2001
From: Renato Araujo Oliveira Filho <renato.filho@canonical.com>
Date: Fri, 7 Mar 2014 15:11:27 -0300
Subject: [PATCH] Delete declarative contact after remove it from the model.

Keep any contact fetched by the model update even if the contact is not in the model.
Delete any fetched contact if it get removed from the engine.

Change-Id: I646cc2d53ca7bb25b107f44c9517c0aac6814422
---
 src/imports/contacts/qdeclarativecontactmodel.cpp | 47 ++++++++++++++++++++---
 1 file changed, 42 insertions(+), 5 deletions(-)

diff --git a/src/imports/contacts/qdeclarativecontactmodel.cpp b/src/imports/contacts/qdeclarativecontactmodel.cpp
index 5e9bec6..148c003 100644
--- a/src/imports/contacts/qdeclarativecontactmodel.cpp
+++ b/src/imports/contacts/qdeclarativecontactmodel.cpp
@@ -117,6 +117,7 @@ public:
 
     QList<QDeclarativeContact*> m_contacts;
     QMap<QContactId, QDeclarativeContact*> m_contactMap;
+    QMap<QContactId, QDeclarativeContact*> m_contactFetchedMap;
     QContactManager* m_manager;
     QContactAbstractRequest::StorageLocations m_storageLocations;
     QDeclarativeContactFetchHint* m_fetchHint;
@@ -684,8 +685,12 @@ void QDeclarativeContactModel::onFetchContactsRequestStateChanged(QContactAbstra
     if (request->error() == QContactManager::NoError) {
         QList<QContact> contacts(request->contacts());
         foreach (const QContact &contact, contacts) {
-            QDeclarativeContact *declarativeContact(0);
-            declarativeContact = new QDeclarativeContact(this);
+            // if the contact was already fetched update the contact
+            QDeclarativeContact *declarativeContact = d->m_contactFetchedMap.value(contact.id(), 0);
+            if (!declarativeContact) {
+                declarativeContact = new QDeclarativeContact(this);
+                d->m_contactFetchedMap[contact.id()] = declarativeContact;
+            }
             declarativeContact->setContact(contact);
             list.append(QVariant::fromValue(declarativeContact));
         }
@@ -699,6 +704,8 @@ void QDeclarativeContactModel::clearContacts()
     qDeleteAll(d->m_contacts);
     d->m_contacts.clear();
     d->m_contactMap.clear();
+    qDeleteAll(d->m_contactFetchedMap.values());
+    d->m_contactFetchedMap.clear();
 }
 
 void QDeclarativeContactModel::fetchAgain()
@@ -919,6 +926,7 @@ void QDeclarativeContactModel::onContactsAdded(const QList<QContactId>& ids)
         QList<QContactId> contactsIdsForThisModel = extractContactIdsInStorageLocationFromThisModel(ids);
         if (contactsIdsForThisModel.isEmpty())
             return;
+
         QContactFetchRequest *fetchRequest = createContactFetchRequest(contactsIdsForThisModel);
         connect(fetchRequest,SIGNAL(stateChanged(QContactAbstractRequest::State)),
                 this, SLOT(onContactsAddedFetchRequestStateChanged(QContactAbstractRequest::State)));
@@ -987,6 +995,11 @@ void QDeclarativeContactModel::onContactsRemoved(const QList<QContactId> &ids)
 
     bool emitSignal = false;
     foreach (const QContactId &id, ids) {
+        // delete the contact from fetched map if necessary
+        QDeclarativeContact* contact = d->m_contactFetchedMap.take(id);
+        if (contact)
+            contact->deleteLater();
+
         if (d->m_contactMap.contains(id)) {
             int row = 0;
             //TODO:need a fast lookup
@@ -997,7 +1010,8 @@ void QDeclarativeContactModel::onContactsRemoved(const QList<QContactId> &ids)
 
             if (row < d->m_contacts.count()) {
                 beginRemoveRows(QModelIndex(), row, row);
-                d->m_contacts.removeAt(row);
+                contact = d->m_contacts.takeAt(row);
+                contact->deleteLater();
                 d->m_contactMap.remove(id);
                 endRemoveRows();
                 emitSignal = true;
@@ -1014,6 +1028,7 @@ void QDeclarativeContactModel::onContactsChanged(const QList<QContactId> &ids)
         QList<QContactId> contactsIdsForThisModel = extractContactIdsInStorageLocationFromThisModel(ids);
         if (contactsIdsForThisModel.isEmpty())
             return;
+
         QContactFetchRequest *fetchRequest = createContactFetchRequest(contactsIdsForThisModel);
         connect(fetchRequest, SIGNAL(stateChanged(QContactAbstractRequest::State)),
                 this, SLOT(onContactsChangedFetchRequestStateChanged(QContactAbstractRequest::State)));
@@ -1188,9 +1203,16 @@ void QDeclarativeContactModel::onContactsChangedFetchRequestStateChanged(QContac
         foreach (const QContactId &id, requestedContactIds) {
             if (contactListDoesNotContainContactWithId(fetchedContacts, id)) {
                 for (int i=0;i<d->m_contacts.size();++i) {
+                    // Remove contact from fetched map
+                    QDeclarativeContact *dc = d->m_contactFetchedMap.take(id);
+                    if (dc)
+                        dc->deleteLater();
+
                     if (d->m_contacts.at(i)->contactId() == id.toString()) {
                         beginRemoveRows(QModelIndex(), i, i);
-                        d->m_contacts.removeAt(i);
+                        // Remove and delete contact object
+                        dc = d->m_contacts.takeAt(i);
+                        dc->deleteLater();
                         d->m_contactMap.remove(id);
                         endRemoveRows();
                         contactsUpdated = true;
@@ -1198,13 +1220,25 @@ void QDeclarativeContactModel::onContactsChangedFetchRequestStateChanged(QContac
                 }
             }
         }
+        QList<QString> pendingFetch;
         foreach (const QContact &fetchedContact, fetchedContacts) {
+            // If contact exists in the fetched list, we need to update it
+            QDeclarativeContact* dc = d->m_contactFetchedMap.value(fetchedContact.id());
+            if (dc) {
+                // if model contains a fetchHint we can not use the same contact we need to fetch the full contact
+                if (d->m_fetchHint) {
+                    pendingFetch << dc->contactId();
+                } else {
+                    dc->setContact(fetchedContact);
+                }
+            }
+
             QString contactIdString(fetchedContact.id().toString());
             bool fetchedContactFound = false;
             for (int i = 0; i < d->m_contacts.size(); ++i) {
                 //handle updated contacts which should be updated in the model
                 if (d->m_contacts.at(i)->contactId() == contactIdString) {
-                    QDeclarativeContact* dc = d->m_contacts.at(i);
+                    dc = d->m_contacts.at(i);
                     dc->setContact(fetchedContact);
 
                     // Since the contact can change the position due the sort order we need take care of it
@@ -1240,6 +1274,9 @@ void QDeclarativeContactModel::onContactsChangedFetchRequestStateChanged(QContac
                 endInsertRows();
             }
         }
+
+        // re-fetch the full contact
+        fetchContacts(pendingFetch);
     }
 
     if (contactsUpdated)
-- 
1.9.0

