TizenRefApp-6415 Search Result isn't Updated after Editing Contact 97/78897/5
authorSergei Kobec <s.kobec@samsung.com>
Tue, 12 Jul 2016 10:24:46 +0000 (13:24 +0300)
committerSergei Kobec <s.kobec@samsung.com>
Tue, 12 Jul 2016 10:24:46 +0000 (13:24 +0300)
Implementation: Refactored Person to keep all contact records instead of partial data about default contact

Change-Id: I18d5a96aeffff96d07c2a53a7aa7e257ede5f74e
Signed-off-by: Sergei Kobec <s.kobec@samsung.com>
lib-common/inc/Common/Database/ChildRecordIterator.h
lib-common/inc/Common/Database/Queries.h
lib-common/inc/Common/Database/RecordUtils.h
lib-common/src/Common/Database/Queries.cpp
lib-contacts/inc/Contacts/List/Model/MfcProvider.h
lib-contacts/inc/Contacts/List/Model/Person.h
lib-contacts/inc/Contacts/List/Model/PersonProvider.h
lib-contacts/src/Contacts/List/Model/MfcProvider.cpp
lib-contacts/src/Contacts/List/Model/Person.cpp
lib-contacts/src/Contacts/List/Model/PersonProvider.cpp

index b677c89..ea5847a 100644 (file)
@@ -20,6 +20,7 @@
 
 #include "Utils/Iterator.h"
 #include "Utils/Range.h"
+#include <contacts.h>
 
 namespace Common
 {
@@ -73,7 +74,12 @@ namespace Common
                        return { record, property, size_t(count) };
                }
 
-               inline Utils::Range<ChildRecordIterator> makeRange(contacts_record_h record, int property)
+               /**
+                * @brief Contact child record range
+                */
+               typedef Utils::Range<ChildRecordIterator> ChildRecordRange;
+
+               inline ChildRecordRange makeRange(contacts_record_h record, int property)
                {
                        return { begin(record, property), end(record, property) };
                }
index bd33ac6..2b9d011 100644 (file)
@@ -47,6 +47,28 @@ namespace Common
                 * @return _contacts_person ID.
                 */
                EXPORT_API int getPersonId(int contactId);
+
+               /**
+                * @brief Get record list
+                * @remark Return value MUST be destroyed with contacts_list_destroy by you
+                * @param[in]   uri             Record uri
+                * @param[in]   propertyId      Filter property ID
+                * @param[in]   value           Value that should be equal to @a propertyId field value
+                * @param[in]   parentFilter    Parent filter, optional
+                * @return Contacts list on success, otherwise nullptr
+                */
+               EXPORT_API contacts_list_h getRecordList(const char *uri, unsigned propertyId, int value, contacts_filter_h parentFilter = nullptr);
+
+               /**
+                * @brief Get record list
+                * @remark Return value MUST be destroyed with contacts_list_destroy by you
+                * @param[in]   uri             Record uri
+                * @param[in]   propertyId      Filter property ID
+                * @param[in]   values          List of values, which should be equal with @a propertyId field value
+                * @param[in]   parentFilter    Parent filter, optional
+                * @return Contacts list on success, otherwise nullptr
+                */
+               EXPORT_API contacts_list_h getRecordList(const char *uri, unsigned propertyId, Utils::Range<int *> values, contacts_filter_h parentFilter = nullptr);
        }
 }
 
index bf24d5e..f69350a 100644 (file)
 #ifndef COMMON_DATABASE_RECORD_UTILS_H
 #define COMMON_DATABASE_RECORD_UTILS_H
 
-#include <contacts.h>
 #include "Utils/String.h"
+#include "Common/Database/ChildRecordIterator.h"
+
+#include <contacts.h>
 
 #define CONTACTS_LIST_FOREACH(list, record) \
        bool success = (contacts_list_get_current_record_p(list, &record) == CONTACTS_ERROR_NONE); \
