4 #include <Elementary.h>
11 #include "contacts-ofono-efl.h"
15 #ifndef EET_COMPRESSION_DEFAULT
16 #define EET_COMPRESSION_DEFAULT 1
19 #define CONTACTS_ENTRY "contacts"
21 typedef struct _Contacts_List {
24 Ecore_Poller *save_poller;
27 typedef struct _Contacts {
30 Eet_Data_Descriptor *edd;
31 Eet_Data_Descriptor *edd_list;
32 Elm_Genlist_Item_Class *itc, *group;
33 Evas_Object *genlist, *layout, *details;
34 Contacts_List *c_list;
37 struct _Contact_Info {
38 const char *first_name;
39 const char *last_name;
40 const char *full_name; /* not in edd */
46 Contacts *contacts; /* not in edd */
47 Elm_Object_Item *it; /* not in edd */
48 Eina_Inlist *on_del_cbs; /* not in edd */
49 Ecore_Idler *changed_idler; /* not in edd */
51 Eina_Inlist *listeners;
54 } on_changed_cbs; /* not in edd */
57 typedef struct _Contact_Info_On_Del_Ctx {
59 void (*cb)(void *, const Contact_Info *);
61 } Contact_Info_On_Del_Ctx;
63 typedef struct _Contact_Info_On_Changed_Ctx {
65 void (*cb)(void *, Contact_Info *);
68 } Contact_Info_On_Changed_Ctx;
70 Eina_List *contact_info_all_numbers_get(const Contact_Info *c)
74 EINA_SAFETY_ON_NULL_RETURN_VAL(c, NULL);
77 l = eina_list_append(l, c->mobile);
79 l = eina_list_append(l, c->work);
81 l = eina_list_append(l, c->home);
86 static Eina_Bool _number_match(const char *n1, const char *n2)
88 if (eina_str_has_suffix(n1, n2))
94 struct _Contact_Partial_Match
96 const Contact_Info *info;
98 Eina_Bool name_match : 1;
101 static void _partial_match_add(Eina_List **p_list, const char *type,
102 const Contact_Info *c_info,
103 Eina_Bool name_match)
105 Contact_Partial_Match *pm = malloc(sizeof(Contact_Partial_Match));
106 EINA_SAFETY_ON_NULL_RETURN(pm);
109 pm->name_match = name_match;
110 *p_list = eina_list_append(*p_list, pm);
113 static void _partial_name_match_add(Eina_List **p_list,
114 const Contact_Info *c_info)
117 _partial_match_add(p_list, "Mobile", c_info, EINA_TRUE);
119 _partial_match_add(p_list, "Work", c_info, EINA_TRUE);
121 _partial_match_add(p_list, "Home", c_info, EINA_TRUE);
124 static void _partial_number_match_add(Eina_List **p_list, const char *type,
125 const Contact_Info *c_info)
127 _partial_match_add(p_list, type, c_info, EINA_FALSE);
130 Eina_List *contact_partial_match_search(Evas_Object *obj, const char *query)
132 const Contact_Info *c_info;
133 const Contacts *contacts;
134 Eina_List *ret = NULL, *l;
136 Eina_Bool name_search = EINA_FALSE;
139 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
140 EINA_SAFETY_ON_NULL_RETURN_VAL(query, NULL);
141 contacts = evas_object_data_get(obj, "contacts.ctx");
142 EINA_SAFETY_ON_NULL_RETURN_VAL(contacts, NULL);
144 /* Check if it is numeric */
145 query_number = alloca(strlen(query) + 1);
146 EINA_SAFETY_ON_NULL_RETURN_VAL(query_number, NULL);
147 for (i = 0, j = 0; query[i] != '\0'; i++) {
148 if (isalpha(query[i])) {
149 name_search = EINA_TRUE;
151 } else if (isdigit(query[i]))
152 query_number[j++] = query[i];
156 EINA_LIST_FOREACH(contacts->c_list->list, l, c_info) {
157 const char *full_name;
159 full_name = contact_info_full_name_get(c_info);
160 if (strcasestr(full_name, query))
161 _partial_name_match_add(&ret, c_info);
164 query_number[j] = '\0';
165 EINA_LIST_FOREACH(contacts->c_list->list, l, c_info) {
166 if (_number_match(c_info->mobile, query_number))
167 _partial_number_match_add(&ret, "Mobile",
170 if (_number_match(c_info->work, query_number))
171 _partial_number_match_add(&ret, "Work",
174 if (_number_match(c_info->home, query_number))
175 _partial_number_match_add(&ret, "Home",
183 void contact_partial_match_search_free(Eina_List *results)
185 Contact_Partial_Match *pm;
186 EINA_LIST_FREE(results, pm)
190 const char *contact_partial_match_type_get(const Contact_Partial_Match *pm)
192 EINA_SAFETY_ON_NULL_RETURN_VAL(pm, NULL);
196 const Contact_Info *contact_partial_match_info_get(const Contact_Partial_Match *pm)
198 EINA_SAFETY_ON_NULL_RETURN_VAL(pm, NULL);
202 Eina_Bool contact_partial_match_name_match_get(const Contact_Partial_Match *pm)
204 EINA_SAFETY_ON_NULL_RETURN_VAL(pm, EINA_FALSE);
205 return pm->name_match;
208 Contact_Info *contact_search(Evas_Object *obj, const char *number, const char **type)
210 Contact_Info *c_info;
214 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
215 EINA_SAFETY_ON_NULL_RETURN_VAL(number, NULL);
216 contacts = evas_object_data_get(obj, "contacts.ctx");
217 EINA_SAFETY_ON_NULL_RETURN_VAL(contacts, NULL);
219 EINA_LIST_FOREACH(contacts->c_list->list, l, c_info) {
220 if (strcmp(number, c_info->mobile) == 0) {
224 } else if (strcmp(number, c_info->work) == 0) {
228 } else if (strcmp(number, c_info->home) == 0) {
238 const char *contact_info_full_name_get(const Contact_Info *c)
242 EINA_SAFETY_ON_NULL_RETURN_VAL(c, NULL);
247 c2 = (Contact_Info *)c;
248 c2->full_name = eina_stringshare_printf("%s %s",
249 c->first_name, c->last_name);
253 const char *contact_info_first_name_get(const Contact_Info *c)
255 EINA_SAFETY_ON_NULL_RETURN_VAL(c, NULL);
256 return c->first_name;
259 const char *contact_info_last_name_get(const Contact_Info *c)
261 EINA_SAFETY_ON_NULL_RETURN_VAL(c, NULL);
265 const char *contact_info_picture_get(const Contact_Info *c)
267 EINA_SAFETY_ON_NULL_RETURN_VAL(c, NULL);
271 const char *contact_info_detail_get(const Contact_Info *c, const char *type)
273 EINA_SAFETY_ON_NULL_RETURN_VAL(c, NULL);
274 EINA_SAFETY_ON_NULL_RETURN_VAL(type, NULL);
275 if (strcmp(type, "Mobile") == 0)
277 else if (strcmp(type, "Work") == 0)
279 else if (strcmp(type, "Home") == 0)
285 const char *contact_info_number_check(const Contact_Info *c, const char *number)
287 EINA_SAFETY_ON_NULL_RETURN_VAL(c, NULL);
288 EINA_SAFETY_ON_NULL_RETURN_VAL(number, NULL);
290 if (strcmp(number, c->mobile) == 0)
292 else if (strcmp(number, c->work) == 0)
294 else if (strcmp(number, c->home) == 0)
300 static Eina_Bool _contacts_save_do(void *data)
302 Contacts *contacts = data;
305 contacts->c_list->save_poller = NULL;
306 contacts->c_list->dirty = EINA_FALSE;
308 ecore_file_unlink(contacts->bkp);
309 ecore_file_mv(contacts->path, contacts->bkp);
310 efile = eet_open(contacts->path, EET_FILE_MODE_WRITE);
311 EINA_SAFETY_ON_NULL_GOTO(efile, failed);
312 if (!(eet_data_write(efile,
313 contacts->edd_list, CONTACTS_ENTRY,
314 contacts->c_list, EET_COMPRESSION_DEFAULT)))
315 ERR("Could in the contacts database");
317 DBG("wrote %s", contacts->path);
322 ecore_file_mv(contacts->bkp, contacts->path);
326 static void _contacts_save(Contacts *contacts)
328 if (contacts->c_list->save_poller)
331 contacts->c_list->save_poller = ecore_poller_add
332 (ECORE_POLLER_CORE, 32, _contacts_save_do, contacts);
335 static Eina_Bool _contact_info_changed_idler(void *data)
337 Contact_Info *c = data;
338 Contact_Info_On_Changed_Ctx *ctx;
340 c->changed_idler = NULL;
342 c->on_changed_cbs.walking++;
343 EINA_INLIST_FOREACH(c->on_changed_cbs.listeners, ctx) {
346 ctx->cb((void *)ctx->data, c);
348 c->on_changed_cbs.walking--;
350 _contacts_save(c->contacts);
352 if (c->on_changed_cbs.walking > 0)
355 EINA_LIST_FREE(c->on_changed_cbs.deleted, ctx) {
356 c->on_changed_cbs.listeners = eina_inlist_remove(
357 c->on_changed_cbs.listeners, EINA_INLIST_GET(ctx));
364 static void _contact_info_changed(Contact_Info *c)
366 if (c->changed_idler)
368 c->changed_idler = ecore_idler_add(_contact_info_changed_idler, c);
371 Eina_Bool contact_info_picture_set(Contact_Info *c, const char *filename)
373 EINA_SAFETY_ON_NULL_RETURN_VAL(c, EINA_FALSE);
374 EINA_SAFETY_ON_NULL_RETURN_VAL(filename, EINA_FALSE);
376 DBG("c=%p, was=%s, new=%s", c, c->picture, filename);
378 if (eina_stringshare_replace(&(c->picture), filename))
379 _contact_info_changed(c);
384 Eina_Bool contact_info_first_name_set(Contact_Info *c, const char *name)
386 EINA_SAFETY_ON_NULL_RETURN_VAL(c, EINA_FALSE);
387 EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE);
389 DBG("c=%p, was=%s, new=%s", c, c->first_name, name);
391 if (eina_stringshare_replace(&(c->first_name), name)) {
392 eina_stringshare_replace(&(c->full_name), NULL);
393 _contact_info_changed(c);
399 Eina_Bool contact_info_last_name_set(Contact_Info *c, const char *name)
401 EINA_SAFETY_ON_NULL_RETURN_VAL(c, EINA_FALSE);
402 EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE);
404 DBG("c=%p, was=%s, new=%s", c, c->last_name, name);
406 if (eina_stringshare_replace(&(c->last_name), name)) {
407 eina_stringshare_replace(&(c->full_name), NULL);
408 _contact_info_changed(c);
414 Eina_Bool contact_info_detail_set(Contact_Info *c, const char *type, const char *number)
416 Eina_Bool changed = EINA_FALSE;
418 EINA_SAFETY_ON_NULL_RETURN_VAL(c, EINA_FALSE);
419 EINA_SAFETY_ON_NULL_RETURN_VAL(type, EINA_FALSE);
420 EINA_SAFETY_ON_NULL_RETURN_VAL(number, EINA_FALSE);
422 DBG("c=%p, type=%s, number=%s", c, type, number);
424 if (strcmp(type, "Mobile") == 0)
425 changed = eina_stringshare_replace(&(c->mobile), number);
426 else if (strcmp(type, "Work") == 0)
427 changed = eina_stringshare_replace(&(c->work), number);
428 else if (strcmp(type, "Home") == 0)
429 changed = eina_stringshare_replace(&(c->home), number);
431 ERR("Unknown type: %s, number: %s", type, number);
436 _contact_info_changed(c);
442 void contact_info_on_changed_callback_add(Contact_Info *c,
443 void (*cb)(void *data, Contact_Info *c),
446 Contact_Info_On_Changed_Ctx *ctx;
448 EINA_SAFETY_ON_NULL_RETURN(c);
449 EINA_SAFETY_ON_NULL_RETURN(cb);
451 ctx = calloc(1, sizeof(Contact_Info_On_Changed_Ctx));
452 EINA_SAFETY_ON_NULL_RETURN(ctx);
456 c->on_changed_cbs.listeners = eina_inlist_append(
457 c->on_changed_cbs.listeners, EINA_INLIST_GET(ctx));
460 void contact_info_on_changed_callback_del(Contact_Info *c,
461 void (*cb)(void *data, Contact_Info *c),
464 Contact_Info_On_Changed_Ctx *ctx, *found = NULL;
465 EINA_SAFETY_ON_NULL_RETURN(c);
466 EINA_SAFETY_ON_NULL_RETURN(cb);
468 EINA_INLIST_FOREACH(c->on_changed_cbs.listeners, ctx) {
469 if (ctx->cb == cb && ctx->data == data) {
478 if (c->on_changed_cbs.walking > 0) {
479 found->deleted = EINA_TRUE;
480 c->on_changed_cbs.deleted = eina_list_append(
481 c->on_changed_cbs.deleted, found);
485 c->on_changed_cbs.listeners = eina_inlist_remove(
486 c->on_changed_cbs.listeners, EINA_INLIST_GET(found));
491 void contact_info_on_del_callback_add(Contact_Info *c,
492 void (*cb)(void *data, const Contact_Info *c),
495 Contact_Info_On_Del_Ctx *ctx;
497 EINA_SAFETY_ON_NULL_RETURN(c);
498 EINA_SAFETY_ON_NULL_RETURN(cb);
500 ctx = calloc(1, sizeof(Contact_Info_On_Del_Ctx));
501 EINA_SAFETY_ON_NULL_RETURN(ctx);
505 c->on_del_cbs = eina_inlist_append(c->on_del_cbs, EINA_INLIST_GET(ctx));
508 void contact_info_on_del_callback_del(Contact_Info *c,
509 void (*cb)(void *data, const Contact_Info *c),
512 Contact_Info_On_Del_Ctx *ctx, *found = NULL;
513 EINA_SAFETY_ON_NULL_RETURN(c);
514 EINA_SAFETY_ON_NULL_RETURN(cb);
516 EINA_INLIST_FOREACH(c->on_del_cbs, ctx) {
517 if (ctx->cb == cb && ctx->data == data) {
526 c->on_del_cbs = eina_inlist_remove(c->on_del_cbs,
527 EINA_INLIST_GET(found));
532 static void _contact_info_on_del_dispatch(Contact_Info *c)
534 Eina_Inlist *lst = c->on_del_cbs;
535 c->on_del_cbs = NULL; /* avoid contact_info_on_del_callback_del() */
537 Contact_Info_On_Del_Ctx *ctx = EINA_INLIST_CONTAINER_GET
538 (lst, Contact_Info_On_Del_Ctx);
540 lst = eina_inlist_remove(lst, lst);
542 ctx->cb((void *)ctx->data, c);
547 static void _contact_info_free(Contact_Info *c_info);
549 void contact_info_del(Contact_Info *c)
553 EINA_SAFETY_ON_NULL_RETURN(c);
555 _contact_info_on_del_dispatch(c);
558 elm_object_item_del(c->it);
560 contacts = c->contacts;
561 contacts->c_list->list = eina_list_remove(contacts->c_list->list, c);
562 contacts->c_list->dirty = EINA_TRUE;
563 _contacts_save(contacts);
565 _contact_info_free(c);
568 static void _contacts_info_descriptor_init(Eet_Data_Descriptor **edd,
569 Eet_Data_Descriptor **edd_list)
571 Eet_Data_Descriptor_Class eddc;
573 EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Contact_Info);
574 *edd = eet_data_descriptor_stream_new(&eddc);
576 EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Contacts_List);
577 *edd_list = eet_data_descriptor_stream_new(&eddc);
579 EET_DATA_DESCRIPTOR_ADD_BASIC(*edd, Contact_Info,
580 "picture", picture, EET_T_STRING);
581 EET_DATA_DESCRIPTOR_ADD_BASIC(*edd, Contact_Info,
582 "work", work, EET_T_STRING);
583 EET_DATA_DESCRIPTOR_ADD_BASIC(*edd, Contact_Info,
584 "home", home, EET_T_STRING);
585 EET_DATA_DESCRIPTOR_ADD_BASIC(*edd, Contact_Info,
586 "mobile", mobile, EET_T_STRING);
587 EET_DATA_DESCRIPTOR_ADD_BASIC(*edd, Contact_Info,
588 "first_name", first_name, EET_T_STRING);
589 EET_DATA_DESCRIPTOR_ADD_BASIC(*edd, Contact_Info,
590 "last_name", last_name, EET_T_STRING);
592 EET_DATA_DESCRIPTOR_ADD_LIST(*edd_list, Contacts_List, "list", list,
596 static void _contact_info_free(Contact_Info *c_info)
598 EINA_SAFETY_ON_FALSE_RETURN(c_info->on_changed_cbs.walking == 0);
600 if (c_info->on_changed_cbs.deleted) {
601 ERR("contact still have changed deleted listeners: %p %s %s",
602 c_info, c_info->first_name, c_info->last_name);
603 eina_list_free(c_info->on_changed_cbs.deleted);
606 if (c_info->on_changed_cbs.listeners) {
607 while (c_info->on_changed_cbs.listeners) {
608 Contact_Info_On_Changed_Ctx *ctx;
610 ctx = EINA_INLIST_CONTAINER_GET(
611 c_info->on_changed_cbs.listeners,
612 Contact_Info_On_Changed_Ctx);
613 c_info->on_changed_cbs.listeners = eina_inlist_remove
614 (c_info->on_changed_cbs.listeners,
615 c_info->on_changed_cbs.listeners);
620 if (c_info->changed_idler)
621 ecore_idler_del(c_info->changed_idler);
623 eina_stringshare_del(c_info->first_name);
624 eina_stringshare_del(c_info->last_name);
625 eina_stringshare_del(c_info->full_name);
626 eina_stringshare_del(c_info->mobile);
627 eina_stringshare_del(c_info->home);
628 eina_stringshare_del(c_info->work);
629 eina_stringshare_del(c_info->picture);
633 static void _on_del(void *data, Evas *e __UNUSED__,
634 Evas_Object *obj __UNUSED__, void *event __UNUSED__)
636 Contacts *contacts = data;
637 Contact_Info *c_info;
639 if (contacts->c_list->save_poller)
640 ecore_poller_del(contacts->c_list->save_poller);
641 if (contacts->c_list->dirty)
642 _contacts_save_do(contacts);
644 eet_data_descriptor_free(contacts->edd);
645 eet_data_descriptor_free(contacts->edd_list);
646 EINA_LIST_FREE(contacts->c_list->list, c_info) {
647 _contact_info_on_del_dispatch(c_info);
648 _contact_info_free(c_info);
650 free(contacts->c_list);
651 elm_genlist_item_class_free(contacts->itc);
652 elm_genlist_item_class_free(contacts->group);
653 free(contacts->path);
659 static void _on_number_clicked(void *data, Evas_Object *obj,
660 void *event_inf __UNUSED__)
662 const char *number = data;
663 Evas_Object *contacts = evas_object_data_get(obj, "contacts");
664 printf("contacts=%p, number=%p\n", contacts, number);
665 evas_object_smart_callback_call(contacts, "selected", (void *)number);
668 static void _on_item_click(void *data, Evas_Object *obj __UNUSED__,
671 Contacts *contacts = data;
672 Elm_Object_Item *item = event_inf;
673 Evas_Object *details, *btn, *photo;
674 Contact_Info *c_info;
677 details = contacts->details;
678 c_info = elm_object_item_data_get(item);
679 elm_genlist_item_selected_set(item, EINA_FALSE);
680 elm_layout_box_remove_all(details, "box.phones", EINA_TRUE);
682 elm_object_part_text_set(details, "text.name", c_info->first_name);
683 elm_object_part_text_set(details, "text.last.name", c_info->last_name);
685 photo = picture_icon_get(details, c_info->picture);
686 elm_object_part_content_set(details, "swallow.photo", photo);
688 btn = elm_button_add(details);
689 EINA_SAFETY_ON_NULL_RETURN(btn);
690 elm_object_style_set(btn, "contacts");
691 phone = phone_format(c_info->mobile);
692 elm_object_part_text_set(btn, "elm.text.type", _("Mobile"));
693 elm_object_part_text_set(btn, "elm.text.phone", phone);
695 evas_object_size_hint_weight_set(btn, EVAS_HINT_EXPAND,
697 evas_object_size_hint_align_set(btn, EVAS_HINT_FILL, EVAS_HINT_FILL);
698 evas_object_show(btn);
699 evas_object_data_set(btn, "contacts", contacts->layout);
700 evas_object_smart_callback_add(btn, "clicked", _on_number_clicked,
702 elm_layout_box_append(details, "box.phones", btn);
704 btn = elm_button_add(details);
705 EINA_SAFETY_ON_NULL_RETURN(btn);
706 elm_object_style_set(btn, "contacts");
707 phone = phone_format(c_info->home);
708 elm_object_part_text_set(btn, "elm.text.type", _("Home"));
709 elm_object_part_text_set(btn, "elm.text.phone", phone);
711 evas_object_size_hint_weight_set(btn, EVAS_HINT_EXPAND,
713 evas_object_size_hint_align_set(btn, EVAS_HINT_FILL, EVAS_HINT_FILL);
714 evas_object_show(btn);
715 evas_object_data_set(btn, "contacts", contacts->layout);
716 evas_object_smart_callback_add(btn, "clicked", _on_number_clicked,
718 elm_layout_box_append(details, "box.phones", btn);
720 btn = elm_button_add(details);
721 EINA_SAFETY_ON_NULL_RETURN(btn);
722 elm_object_style_set(btn, "contacts");
723 phone = phone_format(c_info->work);
724 elm_object_part_text_set(btn, "elm.text.type", _("Work"));
725 elm_object_part_text_set(btn, "elm.text.phone", phone);
727 evas_object_size_hint_weight_set(btn, EVAS_HINT_EXPAND,
729 evas_object_size_hint_align_set(btn, EVAS_HINT_FILL, EVAS_HINT_FILL);
730 evas_object_show(btn);
731 evas_object_data_set(btn, "contacts", contacts->layout);
732 evas_object_smart_callback_add(btn, "clicked", _on_number_clicked,
734 elm_layout_box_append(details, "box.phones", btn);
735 elm_object_signal_emit(contacts->layout, "show,details", "gui");
738 static int _sort_by_name_cb(const void *v1, const void *v2)
740 const Contact_Info *c1, *c2;
749 r = strcmp(c1->first_name, c2->first_name);
751 return strcmp(c1->last_name, c2->last_name);
756 static void _contacts_read(Contacts *contacts)
758 Contact_Info *c_info;
761 Elm_Object_Item *it = NULL;
763 efile = eet_open(contacts->path, EET_FILE_MODE_READ);
766 contacts->c_list = eet_data_read(efile, contacts->edd_list,
771 if (!contacts->c_list) {
772 efile = eet_open(contacts->bkp, EET_FILE_MODE_READ);
774 contacts->c_list = eet_data_read(
775 efile, contacts->edd_list, CONTACTS_ENTRY);
780 if (!contacts->c_list)
781 contacts->c_list = calloc(1, sizeof(Contacts_List));
783 EINA_SAFETY_ON_NULL_RETURN(contacts->c_list);
784 contacts->c_list->list = eina_list_sort(contacts->c_list->list, 0,
787 EINA_LIST_FOREACH(contacts->c_list->list, l, c_info) {
790 if (group != c_info->first_name[0]) {
791 group = c_info->first_name[0];
792 it = elm_genlist_item_append(contacts->genlist,
795 ELM_GENLIST_ITEM_GROUP,
798 elm_genlist_item_select_mode_set(it, ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY);
800 it = elm_genlist_item_append(contacts->genlist,contacts->itc,
802 ELM_GENLIST_ITEM_NONE,
803 _on_item_click, contacts);
805 c_info->contacts = contacts;
809 static char *_item_label_get(void *data, Evas_Object *obj __UNUSED__,
812 Contact_Info *c_info = data;
814 if (strncmp(part, "text.contacts.", strlen("text.contacts.")))
817 part += strlen("text.contacts.");
819 if (strcmp(part, "name") == 0)
820 return strdup(c_info->first_name);
821 else if (strcmp(part, "last") == 0)
822 return strdup(c_info->last_name);
823 else if (strcmp(part, "full") == 0)
824 return strdup(contact_info_full_name_get(c_info));
826 ERR("Unexpected part name: %s", part);
830 static char *_group_label_get(void *data, Evas_Object *obj __UNUSED__,
831 const char *part __UNUSED__)
833 Contact_Info *c_info = data;
835 snprintf(buf, sizeof(buf), "%c", c_info->first_name[0]);
840 static Evas_Object *_item_content_get(void *data,
844 Contact_Info *c_info = data;
847 if (strncmp(part, "swallow.", strlen("swallow.")))
850 part += strlen("swallow.");
852 if (strcmp(part, "photo") != 0) {
853 ERR("Unexpected part name: %s", part);
857 photo = picture_icon_get(obj, c_info->picture);
862 static void _on_back_clicked(void *data, Evas_Object *obj __UNUSED__,
863 const char *emission __UNUSED__,
864 const char *source __UNUSED__)
866 Evas_Object *layout = data;
867 elm_object_signal_emit(layout, "hide,details", "gui");
870 Evas_Object *contacts_add(Evas_Object *parent)
873 const char *config_path;
874 char base_dir[PATH_MAX], *path;
876 Evas_Object *obj, *genlist, *details;
877 Elm_Genlist_Item_Class *itc, *group;
880 contacts = calloc(1, sizeof(Contacts));
881 EINA_SAFETY_ON_NULL_RETURN_VAL(contacts, NULL);
884 details = layout_add(parent, "contacts_details");
885 EINA_SAFETY_ON_NULL_GOTO(details, err_layout);
886 elm_object_part_text_set(details, "label.back", _("Back"));
888 obj = layout_add(parent, "contacts_bg");
889 EINA_SAFETY_ON_NULL_GOTO(obj, err_obj);
891 genlist = elm_genlist_add(obj);
892 EINA_SAFETY_ON_NULL_GOTO(genlist, err_genlist);
893 elm_object_style_set(genlist, "contacts");
894 elm_genlist_homogeneous_set(genlist, EINA_TRUE);
896 itc = elm_genlist_item_class_new();
897 EINA_SAFETY_ON_NULL_GOTO(itc, err_genlist);
898 itc->item_style = "contacts";
899 itc->func.text_get = _item_label_get;
900 itc->func.content_get = _item_content_get;
901 itc->func.state_get = NULL;
902 itc->func.del = NULL;
904 group = elm_genlist_item_class_new();
905 EINA_SAFETY_ON_NULL_GOTO(group, err_group);
906 group->item_style = "group_contacts";
907 group->func.text_get = _group_label_get;
908 group->func.content_get = NULL;
909 group->func.state_get = NULL;
910 group->func.del = NULL;
911 contacts->group = group;
912 contacts->genlist = genlist;
914 contacts->layout = obj;
915 contacts->details = details;
917 elm_object_part_content_set(obj, "elm.swallow.genlist", genlist);
918 elm_object_part_content_set(obj, "elm.swallow.details", details);
920 elm_object_signal_callback_add(details, "clicked,back", "gui",
921 _on_back_clicked, obj);
923 config_path = efreet_config_home_get();
924 snprintf(base_dir, sizeof(base_dir), "%s/%s", config_path,
926 ecore_file_mkpath(base_dir);
928 r = asprintf(&path, "%s/%s/contacts.eet", config_path, PACKAGE_NAME);
932 contacts->path = path;
934 r = asprintf(&path, "%s/%s/contacts.eet.bkp", config_path,
939 contacts->bkp = path;
941 _contacts_info_descriptor_init(&contacts->edd, &contacts->edd_list);
942 _contacts_read(contacts);
943 EINA_SAFETY_ON_NULL_GOTO(contacts->c_list, err_read);
945 evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, _on_del,
948 evas_object_data_set(obj, "contacts.ctx", contacts);
952 eet_data_descriptor_free(contacts->edd);
953 eet_data_descriptor_free(contacts->edd_list);
956 free(contacts->path);
958 elm_genlist_item_class_free(group);
960 elm_genlist_item_class_free(itc);