* limitations under the License.
*
*/
+
#ifndef CONTACTS_LIST_CONTACT_GROUP_ITEM_H
#define CONTACTS_LIST_CONTACT_GROUP_ITEM_H
#include "Ui/GenlistGroupItem.h"
#include <string>
+namespace Utils
+{
+ class UniString;
+}
+
namespace Contacts
{
namespace List
/**
* @return Group item title
*/
- const char *getTitle() const;
+ const Utils::UniString &getTitle() const;
/**
* @return Linked index item
virtual char *getText(Evas_Object *parent, const char *part);
std::string m_Title;
+ mutable Utils::UniString *m_UniTitle;
+
Elm_Object_Item *m_IndexItem;
};
}
*/
const Model::Contact &getContact() const;
+ /**
+ * @brief Set contact object
+ * @param[in] contact Contact object
+ */
+ void setContact(Model::ContactPtr contact);
+
private:
virtual char *getText(Evas_Object *parent, const char *part) override;
virtual Evas_Object *getContent(Evas_Object *parent, const char *part) override;
#ifndef CONTACTS_LIST_LIST_VIEW_H
#define CONTACTS_LIST_LIST_VIEW_H
-#include "Ui/View.h"
#include "Contacts/List/Model/ContactProvider.h"
+#include "Ui/View.h"
+#include "Utils/UniString.h"
#include <map>
namespace Ui
void fillList();
+ Elm_Index_Item *insertIndexItem(const char *indexLetter,
+ Elm_Index_Item *nextItem = nullptr);
+
ContactGroupItem *insertGroupItem(const char *indexLetter,
ContactGroupItem *nextGroup = nullptr);
- ContactGroupItem *getNextGroupItem(const char *indexLetter);
+ void deleteGroupItem(ContactGroupItem *group);
+ ContactGroupItem *getNextGroupItem(const Utils::UniString &indexLetter);
- ContactItem *insertItem(Model::ContactPtr contact, ContactGroupItem *group,
- ContactItem *nextItem = nullptr);
- ContactItem *getNextItem(ContactGroupItem *group, const Model::Contact &contact);
+ ContactItem *createContactItem(Model::ContactPtr contact);
+ void insertContactItem(ContactItem *item);
+ void updateContactItem(ContactItem *item, Model::ContactPtr contact);
+ ContactItem *getNextContactItem(ContactGroupItem *group, const Model::Contact &contact);
void onItemSelected(Evas_Object *genlist, Elm_Object_Item *genlistItem);
void onIndexChanged(Evas_Object *index, Elm_Object_Item *indexItem);
virtual void onMenuPressed() override;
void onContactInserted(Model::ContactPtr contact);
+ void onContactChanged(Model::ContactPtr contact, contacts_changed_e changeType, ContactItem *item);
Ui::Genlist *m_Genlist;
Evas_Object *m_Index;
- std::map<std::string, ContactGroupItem *> m_Groups;
+ std::map<Utils::UniString, ContactGroupItem *> m_Groups;
Model::ContactProvider m_Provider;
};
#include <contacts.h>
#include <memory>
#include <vector>
-#include <utils_i18n.h>
+
+namespace Utils
+{
+ class UniString;
+}
namespace Contacts
{
bool operator<(const Contact &that) const;
/**
+ * @brief Compares contact's "Sort by" (first name/last name) values on equality
+ * @return True if sort values are equivalent, otherwise false
+ */
+ bool operator==(const Contact &that) const;
+
+ /**
+ * @brief Compares contact's "Sort by" (first name/last name) values on inequality
+ * @return True if sort values are not equivalent, otherwise false
+ */
+ bool operator!=(const Contact &that) const;
+
+ /**
* @return Person ID
*/
int getPersonId() const;
const contacts_record_h getRecord() const;
private:
- const i18n_uchar *getSortValue() const;
+ const Utils::UniString &getSortValue() const;
void initSortValue(const char *sortValue) const;
const char *getDbSortValue() const;
contacts_record_h m_PersonRecord;
contacts_record_h m_ContactRecord;
- mutable i18n_uchar *m_SortValue;
+ mutable Utils::UniString *m_SortValue;
};
}
}
/**
* @brief Person change callback
- * @param[in] id Person ID
+ * @param[in] contact Contact object
* @param[in] changeType Change type
*/
- typedef std::function<void(int id, contacts_changed_e changeType)> ChangeCallback;
+ typedef std::function<void(ContactPtr contact, contacts_changed_e changeType)> ChangeCallback;
/**
* @brief Person insert callback
*/
#include "Contacts/List/ContactGroupItem.h"
+#include "Utils/UniString.h"
using namespace Contacts::List;
+using namespace Utils;
ContactGroupItem::ContactGroupItem(const char *title, Elm_Object_Item *indexItem)
- : m_IndexItem(indexItem)
+ : m_UniTitle(nullptr), m_IndexItem(indexItem)
{
if (title) {
m_Title = title;
}
}
-const char *Contacts::List::ContactGroupItem::getTitle() const
+const UniString &ContactGroupItem::getTitle() const
{
- return m_Title.c_str();
+ if (!m_UniTitle) {
+ m_UniTitle = new UniString(m_Title.c_str());
+ }
+
+ return *m_UniTitle;
}
Elm_Object_Item *ContactGroupItem::getIndexItem() const
return *m_Contact;
}
+void ContactItem::setContact(Model::ContactPtr contact)
+{
+ m_Contact = std::move(contact);
+}
+
char *ContactItem::getText(Evas_Object *parent, const char *part)
{
if (strcmp(part, PART_CONTACT_NAME) == 0) {
using namespace Contacts;
using namespace Contacts::List;
using namespace Contacts::List::Model;
+using namespace Utils;
ListView::ListView()
: m_Genlist(nullptr), m_Index(nullptr),
void ListView::fillList()
{
ContactList list = m_Provider.getContactList();
-
const char *currentLetter = nullptr;
ContactGroupItem *group = nullptr;
currentLetter = nextLetter;
}
- insertItem(std::move(contact), group);
+ m_Genlist->insert(createContactItem(std::move(contact)), group);
}
}
-ContactGroupItem *ListView::insertGroupItem(const char *indexLetter, ContactGroupItem *nextGroup)
+Elm_Object_Item *ListView::insertIndexItem(const char *indexLetter, Elm_Object_Item *nextItem)
{
Elm_Object_Item *indexItem = nullptr;
- if (nextGroup) {
- indexItem = elm_index_item_insert_before(m_Index, nextGroup->getIndexItem(), indexLetter, nullptr, nullptr);
+ if (nextItem) {
+ indexItem = elm_index_item_insert_before(m_Index, nextItem, indexLetter, nullptr, nullptr);
} else {
indexItem = elm_index_item_append(m_Index, indexLetter, nullptr, nullptr);
}
- elm_index_level_go(indexItem, 0);
+ elm_index_level_go(m_Index, 0);
+
+ return indexItem;
+}
+
+ContactGroupItem *ListView::insertGroupItem(const char *indexLetter, ContactGroupItem *nextGroup)
+{
+ Elm_Object_Item *indexItem = insertIndexItem(indexLetter, nextGroup ? nextGroup->getIndexItem() : nullptr);
ContactGroupItem *item = new ContactGroupItem(indexLetter, indexItem);
m_Genlist->insert(item, nullptr, nextGroup);
return item;
}
-ContactGroupItem *ListView::getNextGroupItem(const char *indexLetter)
+void ListView::deleteGroupItem(ContactGroupItem *group)
+{
+ m_Groups.erase(group->getTitle());
+ delete group;
+}
+
+ContactGroupItem *ListView::getNextGroupItem(const Utils::UniString &indexLetter)
{
auto it = m_Groups.lower_bound(indexLetter);
if (it != m_Groups.end()) {
return nullptr;
}
-ContactItem *ListView::insertItem(Model::ContactPtr contact, ContactGroupItem *group, ContactItem *nextItem)
+ContactItem *ListView::createContactItem(ContactPtr contact)
{
+ using namespace std::placeholders;
+
ContactItem *item = new ContactItem(std::move(contact));
- m_Genlist->insert(item, group, nextItem);
+ m_Provider.setChangeCallback(item->getContact().getPersonId(),
+ std::bind(&ListView::onContactChanged, this, _1, _2, item));
return item;
}
-ContactItem *ListView::getNextItem(ContactGroupItem *group, const Contact &contact)
+void ListView::insertContactItem(ContactItem *item)
+{
+ ContactGroupItem *group = nullptr;
+ ContactItem *nextItem = nullptr;
+ const char *indexLetter = item->getContact().getIndexLetter();
+
+ auto it = m_Groups.find(indexLetter);
+ if (it != m_Groups.end()) {
+ group = it->second;
+ nextItem = getNextContactItem(it->second, item->getContact());
+ } else {
+ group = insertGroupItem(indexLetter, getNextGroupItem(indexLetter));
+ }
+
+ m_Genlist->insert(item, group, nextItem);
+}
+
+void ListView::updateContactItem(ContactItem *item, Model::ContactPtr contact)
+{
+ if (item->getContact() != *contact) {
+ ContactGroupItem *oldGroup = static_cast<ContactGroupItem *>(item->getParentItem());
+
+ item->pop();
+
+ item->setContact(std::move(contact));
+ insertContactItem(item);
+
+ if (oldGroup->empty()) {
+ deleteGroupItem(oldGroup);
+ }
+ } else {
+ item->setContact(std::move(contact));
+ if (strcmp(item->getContact().getImagePath(), contact->getImagePath()) != 0) {
+ elm_genlist_item_fields_update(item->getObjectItem(),
+ PART_CONTACT_THUMBNAIL, ELM_GENLIST_ITEM_FIELD_CONTENT);
+ }
+ }
+}
+
+ContactItem *ListView::getNextContactItem(ContactGroupItem *group, const Contact &contact)
{
for (auto &&item : *group) {
ContactItem *contactItem = static_cast<ContactItem *>(item);
- if (!(contactItem->getContact() < contact)) {
+ if (contact < contactItem->getContact()) {
return contactItem;
}
}
void ListView::onContactInserted(ContactPtr contact)
{
- const char *indexLetter = contact->getIndexLetter();
- auto it = m_Groups.find(indexLetter);
+ insertContactItem(createContactItem(std::move(contact)));
+}
- if (it != m_Groups.end()) {
- ContactItem *nextItem = getNextItem(it->second, *contact);
- insertItem(std::move(contact), it->second, nextItem);
- } else {
- ContactGroupItem *group = insertGroupItem(indexLetter, getNextGroupItem(indexLetter));
- insertItem(std::move(contact), group);
+void ListView::onContactChanged(ContactPtr contact, contacts_changed_e changeType, ContactItem *item)
+{
+ if (changeType == CONTACTS_CHANGE_DELETED) {
+// Todo: Implement delete contact functionality
+ } else if (changeType == CONTACTS_CHANGE_UPDATED) {
+ updateContactItem(item, std::move(contact));
}
}
*/
#include "Contacts/List/Model/Contact.h"
+#include "Utils/UniString.h"
using namespace Contacts::List::Model;
+using namespace Utils;
namespace
{
contacts_record_destroy(m_PersonRecord, true);
contacts_record_destroy(m_ContactRecord, true);
- delete[] m_SortValue;
+ delete m_SortValue;
}
bool Contact::operator<(const Contact &that) const
{
- return i18n_ustring_compare_code_point_order(getSortValue(), that.getSortValue()) < 0;
+ return getSortValue() < that.getSortValue();
+}
+
+bool Contact::operator==(const Contact &that) const
+{
+ return getSortValue() == that.getSortValue();
+}
+
+bool Contact::operator!=(const Contact &that) const
+{
+ return getSortValue() != that.getSortValue();
}
int Contact::getPersonId() const
return m_PersonRecord;
}
-const i18n_uchar *Contact::getSortValue() const
+const UniString &Contact::getSortValue() const
{
if (!m_SortValue) {
- initSortValue(getDbSortValue());
+ m_SortValue = new UniString(getDbSortValue());
}
- return m_SortValue;
-}
-
-void Contact::initSortValue(const char *sortValue) const
-{
- i18n_uchar fakeValue;
- int length = 0;
- i18n_error_code_e err = I18N_ERROR_NONE;
- i18n_ustring_from_UTF8(&fakeValue, 1, &length, sortValue, -1, &err);
-
- m_SortValue = new i18n_uchar[length + 1];
-
- i18n_ustring_from_UTF8(m_SortValue, length + 1, &length, sortValue, -1, &err);
+ return *m_SortValue;
}
const char *Contact::getDbSortValue() const
#include "Contacts/List/Model/ContactProvider.h"
#include "Contacts/Utils.h"
#include "Utils/Callback.h"
+#include "Utils/Range.h"
using namespace Contacts::List::Model;
namespace
{
+ unsigned projection[] = {
+ _contacts_person.id,
+ _contacts_person.display_name,
+ _contacts_person.display_name_index,
+ _contacts_person.display_contact_id,
+ _contacts_person.image_thumbnail_path,
+ _contacts_person.is_favorite,
+ _contacts_person.favorite_priority
+ };
+
contacts_filter_h getProviderFilter(ContactProvider::FilterType filterType)
{
bool emptyFilter = true;
contacts_list_h getContactList(ContactProvider::FilterType filterType)
{
- contacts_list_h list = nullptr;
- contacts_query_h query = nullptr;
- unsigned projection[] = {
- _contacts_person.id,
- _contacts_person.display_name,
- _contacts_person.display_name_index,
- _contacts_person.display_contact_id,
- _contacts_person.image_thumbnail_path,
- _contacts_person.is_favorite,
- _contacts_person.favorite_priority
- };
+ contacts_filter_h filter = getProviderFilter(filterType);
+ contacts_query_h query = nullptr;
contacts_query_create(_contacts_person._uri, &query);
-
- contacts_filter_h filter = getProviderFilter(filterType);
contacts_query_set_filter(query, filter);
+ contacts_query_set_projection(query, projection, Utils::count(projection));
- contacts_query_set_projection(query, projection, sizeof(projection) / sizeof(*projection));
+ contacts_list_h list = nullptr;
contacts_db_get_records_with_query(query, 0, 0, &list);
- contacts_filter_destroy(filter);
contacts_query_destroy(query);
+ contacts_filter_destroy(filter);
return list;
}
contacts_query_h query = nullptr;
contacts_query_create(_contacts_person._uri, &query);
contacts_query_set_filter(query, filter);
+ contacts_query_set_projection(query, projection, Utils::count(projection));
contacts_list_h list = nullptr;
contacts_db_get_records_with_query(query, 0, 1, &list);
case CONTACTS_CHANGE_DELETED:
auto it = m_ChangeCallbacks.find(contact->getPersonId());
if (it != m_ChangeCallbacks.end()) {
- it->second(it->first, changeType);
+ it->second(std::move(contact), changeType);
}
break;
}