@@ -66,6 +68,41 @@ namespace Common
                }
 
                /**
+                * @brief Get first child record
+                * @remark Good way to get single child record
+                * @param[in]   record      Parent record
+                * @param[in]   property    @record property, that points to child DB view
+                * @return Child record on success, otherwise nullptr
+                */
+               inline contacts_record_h getChildRecord(contacts_record_h record, unsigned property)
+               {
+                       contacts_record_h childRecord = nullptr;
+                       contacts_record_get_child_record_at_p(record, property, 0, &childRecord);
+                       return childRecord;
+               }
+
+               /**
+                * @brief Get child record
+                * @param[in]   record      Parent record
+                * @param[in]   property    @record property, that points to child DB view
+                * @param[in]   predicate   Unary function, that accepts child record
+                *                          from parent record range and returns bool value
+                * @return Child record on success, otherwise nullptr
+                */
+               template <typename Pred>
+               inline contacts_record_h getChildRecord(contacts_record_h record, unsigned property,
+                               Pred predicate)
+               {
+                       for (auto childRecord : makeRange(record, property)) {
+                               if (predicate(childRecord)) {
+                                       return childRecord;
+                               }
+                       }
+
+                       return nullptr;
+               }
+
+               /**
                 * @brief Compare two records by the same string property.
                 * @param[in]   record1     First record
                 * @param[in]   records     Second record
index ba0f91e..88045fc 100644 (file)
@@ -65,3 +65,55 @@ int Database::getPersonId(int contactId)
 
        return id;
 }
+
+contacts_list_h Database::getRecordList(const char *uri, unsigned propertyId, int value, contacts_filter_h parentFilter)
+{
+       contacts_filter_h filter = nullptr;
+       contacts_filter_create(uri, &filter);
+       contacts_filter_add_int(filter, propertyId, CONTACTS_MATCH_EQUAL, value);
+       if (parentFilter) {
+               contacts_filter_add_filter(parentFilter, filter);
+       }
+
+       contacts_query_h query = nullptr;
+       contacts_query_create(uri, &query);
+       contacts_query_set_filter(query, filter);
+
+       contacts_list_h list = nullptr;
+       int err = contacts_db_get_records_with_query(query, 0, 0, &list);
+       RETVM_IF_ERR(err, nullptr, "contacts_db_get_records_with_query failed.");
+
+       contacts_query_destroy(query);
+       contacts_filter_destroy(filter);
+
+       return list;
+}
+
+contacts_list_h Database::getRecordList(const char *uri, unsigned propertyId, Utils::Range<int *> values, contacts_filter_h parentFilter)
+{
+       contacts_filter_h filter = nullptr;
+       contacts_filter_create(uri, &filter);
+       for (auto it = values.begin(); it != values.end(); ++it) {
+               if (it != values.begin()) {
+                       contacts_filter_add_operator(filter, CONTACTS_FILTER_OPERATOR_OR);
+               }
+
+               contacts_filter_add_int(filter, propertyId, CONTACTS_MATCH_EQUAL, *it);
+       }
+       if (parentFilter) {
+               contacts_filter_add_filter(parentFilter, filter);
+       }
+
+       contacts_query_h query = nullptr;
+       contacts_query_create(uri, &query);
+       contacts_query_set_filter(query, filter);
+
+       contacts_list_h list = nullptr;
+       int err = contacts_db_get_records_with_query(query, 0, 0, &list);
+       RETVM_IF_ERR(err, nullptr, "contacts_db_get_records_with_query failed.");
+
+       contacts_query_destroy(query);
+       contacts_filter_destroy(filter);
+
+       return list;
+}
index 6c78c0b..bd1e245 100644 (file)
@@ -38,7 +38,7 @@ namespace Contacts
                        private:
                                virtual contacts_list_h getPersonList() const override;
                                virtual contacts_record_h getPersonRecord(int id, IdType idType) const override;
-                               virtual bool insertPerson(int id, IdType idType) override;
+                               virtual void insertPerson(contacts_record_h personRecord) override;
                                virtual void deletePerson(DataList::const_iterator personIt) override;
 
                                contacts_list_h getPersonUsageList() const;
index 01904f7..778b13b 100644 (file)
@@ -20,6 +20,7 @@
 
 #include "Contacts/Model/ContactData.h"
 #include "Utils/UniString.h"
+
 #include <contacts.h>
 #include <vector>
 
@@ -57,6 +58,7 @@ namespace Contacts
                                enum PersonField
                                {
                                        PersonFieldSortValue = FieldMax, /**< Sort value*/
