4 #include <Elementary.h>
11 #include "contacts-ofono-efl.h"
14 #ifndef EET_COMPRESSION_DEFAULT
15 #define EET_COMPRESSION_DEFAULT 1
18 #define CONTACTS_ENTRY "contacts"
20 typedef struct _Contacts_List {
23 Ecore_Poller *save_poller;
26 typedef struct _Contacts {
29 Eet_Data_Descriptor *edd;
30 Eet_Data_Descriptor *edd_list;
31 Elm_Genlist_Item_Class *itc, *group;
32 Evas_Object *genlist, *layout, *details;
33 Contacts_List *c_list;
36 struct _Contact_Info {
37 const char *first_name;
38 const char *last_name;
39 const char *full_name; /* not in edd */
45 Contacts *contacts; /* not in edd */
46 Elm_Object_Item *it; /* not in edd */
47 Eina_Inlist *on_del_cbs; /* not in edd */
48 Ecore_Idler *changed_idler; /* not in edd */
50 Eina_Inlist *listeners;
53 } on_changed_cbs; /* not in edd */
56 typedef struct _Contact_Info_On_Del_Ctx {
58 void (*cb)(void *, const Contact_Info *);
60 } Contact_Info_On_Del_Ctx;
62 typedef struct _Contact_Info_On_Changed_Ctx {
64 void (*cb)(void *, Contact_Info *);
67 } Contact_Info_On_Changed_Ctx;
69 Eina_List *contact_info_all_numbers_get(const Contact_Info *c)
73 EINA_SAFETY_ON_NULL_RETURN_VAL(c, NULL);
76 l = eina_list_append(l, c->mobile);
78 l = eina_list_append(l, c->work);
80 l = eina_list_append(l, c->home);
85 static Eina_Bool _number_match(const char *n1, const char *n2)
87 if (eina_str_has_suffix(n1, n2))
93 struct _Contact_Partial_Match
95 const Contact_Info *info;
97 Eina_Bool name_match : 1;
100 static void _partial_match_add(Eina_List **p_list, const char *type,
101 const Contact_Info *c_info,
102 Eina_Bool name_match)
104 Contact_Partial_Match *pm = malloc(sizeof(Contact_Partial_Match));
105 EINA_SAFETY_ON_NULL_RETURN(pm);
108 pm->name_match = name_match;
109 *p_list = eina_list_append(*p_list, pm);
112 static void _partial_name_match_add(Eina_List **p_list,
113 const Contact_Info *c_info)
116 _partial_match_add(p_list, "Mobile", c_info, EINA_TRUE);
118 _partial_match_add(p_list, "Work", c_info, EINA_TRUE);
120 _partial_match_add(p_list, "Home", c_info, EINA_TRUE);
123 static void _partial_number_match_add(Eina_List **p_list, const char *type,
124 const Contact_Info *c_info)
126 _partial_match_add(p_list, type, c_info, EINA_FALSE);
129 Eina_List *contact_partial_match_search(Evas_Object *obj, const char *query)
131 const Contact_Info *c_info;
132 const Contacts *contacts;
133 Eina_List *ret = NULL, *l;
135 Eina_Bool name_search = EINA_FALSE;
138 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
139 EINA_SAFETY_ON_NULL_RETURN_VAL(query, NULL);
140 contacts = evas_object_data_get(obj, "contacts.ctx");
141 EINA_SAFETY_ON_NULL_RETURN_VAL(contacts, NULL);
143 /* Check if it is numeric */
144 query_number = alloca(strlen(query) + 1);
145 EINA_SAFETY_ON_NULL_RETURN_VAL(query_number, NULL);
146 for (i = 0, j = 0; query[i] != '\0'; i++) {
147 if (isalpha(query[i])) {
148 name_search = EINA_TRUE;
150 } else if (isdigit(query[i]))
151 query_number[j++] = query[i];
155 EINA_LIST_FOREACH(contacts->c_list->list, l, c_info) {
156 const char *full_name;
158 full_name = contact_info_full_name_get(c_info);
159 if (strcasestr(full_name, query))
160 _partial_name_match_add(&ret, c_info);
163 query_number[j] = '\0';
164 EINA_LIST_FOREACH(contacts->c_list->list, l, c_info) {
165 if (_number_match(c_info->mobile, query_number))
166 _partial_number_match_add(&ret, "Mobile",
169 if (_number_match(c_info->work, query_number))
170 _partial_number_match_add(&ret, "Work",
173 if (_number_match(c_info->home, query_number))
174 _partial_number_match_add(&ret, "Home",
182 void contact_partial_match_search_free(Eina_List *results)
184 Contact_Partial_Match *pm;
185 EINA_LIST_FREE(results, pm)
189 const char *contact_partial_match_type_get(const Contact_Partial_Match *pm)
191 EINA_SAFETY_ON_NULL_RETURN_VAL(pm, NULL);
195 const Contact_Info *contact_partial_match_info_get(const Contact_Partial_Match *pm)
197 EINA_SAFETY_ON_NULL_RETURN_VAL(pm, NULL);
201 Eina_Bool contact_partial_match_name_match_get(const Contact_Partial_Match *pm)
203 EINA_SAFETY_ON_NULL_RETURN_VAL(pm, EINA_FALSE);
204 return pm->name_match;
207 Contact_Info *contact_search(Evas_Object *obj, const char *number, const char **type)
209 Contact_Info *c_info;
213 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
214 EINA_SAFETY_ON_NULL_RETURN_VAL(number, NULL);
215 contacts = evas_object_data_get(obj, "contacts.ctx");
216 EINA_SAFETY_ON_NULL_RETURN_VAL(contacts, NULL);
218 EINA_LIST_FOREACH(contacts->c_list->list, l, c_info) {
219 if (strcmp(number, c_info->mobile) == 0) {
223 } else if (strcmp(number, c_info->work) == 0) {
227 } else if (strcmp(number, c_info->home) == 0) {
237 const char *contact_info_full_name_get(const Contact_Info *c)
241 EINA_SAFETY_ON_NULL_RETURN_VAL(c, NULL);
246 c2 = (Contact_Info *)c;
247 c2->full_name = eina_stringshare_printf("%s %s",
248 c->first_name, c->last_name);
252 const char *contact_info_first_name_get(const Contact_Info *c)
254 EINA_SAFETY_ON_NULL_RETURN_VAL(c, NULL);
255 return c->first_name;
258 const char *contact_info_last_name_get(const Contact_Info *c)
260 EINA_SAFETY_ON_NULL_RETURN_VAL(c, NULL);
264 const char *contact_info_picture_get(const Contact_Info *c)
266 EINA_SAFETY_ON_NULL_RETURN_VAL(c, NULL);
270 const char *contact_info_detail_get(const Contact_Info *c, const char *type)
272 EINA_SAFETY_ON_NULL_RETURN_VAL(c, NULL);
273 EINA_SAFETY_ON_NULL_RETURN_VAL(type, NULL);
274 if (strcmp(type, "Mobile") == 0)
276 else if (strcmp(type, "Work") == 0)
278 else if (strcmp(type, "Home") == 0)
284 const char *contact_info_number_check(const Contact_Info *c, const char *number)
286 EINA_SAFETY_ON_NULL_RETURN_VAL(c, NULL);
287 EINA_SAFETY_ON_NULL_RETURN_VAL(number, NULL);
289 if (strcmp(number, c->mobile) == 0)
291 else if (strcmp(number, c->work) == 0)
293 else if (strcmp(number, c->home) == 0)
299 static Eina_Bool _contacts_save_do(void *data)
301 Contacts *contacts = data;
304 contacts->c_list->save_poller = NULL;
305 contacts->c_list->dirty = EINA_FALSE;
307 ecore_file_unlink(contacts->bkp);
308 ecore_file_mv(contacts->path, contacts->bkp);
309 efile = eet_open(contacts->path, EET_FILE_MODE_WRITE);
310 EINA_SAFETY_ON_NULL_GOTO(efile, failed);
311 if (!(eet_data_write(efile,
312 contacts->edd_list, CONTACTS_ENTRY,
313 contacts->c_list, EET_COMPRESSION_DEFAULT)))
314 ERR("Could in the contacts database");
316 DBG("wrote %s", contacts->path);
321 ecore_file_mv(contacts->bkp, contacts->path);
325 static void _contacts_save(Contacts *contacts)
327 if (contacts->c_list->save_poller)
330 contacts->c_list->save_poller = ecore_poller_add
331 (ECORE_POLLER_CORE, 32, _contacts_save_do, contacts);
334 static Eina_Bool _contact_info_changed_idler(void *data)
336 Contact_Info *c = data;
337 Contact_Info_On_Changed_Ctx *ctx;
339 c->changed_idler = NULL;
341 c->on_changed_cbs.walking++;
342 EINA_INLIST_FOREACH(c->on_changed_cbs.listeners, ctx) {
345 ctx->cb((void *)ctx->data, c);
347 c->on_changed_cbs.walking--;
349 _contacts_save(c->contacts);
351 if (c->on_changed_cbs.walking > 0)
354 EINA_LIST_FREE(c->on_changed_cbs.deleted, ctx) {
355 c->on_changed_cbs.listeners = eina_inlist_remove(
356 c->on_changed_cbs.listeners, EINA_INLIST_GET(ctx));
363 static void _contact_info_changed(Contact_Info *c)
365 if (c->changed_idler)
367 c->changed_idler = ecore_idler_add(_contact_info_changed_idler, c);
370 Eina_Bool contact_info_picture_set(Contact_Info *c, const char *filename)
372 EINA_SAFETY_ON_NULL_RETURN_VAL(c, EINA_FALSE);
373 EINA_SAFETY_ON_NULL_RETURN_VAL(filename, EINA_FALSE);
375 DBG("c=%p, was=%s, new=%s", c, c->picture, filename);
377 if (eina_stringshare_replace(&(c->picture), filename))
378 _contact_info_changed(c);
383 Eina_Bool contact_info_first_name_set(Contact_Info *c, const char *name)
385 EINA_SAFETY_ON_NULL_RETURN_VAL(c, EINA_FALSE);
386 EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE);
388 DBG("c=%p, was=%s, new=%s", c, c->first_name, name);
390 if (eina_stringshare_replace(&(c->first_name), name)) {
391 eina_stringshare_replace(&(c->full_name), NULL);
392 _contact_info_changed(c);
398 Eina_Bool contact_info_last_name_set(Contact_Info *c, const char *name)
400 EINA_SAFETY_ON_NULL_RETURN_VAL(c, EINA_FALSE);
401 EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE);
403 DBG("c=%p, was=%s, new=%s", c, c->last_name, name);
405 if (eina_stringshare_replace(&(c->last_name), name)) {
406 eina_stringshare_replace(&(c->full_name), NULL);
407 _contact_info_changed(c);
413 Eina_Bool contact_info_detail_set(Contact_Info *c, const char *type, const char *number)
415 Eina_Bool changed = EINA_FALSE;
417 EINA_SAFETY_ON_NULL_RETURN_VAL(c, EINA_FALSE);
418 EINA_SAFETY_ON_NULL_RETURN_VAL(type, EINA_FALSE);
419 EINA_SAFETY_ON_NULL_RETURN_VAL(number, EINA_FALSE);
421 DBG("c=%p, type=%s, number=%s", c, type, number);
423 if (strcmp(type, "Mobile") == 0)
424 changed = eina_stringshare_replace(&(c->mobile), number);
425 else if (strcmp(type, "Work") == 0)
426 changed = eina_stringshare_replace(&(c->work), number);
427 else if (strcmp(type, "Home") == 0)
428 changed = eina_stringshare_replace(&(c->home), number);
430 ERR("Unknown type: %s, number: %s", type, number);
435 _contact_info_changed(c);
441 void contact_info_on_changed_callback_add(Contact_Info *c,
442 void (*cb)(void *data, Contact_Info *c),
445 Contact_Info_On_Changed_Ctx *ctx;
447 EINA_SAFETY_ON_NULL_RETURN(c);
448 EINA_SAFETY_ON_NULL_RETURN(cb);
450 ctx = calloc(1, sizeof(Contact_Info_On_Changed_Ctx));
451 EINA_SAFETY_ON_NULL_RETURN(ctx);
455 c->on_changed_cbs.listeners = eina_inlist_append(
456 c->on_changed_cbs.listeners, EINA_INLIST_GET(ctx));
459 void contact_info_on_changed_callback_del(Contact_Info *c,
460 void (*cb)(void *data, Contact_Info *c),
463 Contact_Info_On_Changed_Ctx *ctx, *found = NULL;
464 EINA_SAFETY_ON_NULL_RETURN(c);
465 EINA_SAFETY_ON_NULL_RETURN(cb);
467 EINA_INLIST_FOREACH(c->on_changed_cbs.listeners, ctx) {
468 if (ctx->cb == cb && ctx->data == data) {
477 if (c->on_changed_cbs.walking > 0) {
478 found->deleted = EINA_TRUE;
479 c->on_changed_cbs.deleted = eina_list_append(
480 c->on_changed_cbs.deleted, found);
484 c->on_changed_cbs.listeners = eina_inlist_remove(
485 c->on_changed_cbs.listeners, EINA_INLIST_GET(found));
490 void contact_info_on_del_callback_add(Contact_Info *c,
491 void (*cb)(void *data, const Contact_Info *c),
494 Contact_Info_On_Del_Ctx *ctx;
496 EINA_SAFETY_ON_NULL_RETURN(c);
497 EINA_SAFETY_ON_NULL_RETURN(cb);
499 ctx = calloc(1, sizeof(Contact_Info_On_Del_Ctx));
500 EINA_SAFETY_ON_NULL_RETURN(ctx);
504 c->on_del_cbs = eina_inlist_append(c->on_del_cbs, EINA_INLIST_GET(ctx));
507 void contact_info_on_del_callback_del(Contact_Info *c,
508 void (*cb)(void *data, const Contact_Info *c),
511 Contact_Info_On_Del_Ctx *ctx, *found = NULL;
512 EINA_SAFETY_ON_NULL_RETURN(c);
513 EINA_SAFETY_ON_NULL_RETURN(cb);
515 EINA_INLIST_FOREACH(c->on_del_cbs, ctx) {
516 if (ctx->cb == cb && ctx->data == data) {
525 c->on_del_cbs = eina_inlist_remove(c->on_del_cbs,
526 EINA_INLIST_GET(found));
531 static void _contact_info_on_del_dispatch(Contact_Info *c)
533 Eina_Inlist *lst = c->on_del_cbs;
534 c->on_del_cbs = NULL; /* avoid contact_info_on_del_callback_del() */
536 Contact_Info_On_Del_Ctx *ctx = EINA_INLIST_CONTAINER_GET
537 (lst, Contact_Info_On_Del_Ctx);
539 lst = eina_inlist_remove(lst, lst);
541 ctx->cb((void *)ctx->data, c);
546 static void _contact_info_free(Contact_Info *c_info);
548 void contact_info_del(Contact_Info *c)
552 EINA_SAFETY_ON_NULL_RETURN(c);
554 _contact_info_on_del_dispatch(c);
557 elm_object_item_del(c->it);
559 contacts = c->contacts;
560 contacts->c_list->list = eina_list_remove(contacts->c_list->list, c);
561 contacts->c_list->dirty = EINA_TRUE;
562 _contacts_save(contacts);
564 _contact_info_free(c);
567 static void _contacts_info_descriptor_init(Eet_Data_Descriptor **edd,
568 Eet_Data_Descriptor **edd_list)
570 Eet_Data_Descriptor_Class eddc;
572 EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Contact_Info);
573 *edd = eet_data_descriptor_stream_new(&eddc);
575 EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Contacts_List);
576 *edd_list = eet_data_descriptor_stream_new(&eddc);
578 EET_DATA_DESCRIPTOR_ADD_BASIC(*edd, Contact_Info,
579 "picture", picture, EET_T_STRING);
580 EET_DATA_DESCRIPTOR_ADD_BASIC(*edd, Contact_Info,
581 "work", work, EET_T_STRING);
582 EET_DATA_DESCRIPTOR_ADD_BASIC(*edd, Contact_Info,
583 "home", home, EET_T_STRING);
584 EET_DATA_DESCRIPTOR_ADD_BASIC(*edd, Contact_Info,
585 "mobile", mobile, EET_T_STRING);
586 EET_DATA_DESCRIPTOR_ADD_BASIC(*edd, Contact_Info,
587 "first_name", first_name, EET_T_STRING);
588 EET_DATA_DESCRIPTOR_ADD_BASIC(*edd, Contact_Info,
589 "last_name", last_name, EET_T_STRING);
591 EET_DATA_DESCRIPTOR_ADD_LIST(*edd_list, Contacts_List, "list", list,
595 static void _contact_info_free(Contact_Info *c_info)
597 EINA_SAFETY_ON_FALSE_RETURN(c_info->on_changed_cbs.walking == 0);
599 if (c_info->on_changed_cbs.deleted) {
600 ERR("contact still have changed deleted listeners: %p %s %s",
601 c_info, c_info->first_name, c_info->last_name);
602 eina_list_free(c_info->on_changed_cbs.deleted);
605 if (c_info->on_changed_cbs.listeners) {
606 while (c_info->on_changed_cbs.listeners) {
607 Contact_Info_On_Changed_Ctx *ctx;
609 ctx = EINA_INLIST_CONTAINER_GET(
610 c_info->on_changed_cbs.listeners,
611 Contact_Info_On_Changed_Ctx);
612 c_info->on_changed_cbs.listeners = eina_inlist_remove
613 (c_info->on_changed_cbs.listeners,
614 c_info->on_changed_cbs.listeners);
619 if (c_info->changed_idler)
620 ecore_idler_del(c_info->changed_idler);
622 eina_stringshare_del(c_info->first_name);
623 eina_stringshare_del(c_info->last_name);
624 eina_stringshare_del(c_info->full_name);
625 eina_stringshare_del(c_info->mobile);
626 eina_stringshare_del(c_info->home);
627 eina_stringshare_del(c_info->work);
628 eina_stringshare_del(c_info->picture);
632 static void _on_del(void *data, Evas *e __UNUSED__,
633 Evas_Object *obj __UNUSED__, void *event __UNUSED__)
635 Contacts *contacts = data;
636 Contact_Info *c_info;
638 if (contacts->c_list->save_poller)
639 ecore_poller_del(contacts->c_list->save_poller);
640 if (contacts->c_list->dirty)
641 _contacts_save_do(contacts);
643 eet_data_descriptor_free(contacts->edd);
644 eet_data_descriptor_free(contacts->edd_list);
645 EINA_LIST_FREE(contacts->c_list->list, c_info) {
646 _contact_info_on_del_dispatch(c_info);
647 _contact_info_free(c_info);
649 free(contacts->c_list);
650 elm_genlist_item_class_free(contacts->itc);
651 elm_genlist_item_class_free(contacts->group);
652 free(contacts->path);
658 static void _on_number_clicked(void *data, Evas_Object *obj,
659 void *event_inf __UNUSED__)
661 const char *number = data;
662 Evas_Object *contacts = evas_object_data_get(obj, "contacts");
663 printf("contacts=%p, number=%p\n", contacts, number);
664 evas_object_smart_callback_call(contacts, "selected", (void *)number);
667 static void _on_item_click(void *data, Evas_Object *obj __UNUSED__,
670 Contacts *contacts = data;
671 Elm_Object_Item *item = event_inf;
672 Evas_Object *details, *btn, *photo;
673 Contact_Info *c_info;
676 details = contacts->details;
677 c_info = elm_object_item_data_get(item);
678 elm_genlist_item_selected_set(item, EINA_FALSE);
679 elm_layout_box_remove_all(details, "box.phones", EINA_TRUE);
681 elm_object_part_text_set(details, "text.name", c_info->first_name);
682 elm_object_part_text_set(details, "text.last.name", c_info->last_name);
684 photo = picture_icon_get(details, c_info->picture);
685 elm_object_part_content_set(details, "swallow.photo", photo);
687 btn = elm_button_add(details);
688 EINA_SAFETY_ON_NULL_RETURN(btn);
689 elm_object_style_set(btn, "contacts");
690 phone = phone_format(c_info->mobile);
691 elm_object_part_text_set(btn, "elm.text.type", "Mobile");
692 elm_object_part_text_set(btn, "elm.text.phone", phone);
694 evas_object_size_hint_weight_set(btn, EVAS_HINT_EXPAND,
696 evas_object_size_hint_align_set(btn, EVAS_HINT_FILL, EVAS_HINT_FILL);
697 evas_object_show(btn);
698 evas_object_data_set(btn, "contacts", contacts->layout);
699 evas_object_smart_callback_add(btn, "clicked", _on_number_clicked,
701 elm_layout_box_append(details, "box.phones", btn);
703 btn = elm_button_add(details);
704 EINA_SAFETY_ON_NULL_RETURN(btn);
705 elm_object_style_set(btn, "contacts");
706 phone = phone_format(c_info->home);
707 elm_object_part_text_set(btn, "elm.text.type", "Home");
708 elm_object_part_text_set(btn, "elm.text.phone", phone);
710 evas_object_size_hint_weight_set(btn, EVAS_HINT_EXPAND,
712 evas_object_size_hint_align_set(btn, EVAS_HINT_FILL, EVAS_HINT_FILL);
713 evas_object_show(btn);
714 evas_object_data_set(btn, "contacts", contacts->layout);
715 evas_object_smart_callback_add(btn, "clicked", _on_number_clicked,
717 elm_layout_box_append(details, "box.phones", btn);
719 btn = elm_button_add(details);
720 EINA_SAFETY_ON_NULL_RETURN(btn);
721 elm_object_style_set(btn, "contacts");
722 phone = phone_format(c_info->work);
723 elm_object_part_text_set(btn, "elm.text.type", "Work");
724 elm_object_part_text_set(btn, "elm.text.phone", phone);
726 evas_object_size_hint_weight_set(btn, EVAS_HINT_EXPAND,
728 evas_object_size_hint_align_set(btn, EVAS_HINT_FILL, EVAS_HINT_FILL);
729 evas_object_show(btn);
730 evas_object_data_set(btn, "contacts", contacts->layout);
731 evas_object_smart_callback_add(btn, "clicked", _on_number_clicked,
733 elm_layout_box_append(details, "box.phones", btn);
734 elm_object_signal_emit(contacts->layout, "show,details", "gui");
737 static int _sort_by_name_cb(const void *v1, const void *v2)
739 const Contact_Info *c1, *c2;
748 r = strcmp(c1->first_name, c2->first_name);
750 return strcmp(c1->last_name, c2->last_name);
755 static void _contacts_read(Contacts *contacts)
757 Contact_Info *c_info;
760 Elm_Object_Item *it = NULL;
762 efile = eet_open(contacts->path, EET_FILE_MODE_READ);
765 contacts->c_list = eet_data_read(efile, contacts->edd_list,
770 if (!contacts->c_list) {
771 efile = eet_open(contacts->bkp, EET_FILE_MODE_READ);
773 contacts->c_list = eet_data_read(
774 efile, contacts->edd_list, CONTACTS_ENTRY);
779 if (!contacts->c_list)
780 contacts->c_list = calloc(1, sizeof(Contacts_List));
782 EINA_SAFETY_ON_NULL_RETURN(contacts->c_list);
783 contacts->c_list->list = eina_list_sort(contacts->c_list->list, 0,
786 EINA_LIST_FOREACH(contacts->c_list->list, l, c_info) {
789 if (group != c_info->first_name[0]) {
790 group = c_info->first_name[0];
791 it = elm_genlist_item_append(contacts->genlist,
794 ELM_GENLIST_ITEM_GROUP,
797 elm_genlist_item_select_mode_set(it, ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY);
799 it = elm_genlist_item_append(contacts->genlist,contacts->itc,
801 ELM_GENLIST_ITEM_NONE,
802 _on_item_click, contacts);
804 c_info->contacts = contacts;
808 static char *_item_label_get(void *data, Evas_Object *obj __UNUSED__,
811 Contact_Info *c_info = data;
813 if (strncmp(part, "text.contacts.", strlen("text.contacts.")))
816 part += strlen("text.contacts.");
818 if (strcmp(part, "name") == 0)
819 return strdup(c_info->first_name);
820 else if (strcmp(part, "last") == 0)
821 return strdup(c_info->last_name);
822 else if (strcmp(part, "full") == 0)
823 return strdup(contact_info_full_name_get(c_info));
825 ERR("Unexpected part name: %s", part);
829 static char *_group_label_get(void *data, Evas_Object *obj __UNUSED__,
830 const char *part __UNUSED__)
832 Contact_Info *c_info = data;
834 snprintf(buf, sizeof(buf), "%c", c_info->first_name[0]);
839 static Evas_Object *_item_content_get(void *data,
843 Contact_Info *c_info = data;
846 if (strncmp(part, "swallow.", strlen("swallow.")))
849 part += strlen("swallow.");
851 if (strcmp(part, "photo") != 0) {
852 ERR("Unexpected part name: %s", part);
856 photo = picture_icon_get(obj, c_info->picture);
861 static void _on_back_clicked(void *data, Evas_Object *obj __UNUSED__,
862 const char *emission __UNUSED__,
863 const char *source __UNUSED__)
865 Evas_Object *layout = data;
866 elm_object_signal_emit(layout, "hide,details", "gui");
869 Evas_Object *contacts_add(Evas_Object *parent)
872 const char *config_path;
873 char base_dir[PATH_MAX], *path;
875 Evas_Object *obj, *genlist, *details;
876 Elm_Genlist_Item_Class *itc, *group;
879 contacts = calloc(1, sizeof(Contacts));
880 EINA_SAFETY_ON_NULL_RETURN_VAL(contacts, NULL);
883 details = layout_add(parent, "contacts_details");
884 EINA_SAFETY_ON_NULL_GOTO(details, err_layout);
886 obj = layout_add(parent, "contacts_bg");
887 EINA_SAFETY_ON_NULL_GOTO(obj, err_obj);
889 genlist = elm_genlist_add(obj);
890 EINA_SAFETY_ON_NULL_GOTO(genlist, err_genlist);
891 elm_object_style_set(genlist, "contacts");
892 elm_genlist_homogeneous_set(genlist, EINA_TRUE);
894 itc = elm_genlist_item_class_new();
895 EINA_SAFETY_ON_NULL_GOTO(itc, err_genlist);
896 itc->item_style = "contacts";
897 itc->func.text_get = _item_label_get;
898 itc->func.content_get = _item_content_get;
899 itc->func.state_get = NULL;
900 itc->func.del = NULL;
902 group = elm_genlist_item_class_new();
903 EINA_SAFETY_ON_NULL_GOTO(group, err_group);
904 group->item_style = "group_contacts";
905 group->func.text_get = _group_label_get;
906 group->func.content_get = NULL;
907 group->func.state_get = NULL;
908 group->func.del = NULL;
909 contacts->group = group;
910 contacts->genlist = genlist;
912 contacts->layout = obj;
913 contacts->details = details;
915 elm_object_part_content_set(obj, "elm.swallow.genlist", genlist);
916 elm_object_part_content_set(obj, "elm.swallow.details", details);
918 elm_object_signal_callback_add(details, "clicked,back", "gui",
919 _on_back_clicked, obj);
921 config_path = efreet_config_home_get();
922 snprintf(base_dir, sizeof(base_dir), "%s/%s", config_path,
924 ecore_file_mkpath(base_dir);
926 r = asprintf(&path, "%s/%s/contacts.eet", config_path, PACKAGE_NAME);
930 contacts->path = path;
932 r = asprintf(&path, "%s/%s/contacts.eet.bkp", config_path,
937 contacts->bkp = path;
939 _contacts_info_descriptor_init(&contacts->edd, &contacts->edd_list);
940 _contacts_read(contacts);
941 EINA_SAFETY_ON_NULL_GOTO(contacts->c_list, err_read);
943 evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, _on_del,
946 evas_object_data_set(obj, "contacts.ctx", contacts);
950 eet_data_descriptor_free(contacts->edd);
951 eet_data_descriptor_free(contacts->edd_list);
954 free(contacts->path);
956 elm_genlist_item_class_free(group);
958 elm_genlist_item_class_free(itc);