From aeae319b39bfda22cb26e5393288e8aa953140d0 Mon Sep 17 00:00:00 2001
From: AmarOk <blin.sebastien@enconn.fr>
Date: Sun, 23 Apr 2017 15:53:04 -0400
Subject: [PATCH] fix incorrect contact deletion
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

When a contact is removed we need to remove it from personmodel and update
recentmodel & categorizedcontactmodel.

Change-Id: I09694a901278cdd01f771ea83498613159180e8d
Tuleap: #1050
Reviewed-by: Nicolas Jäger <nicolas.jager@savoirfairelinux.com>
---
 src/categorizedcontactmodel.cpp |  8 ++++++++
 src/contactmethod.cpp           |  1 +
 src/personmodel.cpp             | 34 +++++++++++++++++++++++++++++++--
 src/personmodel.h               |  2 +-
 src/recentmodel.cpp             | 22 +++++++++++++++++++++
 5 files changed, 64 insertions(+), 3 deletions(-)

diff --git a/src/categorizedcontactmodel.cpp b/src/categorizedcontactmodel.cpp
index f4fa3dcb..13d3aa32 100644
--- a/src/categorizedcontactmodel.cpp
+++ b/src/categorizedcontactmodel.cpp
@@ -113,6 +113,7 @@ private:
 public Q_SLOTS:
    void reloadCategories();
    void slotContactAdded(const Person* c);
+   void slotContactRemoved(const Person* c);
 };
 
 ContactTreeNode::ContactTreeNode(const Person* ct, CategorizedContactModel* parent) :