+                                       PersonFieldContact,              /**< Contact field */
                                        PersonFieldMax                   /**< Sentinel value */
                                };
 
@@ -66,7 +68,8 @@ namespace Contacts
                                 */
                                enum PersonChangedInfo
                                {
-                                       ChangedSortValue = 1 << PersonFieldSortValue /**< Sort value has changed */
+                                       ChangedSortValue = 1 << PersonFieldSortValue,   /**< Sort value has changed */
+                                       ChangedContact   = 1 << PersonFieldContact      /**< Whole contact has changed */
                                };
 
                                /**
@@ -122,17 +125,33 @@ namespace Contacts
                                 */
                                bool operator<(const Person &that) const;
 
+                               /**
+                                * @brief Add contact to person
+                                * @param[in]   record  Contact record
+                                */
+                               void addContact(contacts_record_h record);
+
+                               /**
+                                * @brief Remove contact from person
+                                * @param[in]   id  Contact ID
+                                */
+                               void removeContact(int id);
+
+                               /**
+                                * @brief Get count of linked contacts in person
+                                */
+                               size_t getContactCount() const;
+
                        private:
                                friend class PersonProvider;
 
                                const Utils::UniString &getSortValue() const;
-                               void update(contacts_record_h record);
+                               void update(contacts_record_h personRecord);
                                int updateName(contacts_record_h record, unsigned sortProperty);
-                               int updateNumber(int personId);
 
                                contacts_record_h m_Record;
-                               mutable contacts_record_h m_NameRecord;
-                               mutable contacts_record_h m_NumberRecord;
+                               contacts_record_h m_DefaultContactRecord;
+                               std::vector<contacts_record_h> m_ContactRecords;
 
                                Utils::UniString m_IndexLetter;
                                mutable Utils::UniString m_SortValue;
index 93556bb..666ef4e 100644 (file)
@@ -111,19 +111,19 @@ namespace Contacts
                                virtual contacts_record_h getPersonRecord(int id, IdType idType) const;
 
                                /**
-                                * @brief Fetch person from database by ID and insert it into person list.
-                                * @param[in]   id      Person or display contact ID
-                                * @param[in]   idType  Type of ID
-                                * @return Whether insert was successful.
+                                * @brief Insert person into person list.
+                                * @param[in]   personRecord    Person record
                                 */
-                               virtual bool insertPerson(int id, IdType idType);
+                               virtual void insertPerson(contacts_record_h personRecord);
 
                                /**
                                 * @brief Update person from database.
-                                * @param[in]   personIt    Person iterator
+                                * @param[in]   personIt        Person iterator
+                                * @param[in]   personRecord    Person DB record
+                                * @param[in]   contactId       Updated contact ID
                                 * @return Whether update was successful.
                                 */
