4 #include <Elementary.h>
15 #include "simple-popup.h"
18 #ifndef EET_COMPRESSION_DEFAULT
19 #define EET_COMPRESSION_DEFAULT 1
22 #define HISTORY_ENTRY "history"
24 typedef struct _Call_Info_List {
29 typedef struct _History {
31 Eet_Data_Descriptor *edd;
32 Eet_Data_Descriptor *edd_list;
33 Call_Info_List *calls;
34 Elm_Genlist_Item_Class *itc;
36 Evas_Object *clear_popup;
37 Evas_Object *genlist_all, *genlist_missed;
38 Ecore_Poller *updater;
42 typedef struct _Call_Info {
45 long long creation_time; /* not in edd */
50 const OFono_Call *call; /* not in edd */
52 Elm_Object_Item *it_all; /*not in edd */
53 Elm_Object_Item *it_missed; /*not in edd */
54 const Contact_Info *contact; /* not in edd */
55 const char *contact_type; /* not in edd */
56 double contact_last; /* not in edd, last time it was searched */
57 #define CONTACT_LAST_THRESHOLD 1.0
60 static OFono_Callback_List_Call_Node *callback_node_call_removed = NULL;
61 static OFono_Callback_List_Call_Node *callback_node_call_changed = NULL;
63 static Eina_Bool _history_time_updater(void *data)
67 double now = ecore_loop_time_get();
68 const double interval_threshold = 30.0;
69 const long long update_threshold = time(NULL) - WEEK - DAY;
72 * NOTE ABOUT CONSTANTS:
74 * - interval_threshold: to avoid updating too often (window
75 * lost and gained focus, object hidden or shown), we limit
76 * updates to this minimum interval. The poller should run
79 * - update_threshold: since we format strings over a week as
80 * fixed string (often day-month-year, not relative to
81 * today), we can stop flagging list items as updated. We
82 * give it a day of slack so we can be sure to update every
83 * item (for held and conferences, you may have items that
84 * are close in time but slightly out of order as items are
85 * prepended as the calls are removed from ofono, then
86 * history is not strictly in 'time' order). We must
87 * stop iterating after update_threshold so users that never
88 * deleted history and have thousand items will not
89 * uselessly update all the thousand items.
92 if (!ctx->calls->list) {
97 if (now - ctx->last_update < interval_threshold)
99 ctx->last_update = now;
101 it = elm_genlist_first_item_get(ctx->genlist_all);
102 for (; it != NULL; it = elm_genlist_item_next_get(it)) {
103 const Call_Info *call_info = elm_object_item_data_get(it);
104 long long t = call_info->end_time;
105 if (EINA_UNLIKELY(t == 0)) {
106 t = call_info->start_time;
107 if (EINA_UNLIKELY(t == 0))
108 t = call_info->creation_time;
110 if (EINA_UNLIKELY(t < update_threshold))
112 elm_genlist_item_update(it);
115 it = elm_genlist_first_item_get(ctx->genlist_missed);
116 for (; it != NULL; it = elm_genlist_item_next_get(it)) {
117 const Call_Info *call_info = elm_object_item_data_get(it);
118 long long t = call_info->end_time;
119 if (EINA_UNLIKELY(t == 0)) {
120 t = call_info->start_time;
121 if (EINA_UNLIKELY(t == 0))
122 t = call_info->creation_time;
124 if (EINA_UNLIKELY(t < update_threshold))
126 elm_genlist_item_update(it);
132 static void _history_time_updater_stop(History *history)
134 Evas *e = evas_object_evas_get(history->self);
135 Eina_Bool win_focused = evas_focus_state_get(e);
136 Eina_Bool obj_visible = evas_object_visible_get(history->self);
138 DBG("poller %p, win_focused=%hhu, obj_visible=%hhu",
139 history->updater, win_focused, obj_visible);
140 if (!history->updater)
142 if (win_focused && obj_visible)
145 DBG("delete poller %p", history->updater);
146 ecore_poller_del(history->updater);
147 history->updater = NULL;
150 static void _history_time_updater_start(History *history)
152 Evas *e = evas_object_evas_get(history->self);
153 Eina_Bool win_focused = evas_focus_state_get(e);
154 Eina_Bool obj_visible = evas_object_visible_get(history->self);
156 DBG("poller %p, win_focused=%hhu, obj_visible=%hhu",
157 history->updater, win_focused, obj_visible);
158 if (history->updater)
160 if (!history->calls->list)
162 if ((!win_focused) || (!obj_visible))
166 /* ECORE_POLLER_CORE is 1/8th of second. */
167 history->updater = ecore_poller_add(ECORE_POLLER_CORE, 8 * 60,
168 _history_time_updater,
170 _history_time_updater(history);
173 static Call_Info *_history_call_info_search(const History *history,
174 const OFono_Call *call)
176 Call_Info *call_info;
178 long long t = ofono_call_full_start_time_get(call);
179 const char *line_id = ofono_call_line_id_get(call); /* stringshare */
181 EINA_LIST_FOREACH(history->calls->list, l, call_info) {
182 if (call_info->call == call)
184 else if (!call_info->call) {
185 if ((t > 0) && (call_info->start_time == t) &&
186 (line_id == call_info->line_id)) {
187 DBG("associated existing log %p %s (%lld) with "
191 call_info->start_time,
193 call_info->call = call;
202 static Eina_Bool _history_call_info_update(Call_Info *call_info)
204 OFono_Call_State state;
206 EINA_SAFETY_ON_NULL_RETURN_VAL(call_info->call, EINA_FALSE);
207 state = ofono_call_state_get(call_info->call);
209 if (state == OFONO_CALL_STATE_INCOMING ||
210 state == OFONO_CALL_STATE_WAITING) {
211 if (!call_info->incoming) {
212 call_info->incoming = EINA_TRUE;
215 } else if (state == OFONO_CALL_STATE_DIALING ||
216 state == OFONO_CALL_STATE_ALERTING) {
217 if (!call_info->incoming) {
218 call_info->incoming = EINA_FALSE;
221 } else if (state == OFONO_CALL_STATE_ACTIVE ||
222 state == OFONO_CALL_STATE_HELD) {
223 if (!call_info->completed) {
224 call_info->start_time = ofono_call_full_start_time_get
226 if (call_info->start_time == 0)
227 call_info->start_time = call_info->creation_time;
229 call_info->completed = EINA_TRUE;
237 static void _on_item_clicked(void *data, Evas_Object *obj __UNUSED__,
240 Elm_Object_Item *it = event_info;
241 const char *number = data;
243 INF("call %s", number);
245 elm_genlist_item_selected_set(it, EINA_FALSE);
248 static void _history_call_changed(void *data, OFono_Call *call)
250 History *history = data;
251 const char *line_id = ofono_call_line_id_get(call);
252 Call_Info *call_info;
253 OFono_Call_State state = ofono_call_state_get(call);
255 call_info = _history_call_info_search(history, call);
256 DBG("call=%p, id=%s, state=%d, completed=%d, incoming=%d, info=%p",
257 call, line_id, state,
258 call_info ? call_info->completed : EINA_FALSE,
259 call_info ? call_info->incoming : EINA_FALSE,
265 call_info = calloc(1, sizeof(Call_Info));
266 EINA_SAFETY_ON_NULL_RETURN(call_info);
268 call_info->call = call;
269 call_info->start_time = ofono_call_full_start_time_get(call);
270 call_info->creation_time = time(NULL);
271 if (call_info->start_time == 0)
272 call_info->start_time = call_info->creation_time;
273 call_info->line_id = eina_stringshare_add(line_id);
274 call_info->name = eina_stringshare_add(ofono_call_name_get(call));
275 history->calls->list =
276 eina_list_prepend(history->calls->list, call_info);
277 history->calls->dirty = EINA_TRUE;
280 if (_history_call_info_update(call_info))
281 history->calls->dirty = EINA_TRUE;
284 static void _history_call_log_save(History *history)
288 EINA_SAFETY_ON_NULL_RETURN(history->calls);
289 DBG("save history (%u calls, dirty: %d) to %s",
290 eina_list_count(history->calls->list), history->calls->dirty,
293 ecore_file_unlink(history->bkp);
294 ecore_file_mv(history->path, history->bkp);
295 efile = eet_open(history->path, EET_FILE_MODE_WRITE);
296 EINA_SAFETY_ON_NULL_RETURN(efile);
297 if (!(eet_data_write(efile,
298 history->edd_list, HISTORY_ENTRY,
299 history->calls, EET_COMPRESSION_DEFAULT)))
300 ERR("Could in the history log file");
305 static void _history_call_removed(void *data, OFono_Call *call)
308 History *history = data;
309 const char *line_id = ofono_call_line_id_get(call);
310 Call_Info *call_info;
314 call_info = _history_call_info_search(history, call);
315 DBG("call=%p, id=%s, info=%p", call, line_id, call_info);
316 EINA_SAFETY_ON_NULL_RETURN(call_info);
318 if (call_info->start_time == 0)
319 call_info->start_time = call_info->creation_time;
321 start = call_info->start_time;
324 call_info->end_time = time(NULL);
325 call_info->call = NULL;
327 if (call_info->completed)
328 INF("Call end: %s at %s", line_id, tm);
330 if (!call_info->incoming)
331 INF("Not answered: %s at %s", line_id, tm);
333 INF("Missed: %s at %s", line_id, tm);
334 if (call_info->it_missed)
335 elm_genlist_item_update(call_info->it_missed);
337 it = elm_genlist_item_prepend
338 (history->genlist_missed,
341 ELM_GENLIST_ITEM_NONE,
344 elm_genlist_item_show
345 (it, ELM_GENLIST_ITEM_SCROLLTO_IN);
346 call_info->it_missed = it;
347 call_info->history = history;
348 _history_time_updater_start(history);
353 history->calls->dirty = EINA_TRUE;
354 _history_call_log_save(history);
356 if (call_info->it_all)
357 elm_genlist_item_update(call_info->it_all);
359 it = elm_genlist_item_prepend(history->genlist_all,
362 ELM_GENLIST_ITEM_NONE,
365 elm_genlist_item_show(it, ELM_GENLIST_ITEM_SCROLLTO_IN);
366 call_info->it_all = it;
367 call_info->history = history;
368 _history_time_updater_start(history);
372 static void _on_contact_del(void *data, const Contact_Info *contact __UNUSED__)
374 Call_Info *call_info = data;
375 call_info->contact = NULL;
376 call_info->contact_type = NULL;
377 call_info->contact_last = 0.0;
380 static void _on_contact_changed(void *data, Contact_Info *contact)
382 Call_Info *call_info = data;
384 if (contact_info_number_check(contact, call_info->line_id))
387 contact_info_on_del_callback_del(contact, _on_contact_del, call_info);
388 contact_info_on_changed_callback_del(contact, _on_contact_changed,
391 call_info->contact = NULL;
392 call_info->contact_type = NULL;
393 call_info->contact_last = 0.0;
396 if (call_info->it_all)
397 elm_genlist_item_update(call_info->it_all);
398 if (call_info->it_missed)
399 elm_genlist_item_update(call_info->it_missed);
402 static void _call_info_free(Call_Info *call_info)
404 if (call_info->contact) {
405 Contact_Info *contact = (Contact_Info *)call_info->contact;
406 contact_info_on_del_callback_del(contact, _on_contact_del,
408 contact_info_on_changed_callback_del(contact,
413 eina_stringshare_del(call_info->line_id);
414 eina_stringshare_del(call_info->name);
418 static void _on_del(void *data, Evas *e __UNUSED__,
419 Evas_Object *obj __UNUSED__, void *event __UNUSED__)
421 History *history = data;
422 Call_Info *call_info;
424 if (history->updater)
425 ecore_poller_del(history->updater);
427 if (history->calls->dirty)
428 _history_call_log_save(history);
430 ofono_call_removed_cb_del(callback_node_call_removed);
431 ofono_call_changed_cb_del(callback_node_call_changed);
432 eet_data_descriptor_free(history->edd);
433 eet_data_descriptor_free(history->edd_list);
434 EINA_LIST_FREE(history->calls->list, call_info)
435 _call_info_free(call_info);
436 free(history->calls);
437 elm_genlist_item_class_free(history->itc);
441 ecore_file_shutdown();
445 static void _on_hide(void *data, Evas *e __UNUSED__,
446 Evas_Object *obj __UNUSED__, void *event __UNUSED__)
448 History *history = data;
449 DBG("history became hidden");
450 _history_time_updater_stop(history);
453 static void _on_show(void *data, Evas *e __UNUSED__,
454 Evas_Object *obj __UNUSED__, void *event __UNUSED__)
456 History *history = data;
457 DBG("history became visible");
458 _history_time_updater_start(history);
461 static void _on_win_focus_out(void *data, Evas *e __UNUSED__,
462 void *event_info __UNUSED__)
464 History *history = data;
465 DBG("window is unfocused");
466 _history_time_updater_stop(history);
469 static void _on_win_focus_in(void *data, Evas *e __UNUSED__,
470 void *event_info __UNUSED__)
472 History *history = data;
473 DBG("window is focused");
474 _history_time_updater_start(history);
477 static void _history_call_info_descriptor_init(Eet_Data_Descriptor **edd,
478 Eet_Data_Descriptor **edd_list)
480 Eet_Data_Descriptor_Class eddc;
482 EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Call_Info);
483 *edd = eet_data_descriptor_stream_new(&eddc);
485 EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Call_Info_List);
486 *edd_list = eet_data_descriptor_stream_new(&eddc);
488 EET_DATA_DESCRIPTOR_ADD_BASIC(*edd, Call_Info,
489 "completed", completed, EET_T_UCHAR);
490 EET_DATA_DESCRIPTOR_ADD_BASIC(*edd, Call_Info,
491 "incoming", incoming, EET_T_UCHAR);
493 EET_DATA_DESCRIPTOR_ADD_BASIC(*edd, Call_Info,
494 "start_time", start_time, EET_T_LONG_LONG);
495 EET_DATA_DESCRIPTOR_ADD_BASIC(*edd, Call_Info,
496 "end_time", end_time, EET_T_LONG_LONG);
497 EET_DATA_DESCRIPTOR_ADD_BASIC(*edd, Call_Info,
498 "line_id", line_id, EET_T_STRING);
499 EET_DATA_DESCRIPTOR_ADD_BASIC(*edd, Call_Info,
500 "name", name, EET_T_STRING);
502 EET_DATA_DESCRIPTOR_ADD_LIST(*edd_list, Call_Info_List, "list", list,
506 static void _history_call_log_read(History *history)
508 Call_Info *call_info;
511 Call_Info_List *calls = NULL;
514 efile = eet_open(history->path, EET_FILE_MODE_READ);
517 calls = eet_data_read(efile, history->edd_list, HISTORY_ENTRY);
522 efile = eet_open(history->bkp, EET_FILE_MODE_READ);
524 calls = eet_data_read(efile, history->edd_list,
531 calls = calloc(1, sizeof(Call_Info_List));
533 history->calls = calls;
534 EINA_SAFETY_ON_NULL_RETURN(history->calls);
536 EINA_LIST_FOREACH(history->calls->list, l, call_info) {
537 it = elm_genlist_item_append(history->genlist_all,
540 ELM_GENLIST_ITEM_NONE,
543 call_info->it_all = it;
544 call_info->history = history;
546 if (call_info->completed)
549 it = elm_genlist_item_append(history->genlist_missed,
550 history->itc, call_info, NULL,
551 ELM_GENLIST_ITEM_NONE,
554 call_info->it_missed = it;
555 call_info->history = history;
558 it = elm_genlist_first_item_get(history->genlist_all);
560 elm_genlist_item_show(it, ELM_GENLIST_ITEM_SCROLLTO_TOP);
562 it = elm_genlist_first_item_get(history->genlist_missed);
564 elm_genlist_item_show(it, ELM_GENLIST_ITEM_SCROLLTO_TOP);
567 static void _history_call_info_del(Call_Info *call_info)
569 History *ctx = call_info->history;
571 EINA_SAFETY_ON_NULL_RETURN(ctx);
573 call_info->call = NULL;
574 if (call_info->it_all)
575 elm_object_item_del(call_info->it_all);
576 if (call_info->it_missed)
577 elm_object_item_del(call_info->it_missed);
579 ctx->calls->list = eina_list_remove(ctx->calls->list, call_info);
580 ctx->calls->dirty = EINA_TRUE;
581 _history_call_log_save(ctx);
583 if ((!ctx->calls->list) && (ctx->updater)) {
584 ecore_poller_del(ctx->updater);
588 _call_info_free(call_info);
591 static void _history_clear_do(void *data, Evas_Object *obj __UNUSED__,
592 void *event_info __UNUSED__)
595 Call_Info *call_info;
597 DBG("ctx=%p, deleting %u entries",
598 ctx, eina_list_count(ctx->calls->list));
600 evas_object_del(ctx->clear_popup);
601 ctx->clear_popup = NULL;
603 elm_genlist_clear(ctx->genlist_all);
604 elm_genlist_clear(ctx->genlist_missed);
606 EINA_LIST_FREE(ctx->calls->list, call_info)
607 _call_info_free(call_info);
609 ctx->calls->dirty = EINA_TRUE;
610 _history_call_log_save(ctx);
613 ecore_poller_del(ctx->updater);
617 elm_object_signal_emit(ctx->self, "toggle,off,edit", "gui");
620 static void _history_clear_cancel(void *data, Evas_Object *obj __UNUSED__,
621 void *event_info __UNUSED__)
627 evas_object_del(ctx->clear_popup);
628 ctx->clear_popup = NULL;
631 static void _history_clear(History *ctx)
635 EINA_SAFETY_ON_TRUE_RETURN(ctx->clear_popup != NULL);
637 ctx->clear_popup = p = gui_simple_popup(_("Clear History"),
638 _("Do you want to clear all history entries?"));
640 simple_popup_buttons_set(p,
643 _history_clear_cancel,
650 static char *_item_label_get(void *data, Evas_Object *obj __UNUSED__,
653 Call_Info *call_info = data;
655 if (strncmp(part, "text.call", strlen("text.call")))
658 part += strlen("text.call.");
660 if (!call_info->contact) {
661 double now = ecore_loop_time_get();
662 double diff = now - call_info->contact_last;
663 if (diff > CONTACT_LAST_THRESHOLD) {
664 Contact_Info *contact = gui_contact_search(
665 call_info->line_id, &(call_info->contact_type));
667 call_info->contact_last = now;
668 call_info->contact = contact;
670 contact_info_on_del_callback_add(
671 contact, _on_contact_del, call_info);
672 contact_info_on_changed_callback_add(
673 contact, _on_contact_changed,
679 if (!strcmp(part, "name")) {
680 if (!call_info->contact)
681 return strdup(call_info->line_id);
682 return strdup(contact_info_full_name_get(call_info->contact));
685 if (!strcmp(part, "time")) {
686 if ((call_info->completed) && (call_info->end_time))
687 return date_format(call_info->end_time);
688 return date_format(call_info->start_time);
691 if (!strcmp(part, "type")) {
692 if (!call_info->contact_type)
693 return strdup(_("Unknown"));
694 return strdup(call_info->contact_type);
697 ERR("Unexpected text part: %s", part);
702 static Eina_Bool _item_state_get(void *data, Evas_Object *obj __UNUSED__,
705 Call_Info *call_info = data;
707 if (!strcmp(part, "missed"))
708 return !call_info->completed;
709 else if (!strcmp(part, "completed"))
710 return call_info->completed;
711 else if (!strcmp(part, "outgoing"))
712 return !call_info->incoming;
713 else if (!strcmp(part, "incoming"))
714 return call_info->incoming;
716 ERR("Unexpected state part: %s", part);
720 static void _on_clicked(void *data, Evas_Object *obj __UNUSED__,
721 const char *emission, const char *source __UNUSED__)
724 Last_User_Mode *last;
726 EINA_SAFETY_ON_NULL_RETURN(emission);
727 emission += strlen("clicked,");
729 DBG("ctx=%p, signal: %s", ctx, emission);
730 last = util_get_last_user_mode();
732 if (!strcmp(emission, "all")) {
733 elm_object_signal_emit(obj, "show,all", "gui");
735 last->last_history_view = DIALER_LAST_HISTORY_VIEW_ALL;
736 util_set_last_user_mode(last);
739 else if (!strcmp(emission, "missed")) {
740 elm_object_signal_emit(obj, "show,missed", "gui");
742 last->last_history_view = DIALER_LAST_HISTORY_VIEW_MISSED;
743 util_set_last_user_mode(last);
746 else if (!strcmp(emission, "clear"))
748 else if (!strcmp(emission, "edit")) {
749 elm_object_signal_emit(obj, "toggle,on,edit", "gui");
750 elm_genlist_decorate_mode_set(ctx->genlist_all, EINA_TRUE);
751 elm_genlist_decorate_mode_set(ctx->genlist_missed, EINA_TRUE);
752 } else if (!strcmp(emission, "edit,done")) {
753 elm_object_signal_emit(obj, "toggle,off,edit", "gui");
754 elm_genlist_decorate_mode_set(ctx->genlist_all, EINA_FALSE);
755 elm_genlist_decorate_mode_set(ctx->genlist_missed, EINA_FALSE);
759 static void _on_more_clicked(void *data __UNUSED__, Evas_Object *obj __UNUSED__,
760 const char *emission __UNUSED__,
761 const char *source __UNUSED__)
766 static void _on_del_clicked(void *data, Evas_Object *obj __UNUSED__,
767 void *event_info __UNUSED__)
769 Call_Info *call_info = data;
770 DBG("call_info=%p, items all=%p missed=%p",
771 call_info, call_info->it_all, call_info->it_missed);
772 _history_call_info_del(call_info);
775 static Evas_Object *_item_content_get(void *data, Evas_Object *obj,
778 Evas_Object *btn = NULL;
780 if (strcmp(part, "call.swallow.more") == 0) {
781 btn = layout_add(obj, "history/img");
782 EINA_SAFETY_ON_NULL_RETURN_VAL(btn, NULL);
783 elm_object_signal_callback_add(btn, "clicked,more", "gui",
784 _on_more_clicked, NULL);
785 evas_object_propagate_events_set(btn, EINA_FALSE);
786 } else if (strcmp(part, "call.swallow.delete") == 0) {
787 btn = elm_button_add(obj);
788 EINA_SAFETY_ON_NULL_RETURN_VAL(btn, NULL);
789 elm_object_style_set(btn, "history-delete");
790 elm_object_text_set(btn, "delete");
791 evas_object_smart_callback_add(btn, "clicked", _on_del_clicked,
793 evas_object_propagate_events_set(btn, EINA_FALSE);
795 ERR("unknown content part '%s'", part);
800 static void _on_list_slide_enter(void *data __UNUSED__,
804 Elm_Object_Item *it = elm_genlist_decorated_item_get(obj);
805 DBG("cancel decorated item=%p", it);
807 elm_genlist_item_decorate_mode_set(it, "slide", EINA_FALSE);
810 EINA_SAFETY_ON_NULL_RETURN(it);
812 elm_genlist_item_decorate_mode_set(it, "slide", EINA_TRUE);
815 static void _on_list_slide_cancel(void *data __UNUSED__,
817 void *event_info __UNUSED__)
819 Elm_Object_Item *it = elm_genlist_decorated_item_get(obj);
822 elm_genlist_item_decorate_mode_set(it, "slide", EINA_FALSE);
825 Evas_Object *history_add(Evas_Object *parent)
830 const char *config_path;
831 char *path, base_dir[PATH_MAX];
832 Elm_Genlist_Item_Class *itc;
833 Evas_Object *obj, *genlist_all, *genlist_missed;
837 history = calloc(1, sizeof(History));
838 EINA_SAFETY_ON_NULL_RETURN_VAL(history, NULL);
840 history->self = obj = layout_add(parent, "history_bg");
841 EINA_SAFETY_ON_NULL_GOTO(obj, err_layout);
843 genlist_all = elm_genlist_add(obj);
844 EINA_SAFETY_ON_NULL_GOTO(genlist_all, err_object_new);
845 elm_object_style_set(genlist_all, "history");
846 elm_genlist_homogeneous_set(genlist_all, EINA_TRUE);
848 evas_object_smart_callback_add(genlist_all, "drag,start,right",
849 _on_list_slide_enter, history);
850 evas_object_smart_callback_add(genlist_all, "drag,start,left",
851 _on_list_slide_cancel, history);
852 evas_object_smart_callback_add(genlist_all, "drag,start,down",
853 _on_list_slide_cancel, history);
854 evas_object_smart_callback_add(genlist_all, "drag,start,up",
855 _on_list_slide_cancel, history);
857 genlist_missed = elm_genlist_add(obj);
858 EINA_SAFETY_ON_NULL_GOTO(genlist_missed, err_object_new);
859 elm_object_style_set(genlist_missed, "history");
860 elm_genlist_homogeneous_set(genlist_missed, EINA_TRUE);
862 evas_object_smart_callback_add(genlist_missed, "drag,start,right",
863 _on_list_slide_enter, history);
864 evas_object_smart_callback_add(genlist_missed, "drag,start,left",
865 _on_list_slide_cancel, history);
866 evas_object_smart_callback_add(genlist_missed, "drag,start,down",
867 _on_list_slide_cancel, history);
868 evas_object_smart_callback_add(genlist_missed, "drag,start,up",
869 _on_list_slide_cancel, history);
871 itc = elm_genlist_item_class_new();
872 EINA_SAFETY_ON_NULL_GOTO(itc, err_object_new);
873 itc->item_style = "history";
874 itc->func.text_get = _item_label_get;
875 itc->func.content_get = _item_content_get;
876 itc->func.state_get = _item_state_get;
877 itc->func.del = NULL;
878 itc->decorate_all_item_style = "history-delete";
879 itc->decorate_item_style = "history-delete";
880 history->genlist_all = genlist_all;
881 history->genlist_missed = genlist_missed;
884 elm_object_part_content_set(obj, "elm.swallow.all", genlist_all);
885 elm_object_part_content_set(obj, "elm.swallow.missed", genlist_missed);
886 elm_object_signal_emit(obj, "show,all", "gui");
887 elm_object_signal_callback_add(obj, "clicked,*", "gui",
888 _on_clicked, history);
890 config_path = efreet_config_home_get();
891 snprintf(base_dir, sizeof(base_dir), "%s/%s", config_path,
893 ecore_file_mkpath(base_dir);
894 r = asprintf(&path, "%s/%s/history.eet", config_path, PACKAGE_NAME);
899 history->path = path;
900 r = asprintf(&path, "%s/%s/history.eet.bkp", config_path,
908 _history_call_info_descriptor_init(&history->edd, &history->edd_list);
909 _history_call_log_read(history);
910 EINA_SAFETY_ON_NULL_GOTO(history->calls, err_log_read);
911 evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, _on_del,
913 evas_object_event_callback_add(obj, EVAS_CALLBACK_HIDE, _on_hide,
915 evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _on_show,
918 e = evas_object_evas_get(obj);
919 evas_event_callback_add(e, EVAS_CALLBACK_CANVAS_FOCUS_OUT,
920 _on_win_focus_out, history);
921 evas_event_callback_add(e, EVAS_CALLBACK_CANVAS_FOCUS_IN,
922 _on_win_focus_in, history);
924 callback_node_call_changed =
925 ofono_call_changed_cb_add(_history_call_changed, history);
926 callback_node_call_removed =
927 ofono_call_removed_cb_add(_history_call_removed, history);
933 eet_data_descriptor_free(history->edd);
934 eet_data_descriptor_free(history->edd_list);
938 elm_genlist_item_class_free(itc);
943 ecore_file_shutdown();