@@ -247,6 +248,7 @@ CategorizedContactModel::CategorizedContactModel(int role) : QAbstractItemModel(
    d_ptr->m_lMimes << RingMimes::PLAIN_TEXT << RingMimes::PHONENUMBER;
 
    connect(&PersonModel::instance(),&PersonModel::newPersonAdded,d_ptr.data(),&CategorizedContactModelPrivate::slotContactAdded);
+   connect(&PersonModel::instance(),&PersonModel::personRemoved,d_ptr.data(),&CategorizedContactModelPrivate::slotContactRemoved);
 
    for(int i=0; i < PersonModel::instance().rowCount();i++) {
       Person* p = qvariant_cast<Person*>(PersonModel::instance().index(i,0).data((int)Person::Role::Object));
@@ -323,6 +325,12 @@ void CategorizedContactModelPrivate::reloadCategories()
    emit q_ptr->layoutChanged();
 }
 
+void CategorizedContactModelPrivate::slotContactRemoved(const Person* c) {
+    Q_UNUSED(c)
+
+    reloadCategories();
+}
+
 void CategorizedContactModelPrivate::slotContactAdded(const Person* c)
 {
    if (!c) return;
diff --git a/src/contactmethod.cpp b/src/contactmethod.cpp
index 28f0656b..cb0a50d6 100644
--- a/src/contactmethod.cpp
+++ b/src/contactmethod.cpp
@@ -226,6 +226,7 @@ void ContactMethod::setPerson(Person* contact)
       contact->d_ptr->registerContactMethod(this);
 
    if (contact && d_ptr->m_Type != ContactMethod::Type::TEMPORARY) {
+      contact->d_ptr->registerContactMethod(this);
       PhoneDirectoryModel::instance().d_ptr->indexNumber(this,d_ptr->m_hNames.keys()+QStringList(contact->formattedName()));
       d_ptr->m_PrimaryName_cache = contact->formattedName();
       d_ptr->primaryNameChanged(d_ptr->m_PrimaryName_cache);
diff --git a/src/personmodel.cpp b/src/personmodel.cpp
index aa75e133..8ef4f0fc 100644
--- a/src/personmodel.cpp
+++ b/src/personmodel.cpp
@@ -304,8 +304,38 @@ bool PersonModel::addItemCallback(const Person* c)
 
 bool PersonModel::removeItemCallback(const Person* item)
 {
-   if (item)
-      emit const_cast<Person*>(item)->changed();
+   for (unsigned int nodeIdx = 0; nodeIdx < d_ptr->m_lPersons.size(); ++nodeIdx) {
+      auto person = d_ptr->m_lPersons[nodeIdx]->m_pPerson.get();
+      if (person == item) {
+
+          for ( const auto cm : person->phoneNumbers() )
+              // cm is not linked to any person anymore
+              cm->setPerson(nullptr);
+
+          // Remove contact
+          beginRemoveRows(QModelIndex(), nodeIdx, nodeIdx);
+          d_ptr->m_lPersons[nodeIdx].release();
+          d_ptr->m_lPersons.erase(d_ptr->m_lPersons.begin() + nodeIdx);
+
+          // update indexes
+          for (unsigned int i = 0; i < d_ptr->m_lPersons.size(); ++i) {
+             d_ptr->m_lPersons[i]->m_Index = i;
+             for (unsigned int j = 0; j < d_ptr->m_lPersons[i]->m_lChildren.size(); ++j)
+                d_ptr->m_lPersons[i]->m_lChildren[j]->m_Index = j;
+          }
+          endRemoveRows();
+
+          //Deprecate the placeholder
+          if (d_ptr->m_hPlaceholders.contains(item->uid())) {
+             PersonPlaceHolder* placeholder = d_ptr->m_hPlaceholders[item->uid()];
+             if (placeholder)
+                d_ptr->m_hPlaceholders[item->uid()] = nullptr;
+          }
+          break;
+      }
+   }
+
+   emit personRemoved(item);
    return item;
 }
 
diff --git a/src/personmodel.h b/src/personmodel.h
index f267ffcc..bc862b48 100644
--- a/src/personmodel.h
+++ b/src/personmodel.h
@@ -87,9 +87,9 @@ public Q_SLOTS:
    bool addNewPerson(Person* c, CollectionInterface* backend = nullptr);
 
 Q_SIGNALS:
+   void personRemoved(const Person* c);
    void newPersonAdded(const Person* c);
    void newBackendAdded(CollectionInterface* backend);
    ///The last time there was an interaction with this person changed
    void lastUsedTimeChanged(Person* p, long long) const;
 };
-
diff --git a/src/recentmodel.cpp b/src/recentmodel.cpp
index ef4ce977..b6c658f2 100644
--- a/src/recentmodel.cpp
+++ b/src/recentmodel.cpp
@@ -139,6 +139,7 @@ private:
 public Q_SLOTS:
    void slotLastUsedTimeChanged(const Person*  p , time_t t              );
    void slotPersonAdded        (const Person*  p                         );
+   void slotPersonRemoved      (const Person*  p                         );
    void slotLastUsedChanged    (ContactMethod* cm, time_t t              );
    void slotContactChanged     (ContactMethod* cm, Person* np, Person* op);
    void slotCallAdded          (Call* call       , Call* parent          );
@@ -205,6 +206,7 @@ RecentModel::RecentModel(QObject* parent) : QAbstractItemModel(parent), d_ptr(ne
 {
     connect(&PersonModel::instance()        , &PersonModel::lastUsedTimeChanged    , d_ptr, &RecentModelPrivate::slotLastUsedTimeChanged);
     connect(&PersonModel::instance()        , &PersonModel::newPersonAdded         , d_ptr, &RecentModelPrivate::slotPersonAdded        );
+    connect(&PersonModel::instance()        , &PersonModel::personRemoved          , d_ptr, &RecentModelPrivate::slotPersonRemoved      );
     connect(&PhoneDirectoryModel::instance(), &PhoneDirectoryModel::lastUsedChanged, d_ptr, &RecentModelPrivate::slotLastUsedChanged    );
     connect(&PhoneDirectoryModel::instance(), &PhoneDirectoryModel::contactChanged , d_ptr, &RecentModelPrivate::slotContactChanged     );
     connect(&CallModel::instance()          , &CallModel::callAdded                , d_ptr, &RecentModelPrivate::slotCallAdded          );
@@ -739,6 +741,26 @@ void RecentModelPrivate::slotPersonAdded(const Person* p)
    }
 }
 
+void RecentModelPrivate::slotPersonRemoved(const Person* p)
+{
+    // delete p from contacts
+    RecentViewNode* n = m_hPersonsToNodes.value(p);
+    const bool isNewContact = !n;
+
+    if ( isNewContact )
+       return;
+
+    removeNode(n);
+
+    // but keep the conversation
+    for ( const auto cmToAdd : p->phoneNumbers() ) {
+        const bool isNewCm = !m_hCMsToNodes.value(cmToAdd);
+        n = new RecentViewNode(cmToAdd, this);
+        m_hCMsToNodes[cmToAdd] = n;
+        insertNode(n, cmToAdd->lastUsed(), isNewCm);
+    }
+}
+
 void RecentModelPrivate::slotLastUsedTimeChanged(const Person* p, time_t t)
 {
    RecentViewNode* n = m_hPersonsToNodes.value(p);
-- 
GitLab