-                               virtual bool updatePerson(DataList::const_iterator personIt);
+                               virtual bool updatePerson(DataList::const_iterator personIt, contacts_record_h personRecord, int contactId);
 
                                /**
                                 * @brief Delete person from person list.
@@ -149,6 +149,9 @@ namespace Contacts
                        private:
                                void updatePersonList();
 
+                               void addContacts();
+                               void removeContact(int contactId);
+
                                void subscribe();
                                void unsubscribe();
                                void resetDbVersion();
index 852a1cb..2b2e4c5 100644 (file)
@@ -61,7 +61,7 @@ contacts_list_h MfcProvider::getPersonList() const
 contacts_record_h MfcProvider::getPersonRecord(int id, PersonProvider::IdType idType) const
 {
        if (idType == ContactId) {
-               id = getPersonId(id);
+               return nullptr;
        }
 
        for (auto &&usageRecord : makeRange(getPersonUsageList())) {
@@ -75,13 +75,13 @@ contacts_record_h MfcProvider::getPersonRecord(int id, PersonProvider::IdType id
        return nullptr;
 }
 
-bool MfcProvider::insertPerson(int id, IdType idType)
+void MfcProvider::insertPerson(contacts_record_h personRecord)
 {
-       if (idType == ContactId) {
-               return false;
+       if (!personRecord) {
+               return;
        }
 
-       return update();
+       update();
 }
 
 void MfcProvider::deletePerson(DataList::const_iterator personIt)
index 57fcdb9..8d66351 100644 (file)
 #include "Common/Database/Queries.h"
 #include "Common/Database/RecordUtils.h"
 #include "Common/Database/RecordIterator.h"
-#include "Common/Database/ChildRecordIterator.h"
 #include "Utils/Logger.h"
 
+#include <algorithm>
+
 using namespace Common::Database;
 using namespace Contacts;
 using namespace Contacts::Model;
@@ -69,20 +70,18 @@ namespace
                return record;
        }
 
-       contacts_record_h getNumberRecord(int personId)
+       contacts_record_h getNumberRecord(contacts_record_h contactRecord)
        {
-               int id = 0;
-               contacts_record_h record = nullptr;
-               contacts_person_get_default_property(CONTACTS_PERSON_PROPERTY_NUMBER, personId, &id);
-               contacts_db_get_record(_contacts_number._uri, id, &record);
-
-               return record;
+               return getChildRecord(contactRecord, _contacts_contact.number,
+                       [](contacts_record_h record) {
+                               return getRecordBool(record, _contacts_number.is_default);
+                       });
        }
 }
 
 Person::Person(contacts_record_h record)
        : ContactData(TypePerson),
-         m_Record(record), m_NameRecord(nullptr), m_NumberRecord(nullptr),
+         m_Record(record), m_DefaultContactRecord(nullptr),
          m_SortProperty(getSortProperty())
 {
        m_IndexLetter = getRecordStr(m_Record, _contacts_person.display_name_index);
@@ -93,8 +92,9 @@ Person::~Person()
        for (auto &&number : m_Numbers) {
                delete number;
        }
-       contacts_record_destroy(m_NameRecord, true);
-       contacts_record_destroy(m_NumberRecord, true);
+       for (auto &&contact : m_ContactRecords) {
+               contacts_record_destroy(contact, true);
+       }
        contacts_record_destroy(m_Record, true);
 }
 
@@ -110,10 +110,7 @@ const char *Person::getName() const
 
 const char *Person::getNumber() const
 {
-       if (!m_NumberRecord) {
-               m_NumberRecord = getNumberRecord(getId());
-       }
-       return getRecordStr(m_NumberRecord, _contacts_number.number);
+       return getRecordStr(getNumberRecord(m_DefaultContactRecord), _contacts_number.number);
 }
 
 const char *Person::getImagePath() const
@@ -161,40 +158,95 @@ bool Person::operator<(const Person &that) const
        return getSortValue() < that.getSortValue();
 }
 
-const UniString &Person::getSortValue() const
+void Person::addContact(contacts_record_h record)
 {
-       if (m_SortValue.getI18nStr().empty()) {
-               if (!m_NameRecord) {
-                       m_NameRecord = getNameRecord(getContactId());
+       if (getContactId() == getRecordInt(record, _contacts_contact.id)) {
+               m_DefaultContactRecord = record;
+       }
+
+       if (!m_ContactRecords.empty()) {
+               auto it = std::find_if(m_ContactRecords.begin(), m_ContactRecords.end(),
+                       [record](contacts_record_h contactRecord) {
+                               return compareRecordsInt(contactRecord, record, _contacts_contact.id);
+                       }
+               );
+
+               if (it != m_ContactRecords.end()) {
+                       contacts_record_destroy(*it, true);
+                       *it = record;
+                       return;
                }
+       }
+
+       m_ContactRecords.push_back(record);
+}
 
-               const char *value = getRecordStr(m_NameRecord, m_SortProperty);
+void Person::removeContact(int id)
+{
+       auto it = std::find_if(m_ContactRecords.begin(), m_ContactRecords.end(),
+               [id](contacts_record_h contactRecord) {
+                       return getRecordInt(contactRecord, _contacts_contact.id) == id;
+               }
+       );
+
+       if (it != m_ContactRecords.end()) {
+               bool isDefault = *it == m_DefaultContactRecord;
+
+               contacts_record_destroy(*it, true);
+               m_ContactRecords.erase(it);
+
+               if (isDefault && !m_ContactRecords.empty()) {
+                       int id = getId();
+                       contacts_record_destroy(m_Record, true);
+                       contacts_db_get_record(_contacts_person._uri, id, &m_Record);
+
+                       int displayContactId = getRecordInt(m_Record, _contacts_person.display_contact_id);
+                       auto it = std::find_if(m_ContactRecords.begin(), m_ContactRecords.end(),
+                               [this, displayContactId](contacts_record_h contactRecord) {
+                                       return displayContactId == getRecordInt(contactRecord, _contacts_contact.id);
+                               }
+                       );
+                       if (it != m_ContactRecords.end()) {
+                               m_DefaultContactRecord = *it;
+                       }
+               }
+       }
+}
+
+size_t Person::getContactCount() const
+{
+       return m_ContactRecords.size();
+}
+
+const UniString &Person::getSortValue() const
+{
+       if (m_SortValue.getI18nStr().empty()) {
+               contacts_record_h nameRecord = getChildRecord(m_DefaultContactRecord, _contacts_contact.name);
+               const char *value = getRecordStr(nameRecord, m_SortProperty);
                m_SortValue = (value && *value) ? value : getName();
        }
 
        return m_SortValue;
 }
 
-void Person::update(contacts_record_h record)
+void Person::update(contacts_record_h personRecord)
 {
        int changes = ChangedNone;
-       if (!compareRecordsStr(m_Record, record, _contacts_person.display_name)) {
+       if (!compareRecordsStr(m_Record, personRecord, _contacts_person.display_name)) {
                changes |= ChangedName;
        }
-       if (!compareRecordsStr(m_Record, record, _contacts_person.image_thumbnail_path)) {
+       if (!compareRecordsStr(m_Record, personRecord, _contacts_person.image_thumbnail_path)) {
                changes |= ChangedImage;
        }
 
        unsigned sortProperty = getSortProperty();
        if ((changes & ChangedName) || m_SortProperty != sortProperty) {
-               changes |= updateName(record, sortProperty);
-       }
-       if (m_NumberRecord) {
-               changes |= updateNumber(getId());
+               changes |= updateName(personRecord, sortProperty);
        }
+       changes |= ChangedContact;
 
        contacts_record_destroy(m_Record, true);
-       m_Record = record;
+       m_Record = personRecord;
 
        onUpdated(changes);
 }
@@ -202,35 +254,18 @@ void Person::update(contacts_record_h record)
 int Person::updateName(contacts_record_h record, unsigned sortProperty)
 {
        int contactId = getRecordInt(record, _contacts_person.display_contact_id);
-       contacts_record_h nameRecord = getNameRecord(contactId);
+       contacts_record_h nameRecord = getNameRecord(contactId);//Todo: Get rid of this query invocation
 
        int changes = ChangedNone;
        if (!Utils::safeCmp(
-                       getRecordStr(m_NameRecord, m_SortProperty),
+                       getRecordStr(getChildRecord(m_DefaultContactRecord, _contacts_contact.name), m_SortProperty),
                        getRecordStr(nameRecord, sortProperty))) {
                changes |= ChangedSortValue;
                m_SortValue.clear();
                m_IndexLetter = getRecordStr(record, _contacts_person.display_name_index);
        }
 
-       contacts_record_destroy(m_NameRecord, true);
-       m_NameRecord = nameRecord;
        m_SortProperty = sortProperty;
-
-       return changes;
-}
-
-int Person::updateNumber(int personId)
-{
-       contacts_record_h numberRecord = getNumberRecord(personId);
-
-       int changes = ChangedNone;
-       if (!compareRecordsStr(m_NumberRecord, numberRecord, _contacts_number.number)) {
-               changes |= ChangedNumber;
-       }
-
-       contacts_record_destroy(m_NumberRecord, true);
-       m_NumberRecord = numberRecord;
-
+       contacts_record_destroy(nameRecord, true);
        return changes;
 }
index d72a7c4..37d839f 100644 (file)
@@ -54,11 +54,12 @@ int PersonProvider::getFilterType() const
 const PersonProvider::DataList &PersonProvider::getDataList()
 {
        if (!m_IsFilled) {
-               contacts_list_h list = getPersonList();
-               for (auto &&record : makeRange(list)) {
+               contacts_list_h persons = getPersonList();
+               for (auto &&record : makeRange(persons)) {
                        m_PersonList.push_back(createPerson(record));
                }
-               contacts_list_destroy(list, false);
+               contacts_list_destroy(persons, false);
+               addContacts();
 
                subscribe();
                m_IsFilled = true;
@@ -94,7 +95,7 @@ void PersonProvider::reload()
 
        contacts_list_h list = getPersonList();
        for (auto &&record : makeRange(list)) {
-               PersonProvider::insertPerson(getRecordInt(record, _contacts_person.id), PersonId);
+               PersonProvider::insertPerson(record);
        }
 
        contacts_list_destroy(list, true);
@@ -197,29 +198,39 @@ contacts_record_h PersonProvider::getPersonRecord(int id, IdType idType) const
        return record;
 }
 
-bool PersonProvider::insertPerson(int id, IdType idType)
+void PersonProvider::insertPerson(contacts_record_h personRecord)
 {
-       contacts_record_h record = getPersonRecord(id, idType);
-       if (record) {
-               m_PersonList.push_back(createPerson(record));
+       if (personRecord) {
+               Person *person = createPerson(personRecord);
+
+               contacts_list_h contacts = getRecordList(_contacts_contact._uri, _contacts_contact.person_id,
+                               person->getId());
+
+               for (auto &&contact : makeRange(contacts)) {
+                       person->addContact(contact);
+               }
+
+               m_PersonList.push_back(person);
                onInserted(*m_PersonList.back());
-               return true;
-       }
 
-       return false;
+               contacts_list_destroy(contacts, false);
+       }
 }
 
-bool PersonProvider::updatePerson(DataList::const_iterator personIt)
+bool PersonProvider::updatePerson(DataList::const_iterator personIt, contacts_record_h personRecord, int contactId)
 {
        Person *person = static_cast<Person *>(*personIt);
-       contacts_record_h record = getPersonRecord(person->getId(), PersonId);
+       if (personRecord) {
+               person->update(personRecord);
 
-       if (record) {
-               person->update(record);
-               return true;
+               contacts_record_h contactRecord = nullptr;
+               contacts_db_get_record(_contacts_contact._uri, contactId, &contactRecord);
+               person->addContact(contactRecord);
+       } else {
+               deletePerson(personIt);
        }
 
-       return false;
+       return personRecord != nullptr;
 }
 
 void PersonProvider::deletePerson(DataList::const_iterator personIt)
@@ -232,13 +243,25 @@ void PersonProvider::deletePerson(DataList::const_iterator personIt)
 
 PersonProvider::DataList::const_iterator PersonProvider::findPerson(int id, IdType idType)
 {
-       int propId = getIdProperty(idType);
-       return std::find_if(m_PersonList.begin(), m_PersonList.end(),
-               [id, propId](::Model::DataItem *data) {
-                       Person *person = static_cast<Person *>(data);
-                       return getRecordInt(person->getRecord(), propId) == id;
-               }
-       );
+       if (idType == PersonId) {
+               return std::find_if(m_PersonList.begin(), m_PersonList.end(),
+                       [id](::Model::DataItem *data) {
+                               Person *person = static_cast<Person *>(data);
+                               return person->getId() == id;
+                       }
+               );
+       } else {
+               return std::find_if(m_PersonList.begin(), m_PersonList.end(),
+                       [id](::Model::DataItem *data) {
+                               Person *person = static_cast<Person *>(data);
+                               return std::find_if(person->m_ContactRecords.begin(), person->m_ContactRecords.end(),
+                                       [id](contacts_record_h contactRecord) {
+                                               return getRecordInt(contactRecord, _contacts_contact.id) == id;
+                                       }
+                               ) != person->m_ContactRecords.end();
+                       }
+               );
+       }
 }
 
 int PersonProvider::getIdProperty(IdType idType)
@@ -259,30 +282,25 @@ void PersonProvider::updatePersonList()
                switch (changeType) {
                        case CONTACTS_CHANGE_INSERTED:
                        {
-                               insertPerson(contactId, ContactId);
+                               insertPerson(getPersonRecord(contactId, ContactId));
                                break;
                        }
                        case CONTACTS_CHANGE_UPDATED:
                        {
                                int personId = getPersonId(contactId);
+                               contacts_record_h personRecord = getPersonRecord(contactId, ContactId);
                                auto personIt = findPerson(personId, PersonId);
+
                                if (personIt != m_PersonList.end()) {
-                                       if (!updatePerson(personIt)) {
-                                               deletePerson(personIt);
-                                       }
+                                       updatePerson(personIt, personRecord, contactId);
                                } else {
-                                       insertPerson(personId, PersonId);
+                                       insertPerson(personRecord);
                                }
                                break;
                        }
                        case CONTACTS_CHANGE_DELETED:
-                       {
-                               auto personIt = findPerson(contactId, ContactId);
-                               if (personIt != m_PersonList.end()) {
-                                       deletePerson(personIt);
-                               }
+                               removeContact(contactId);
                                break;
-                       }
                }
        }
 
@@ -290,6 +308,35 @@ void PersonProvider::updatePersonList()
        onUpdateFinished();
 }
 
+
+void PersonProvider::addContacts()
+{
+       contacts_list_h contacts = nullptr;
+       contacts_db_get_all_records(_contacts_contact._uri, 0, 0, &contacts);
+       for (auto &&record : makeRange(contacts)) {
+               auto it = findPerson(getRecordInt(record, _contacts_contact.person_id), PersonId);
+               if (it != m_PersonList.end()) {
+                       Person *person = static_cast<Person *>(*it);
+                       person->addContact(record);
+               } else {
+                       contacts_record_destroy(record, true);
+               }
+       }
+       contacts_list_destroy(contacts, false);
+}
+
+void PersonProvider::removeContact(int contactId)
+{
+       auto personIt = findPerson(contactId, ContactId);
+       if (personIt != m_PersonList.end()) {
+               Person &person = static_cast<Person &>(**personIt);
+               person.removeContact(contactId);
+               if (!person.getContactCount()) {
+                       deletePerson(personIt);
+               }
+       }
+}
+
 void PersonProvider::subscribe()
 {
        resetDbVersion();