#ifndef CONTACTS_LIST_MODEL_PERSON_PROVIDER_H
#define CONTACTS_LIST_MODEL_PERSON_PROVIDER_H
+#include "Contacts/List/Model/DbChangeObserver.h"
#include "Contacts/List/Model/Person.h"
#include <contacts.h>
#include <functional>
};
/**
- * @brief Person change callback
+ * @brief Person insert callback
* @param[in] person Person object
- * @param[in] changeType Change type
*/
- typedef std::function<void(PersonPtr person, contacts_changed_e changeType)> ChangeCallback;
+ typedef std::function<void(PersonPtr person)> InsertCallback;
/**
- * @brief Person insert callback
+ * @brief Person change callback
* @param[in] person Person object
+ * @param[in] changeType Change type
*/
- typedef std::function<void(PersonPtr person)> InsertCallback;
+ typedef std::function<void(PersonPtr person, contacts_changed_e changeType)> ChangeCallback;
/**
* @brief Constructor
PersonList getPersonList() const;
/**
+ * @brief Set person insert callback
+ * @param[in] callback Create callback
+ */
+ void setInsertCallback(InsertCallback callback);
+
+ /**
+ * @brief Unset person insert callback
+ */
+ void unsetInsertCallback();
+
+ /**
* @brief Set person change callback
* @remark It can be update or delete of person
* @param[in] person Person
*/
void unsetChangeCallback(const Person &person);
- /**
- * @brief Set person insert callback
- * @param[in] callback Create callback
- */
- void setInsertCallback(InsertCallback callback);
-
- /**
- * @brief Unset person insert callback
- */
- void unsetInsertCallback();
-
private:
- void onChanged(const char *viewUri);
- void notify(contacts_changed_e changeType, int contactId);
-
+ void onPersonInserted(int id, contacts_changed_e changeType);
+ void onPersonChanged(int id, contacts_changed_e changeType);
Mode m_Mode;
FilterType m_FilterType;
- int m_DbVersion;
-
- std::unordered_map<int, ChangeCallback> m_ChangeCallbacks;
- InsertCallback m_InsertCallback;
+ std::pair<InsertCallback, Model::DbChangeObserver::CallbackHandle> m_InsertCallback;
+ std::unordered_map<int, std::pair<ChangeCallback, Model::DbChangeObserver::CallbackHandle>> m_ChangeCallbacks;
};
}
}
};
}
+DbChangeObserver::DbChangeObserver(Table table)
+ : m_Table(table), m_DbVersion(0), m_IsSubscribed(false)
+{
+}
+
+DbChangeObserver::~DbChangeObserver()
+{
+ unsubscribe();
+}
+
DbChangeObserver *DbChangeObserver::getInstance(Table table)
{
if (table < 0 || table >= Utils::count(m_Observers)) {
return &m_Observers[table];
}
-DbChangeObserver::~DbChangeObserver()
-{
- unsubscribe();
-}
-
DbChangeObserver::CallbackHandle DbChangeObserver::addCallback(Callback callback)
{
return addCallback(m_Callbacks, std::move(callback));
auto it = m_ChangeCallbacks.find(id);
if (it != m_ChangeCallbacks.end()) {
it->second.erase(handle);
- }
- if (it->second.empty()) {
- m_ChangeCallbacks.erase(it);
+ if (it->second.empty()) {
+ m_ChangeCallbacks.erase(it);
+ }
}
if (m_Callbacks.empty() && m_ChangeCallbacks.empty()) {
}
}
-DbChangeObserver::DbChangeObserver(Table table)
- : m_Table(table), m_DbVersion(0), m_IsSubscribed(false)
-{
-}
-
void DbChangeObserver::subscribe()
{
contacts_db_get_current_version(&m_DbVersion);
void DbChangeObserver::notify(int id, contacts_changed_e changeType)
{
auto notifyAll = [id, changeType](const RecordCbs &callbacks) {
- for (auto &&callback : callbacks) {
+ for (auto it = callbacks.begin(); it != callbacks.end(); ) {
+ auto &callback = *it++;
if (callback) {
callback(id, changeType);
}
#include "Utils/Logger.h"
using namespace Contacts::List::Model;
+using namespace std::placeholders;
namespace
{
ERR("ModeTypeMFC is not supported");
m_Mode = ModeAll;
}
-
- contacts_db_get_current_version(&m_DbVersion);
- contacts_db_add_changed_cb(_contacts_person._uri, makeCallbackWithLastParam(&PersonProvider::onChanged), this);
}
PersonProvider::~PersonProvider()
{
- contacts_db_remove_changed_cb(_contacts_person._uri, makeCallbackWithLastParam(&PersonProvider::onChanged), this);
+ unsetInsertCallback();
+
+ for (auto &&callback : m_ChangeCallbacks) {
+ DbChangeObserver::getInstance()->removeCallback(callback.first, callback.second.second);
+ }
}
PersonList PersonProvider::getPersonList() const
return personList;
}
-void PersonProvider::setChangeCallback(const Person &person, ChangeCallback callback)
-{
- auto ids = person.getContactIds();
-
- auto it = ids.begin();
- for (; it < ids.end() - 1; ++it) {
- m_ChangeCallbacks.insert({ *it, callback });
- }
- m_ChangeCallbacks.insert({ *it, std::move(callback) });
-}
-
-void PersonProvider::unsetChangeCallback(const Person &person)
-{
- for (auto &&id: person.getContactIds()) {
- m_ChangeCallbacks.erase(id);
- }
-}
-
void PersonProvider::setInsertCallback(InsertCallback callback)
{
- m_InsertCallback = std::move(callback);
+ auto handle = DbChangeObserver::getInstance()->addCallback(
+ std::bind(&PersonProvider::onPersonInserted, this, _1, _2));
+ m_InsertCallback = { std::move(callback), std::move(handle) };
}
void PersonProvider::unsetInsertCallback()
{
- m_InsertCallback = nullptr;
+ if (m_InsertCallback.first) {
+ auto handle = m_InsertCallback.second;
+ DbChangeObserver::getInstance()->removeCallback(handle);
+ m_InsertCallback.first = nullptr;
+ }
}
-void PersonProvider::onChanged(const char *viewUri)
+void PersonProvider::setChangeCallback(const Person &person, ChangeCallback callback)
{
- contacts_list_h changes = nullptr;
- contacts_db_get_changes_by_version(_contacts_contact_updated_info._uri, 0, m_DbVersion, &changes, &m_DbVersion);
+ auto addCallback = [this](int id, ChangeCallback callback) {
+ auto handle = DbChangeObserver::getInstance()->addCallback(id,
+ std::bind(&PersonProvider::onPersonChanged, this, _1, _2));
- contacts_record_h record = nullptr;
- CONTACTS_LIST_FOREACH(changes, record) {
- int contactId = 0;
- int changeType = -1;
+ m_ChangeCallbacks.insert({ id, { std::move(callback), std::move(handle) } });
+ };
- contacts_record_get_int(record, _contacts_contact_updated_info.contact_id, &contactId);
- contacts_record_get_int(record, _contacts_contact_updated_info.type, &changeType);
+ auto ids = person.getContactIds();
+ auto it = ids.begin();
- notify(static_cast<contacts_changed_e>(changeType), contactId);
+ for (; it < ids.end() - 1; ++it) {
+ addCallback(*it, callback);
}
- contacts_list_destroy(changes, true);
+ addCallback(*it, std::move(callback));
}
-void PersonProvider::notify(contacts_changed_e changeType, int contactId)
+void PersonProvider::unsetChangeCallback(const Person &person)
{
- auto getPerson = [this, contactId]() -> PersonPtr {
- contacts_record_h personRecord = getPersonRecord(contactId, m_Mode, m_FilterType);
- return personRecord ? PersonPtr(new Person(personRecord)) : nullptr;
- };
+ for (auto &&id: person.getContactIds()) {
+ auto it = m_ChangeCallbacks.find(id);
+ if (it != m_ChangeCallbacks.end()) {
+ auto handle = it->second.second;
+ DbChangeObserver::getInstance()->removeCallback(id, handle);
+
+ m_ChangeCallbacks.erase(it);
+ }
+ }
+}
- PersonPtr person;
+void PersonProvider::onPersonInserted(int id, contacts_changed_e changeType)
+{
+ if (changeType == CONTACTS_CHANGE_INSERTED) {
+ auto callback = m_InsertCallback.first;
+ if (callback) {
+ contacts_record_h record = getPersonRecord(id, m_Mode, m_FilterType);
+ callback(PersonPtr(new Person(record)));
+ }
+ }
+}
- switch (changeType) {
- case CONTACTS_CHANGE_INSERTED:
- person = getPerson();
- if (m_InsertCallback && person) {
- m_InsertCallback(std::move(person));
- }
- break;
- case CONTACTS_CHANGE_UPDATED:
- //Todo: If will be link contact functionality, update only when display contact changed
- person = getPerson();
- if (!person) {
- return;
- }
- //Fallthrough case statement by intention
- case CONTACTS_CHANGE_DELETED:
- {
- auto it = m_ChangeCallbacks.find(contactId);
- if (it != m_ChangeCallbacks.end()) {
- //Todo: If will be link contact functionality, delete only when it was last contact in person
- it->second(std::move(person), changeType);
+void PersonProvider::onPersonChanged(int id, contacts_changed_e changeType)
+{
+ auto it = m_ChangeCallbacks.find(id);
+ if (it != m_ChangeCallbacks.end()) {
+ auto callback = it->second.first;
+
+ if (callback) {
+ if (changeType == CONTACTS_CHANGE_UPDATED) {
+ contacts_record_h record = getPersonRecord(id, m_Mode, m_FilterType);
+ if (record) {
+ callback(PersonPtr(new Person(record)), changeType);
+ } else {
+ callback(nullptr, CONTACTS_CHANGE_DELETED);
+ }
+ } else if (changeType == CONTACTS_CHANGE_DELETED) {
+ callback(nullptr, changeType);
}
}
- break;
}
}