4 #include <Elementary.h>
16 #ifndef EET_COMPRESSION_DEFAULT
17 #define EET_COMPRESSION_DEFAULT 1
20 #define HISTORY_ENTRY "history"
22 typedef struct _Call_Info_List {
27 typedef struct _History {
29 Eet_Data_Descriptor *edd;
30 Eet_Data_Descriptor *edd_list;
31 Call_Info_List *calls;
32 Elm_Genlist_Item_Class *itc;
34 Evas_Object *clear_popup;
35 Evas_Object *genlist_all, *genlist_missed;
36 Ecore_Poller *updater;
40 typedef struct _Call_Info {
43 long long creation_time; /* not in edd */
48 const OFono_Call *call; /* not in edd */
50 Elm_Object_Item *it_all; /*not in edd */
51 Elm_Object_Item *it_missed; /*not in edd */
52 const Contact_Info *contact; /* not in edd */
53 const char *contact_type; /* not in edd */
54 double contact_last; /* not in edd, last time it was searched */
55 #define CONTACT_LAST_THRESHOLD 1.0
58 static OFono_Callback_List_Call_Node *callback_node_call_removed = NULL;
59 static OFono_Callback_List_Call_Node *callback_node_call_changed = NULL;
61 static Eina_Bool _history_time_updater(void *data)
65 double now = ecore_loop_time_get();
66 const double interval_threshold = 30.0;
67 const long long update_threshold = time(NULL) - WEEK - DAY;
70 * NOTE ABOUT CONSTANTS:
72 * - interval_threshold: to avoid updating too often (window
73 * lost and gained focus, object hidden or shown), we limit
74 * updates to this minimum interval. The poller should run
77 * - update_threshold: since we format strings over a week as
78 * fixed string (often day-month-year, not relative to
79 * today), we can stop flagging list items as updated. We
80 * give it a day of slack so we can be sure to update every
81 * item (for held and conferences, you may have items that
82 * are close in time but slightly out of order as items are
83 * prepended as the calls are removed from ofono, then
84 * history is not strictly in 'time' order). We must
85 * stop iterating after update_threshold so users that never
86 * deleted history and have thousand items will not
87 * uselessly update all the thousand items.
90 if (!ctx->calls->list) {
95 if (now - ctx->last_update < interval_threshold)
97 ctx->last_update = now;
99 it = elm_genlist_first_item_get(ctx->genlist_all);
100 for (; it != NULL; it = elm_genlist_item_next_get(it)) {
101 const Call_Info *call_info = elm_object_item_data_get(it);
102 long long t = call_info->end_time;
103 if (EINA_UNLIKELY(t == 0)) {
104 t = call_info->start_time;
105 if (EINA_UNLIKELY(t == 0))
106 t = call_info->creation_time;
108 if (EINA_UNLIKELY(t < update_threshold))
110 elm_genlist_item_update(it);
113 it = elm_genlist_first_item_get(ctx->genlist_missed);
114 for (; it != NULL; it = elm_genlist_item_next_get(it)) {
115 const Call_Info *call_info = elm_object_item_data_get(it);
116 long long t = call_info->end_time;
117 if (EINA_UNLIKELY(t == 0)) {
118 t = call_info->start_time;
119 if (EINA_UNLIKELY(t == 0))
120 t = call_info->creation_time;
122 if (EINA_UNLIKELY(t < update_threshold))
124 elm_genlist_item_update(it);
130 static void _history_time_updater_stop(History *history)
132 Evas *e = evas_object_evas_get(history->self);
133 Eina_Bool win_focused = evas_focus_state_get(e);
134 Eina_Bool obj_visible = evas_object_visible_get(history->self);
136 DBG("poller %p, win_focused=%hhu, obj_visible=%hhu",
137 history->updater, win_focused, obj_visible);
138 if (!history->updater)
140 if (win_focused && obj_visible)
143 DBG("delete poller %p", history->updater);
144 ecore_poller_del(history->updater);
145 history->updater = NULL;
148 static void _history_time_updater_start(History *history)
150 Evas *e = evas_object_evas_get(history->self);
151 Eina_Bool win_focused = evas_focus_state_get(e);
152 Eina_Bool obj_visible = evas_object_visible_get(history->self);
154 DBG("poller %p, win_focused=%hhu, obj_visible=%hhu",
155 history->updater, win_focused, obj_visible);
156 if (history->updater)
158 if (!history->calls->list)
160 if ((!win_focused) || (!obj_visible))
164 /* ECORE_POLLER_CORE is 1/8th of second. */
165 history->updater = ecore_poller_add(ECORE_POLLER_CORE, 8 * 60,
166 _history_time_updater,
168 _history_time_updater(history);
171 static Call_Info *_history_call_info_search(const History *history,
172 const OFono_Call *call)
174 Call_Info *call_info;
176 long long t = ofono_call_full_start_time_get(call);
177 const char *line_id = ofono_call_line_id_get(call); /* stringshare */
179 EINA_LIST_FOREACH(history->calls->list, l, call_info) {
180 if (call_info->call == call)
182 else if (!call_info->call) {
183 if ((t > 0) && (call_info->start_time == t) &&
184 (line_id == call_info->line_id)) {
185 DBG("associated existing log %p %s (%lld) with "
189 call_info->start_time,
191 call_info->call = call;
200 static Eina_Bool _history_call_info_update(Call_Info *call_info)
202 OFono_Call_State state;
204 EINA_SAFETY_ON_NULL_RETURN_VAL(call_info->call, EINA_FALSE);
205 state = ofono_call_state_get(call_info->call);
207 if (state == OFONO_CALL_STATE_INCOMING ||
208 state == OFONO_CALL_STATE_WAITING) {
209 if (!call_info->incoming) {
210 call_info->incoming = EINA_TRUE;
213 } else if (state == OFONO_CALL_STATE_DIALING ||
214 state == OFONO_CALL_STATE_ALERTING) {
215 if (!call_info->incoming) {
216 call_info->incoming = EINA_FALSE;
219 } else if (state == OFONO_CALL_STATE_ACTIVE ||
220 state == OFONO_CALL_STATE_HELD) {
221 if (!call_info->completed) {
222 call_info->start_time = ofono_call_full_start_time_get
224 if (call_info->start_time == 0)
225 call_info->start_time = call_info->creation_time;
227 call_info->completed = EINA_TRUE;
235 static void _dial_reply(void *data, OFono_Error err,
236 OFono_Call *call __UNUSED__)
238 const char *number = data;
240 if (err != OFONO_ERROR_NONE) {
242 snprintf(buf, sizeof(buf), "Could not call: %s", number);
243 gui_simple_popup("Error", buf);
247 static void _on_item_clicked(void *data, Evas_Object *obj __UNUSED__,
250 Elm_Object_Item *it = event_info;
251 const char *number = data;
253 INF("call %s", number);
254 ofono_dial(number, NULL, _dial_reply, number);
255 elm_genlist_item_selected_set(it, EINA_FALSE);
258 static void _history_call_changed(void *data, OFono_Call *call)
260 History *history = data;
261 const char *line_id = ofono_call_line_id_get(call);
262 Call_Info *call_info;
263 OFono_Call_State state = ofono_call_state_get(call);
265 call_info = _history_call_info_search(history, call);
266 DBG("call=%p, id=%s, state=%d, completed=%d, incoming=%d, info=%p",
267 call, line_id, state,
268 call_info ? call_info->completed : EINA_FALSE,
269 call_info ? call_info->incoming : EINA_FALSE,
275 call_info = calloc(1, sizeof(Call_Info));
276 EINA_SAFETY_ON_NULL_RETURN(call_info);
278 call_info->call = call;
279 call_info->start_time = ofono_call_full_start_time_get(call);
280 call_info->creation_time = time(NULL);
281 if (call_info->start_time == 0)
282 call_info->start_time = call_info->creation_time;
283 call_info->line_id = eina_stringshare_add(line_id);
284 call_info->name = eina_stringshare_add(ofono_call_name_get(call));
285 history->calls->list =
286 eina_list_prepend(history->calls->list, call_info);
287 history->calls->dirty = EINA_TRUE;
290 if (_history_call_info_update(call_info))
291 history->calls->dirty = EINA_TRUE;
294 static void _history_call_log_save(History *history)
298 EINA_SAFETY_ON_NULL_RETURN(history->calls);
299 DBG("save history (%u calls, dirty: %d) to %s",
300 eina_list_count(history->calls->list), history->calls->dirty,
303 ecore_file_unlink(history->bkp);
304 ecore_file_mv(history->path, history->bkp);
305 efile = eet_open(history->path, EET_FILE_MODE_WRITE);
306 EINA_SAFETY_ON_NULL_RETURN(efile);
307 if (!(eet_data_write(efile,
308 history->edd_list, HISTORY_ENTRY,
309 history->calls, EET_COMPRESSION_DEFAULT)))
310 ERR("Could in the history log file");
315 static void _history_call_removed(void *data, OFono_Call *call)
318 History *history = data;
319 const char *line_id = ofono_call_line_id_get(call);
320 Call_Info *call_info;
324 call_info = _history_call_info_search(history, call);
325 DBG("call=%p, id=%s, info=%p", call, line_id, call_info);
326 EINA_SAFETY_ON_NULL_RETURN(call_info);
328 if (call_info->start_time == 0)
329 call_info->start_time = call_info->creation_time;
331 start = call_info->start_time;
334 call_info->end_time = time(NULL);
335 call_info->call = NULL;
337 if (call_info->completed)
338 INF("Call end: %s at %s", line_id, tm);
340 if (!call_info->incoming)
341 INF("Not answered: %s at %s", line_id, tm);
343 INF("Missed: %s at %s", line_id, tm);
344 if (call_info->it_missed)
345 elm_genlist_item_update(call_info->it_missed);
347 it = elm_genlist_item_prepend
348 (history->genlist_missed,
351 ELM_GENLIST_ITEM_NONE,
354 elm_genlist_item_show
355 (it, ELM_GENLIST_ITEM_SCROLLTO_IN);
356 call_info->it_missed = it;
357 call_info->history = history;
358 _history_time_updater_start(history);
363 history->calls->dirty = EINA_TRUE;
364 _history_call_log_save(history);
366 if (call_info->it_all)
367 elm_genlist_item_update(call_info->it_all);
369 it = elm_genlist_item_prepend(history->genlist_all,
372 ELM_GENLIST_ITEM_NONE,
375 elm_genlist_item_show(it, ELM_GENLIST_ITEM_SCROLLTO_IN);
376 call_info->it_all = it;
377 call_info->history = history;
378 _history_time_updater_start(history);
382 static void _on_contact_del(void *data, const Contact_Info *contact __UNUSED__)
384 Call_Info *call_info = data;
385 call_info->contact = NULL;
386 call_info->contact_type = NULL;
387 call_info->contact_last = 0.0;
390 static void _on_contact_changed(void *data, Contact_Info *contact)
392 Call_Info *call_info = data;
394 if (contact_info_number_check(contact, call_info->line_id))
397 contact_info_on_del_callback_del(contact, _on_contact_del, call_info);
398 contact_info_on_changed_callback_del(contact, _on_contact_changed,
401 call_info->contact = NULL;
402 call_info->contact_type = NULL;
403 call_info->contact_last = 0.0;
406 if (call_info->it_all)
407 elm_genlist_item_update(call_info->it_all);
408 if (call_info->it_missed)
409 elm_genlist_item_update(call_info->it_missed);
412 static void _call_info_free(Call_Info *call_info)
414 if (call_info->contact) {
415 Contact_Info *contact = (Contact_Info *)call_info->contact;
416 contact_info_on_del_callback_del(contact, _on_contact_del,
418 contact_info_on_changed_callback_del(contact,
423 eina_stringshare_del(call_info->line_id);
424 eina_stringshare_del(call_info->name);
428 static void _on_del(void *data, Evas *e __UNUSED__,
429 Evas_Object *obj __UNUSED__, void *event __UNUSED__)
431 History *history = data;
432 Call_Info *call_info;
434 if (history->updater)
435 ecore_poller_del(history->updater);
437 if (history->calls->dirty)
438 _history_call_log_save(history);
440 ofono_call_removed_cb_del(callback_node_call_removed);
441 ofono_call_changed_cb_del(callback_node_call_changed);
442 eet_data_descriptor_free(history->edd);
443 eet_data_descriptor_free(history->edd_list);
444 EINA_LIST_FREE(history->calls->list, call_info)
445 _call_info_free(call_info);
446 free(history->calls);
447 elm_genlist_item_class_free(history->itc);
451 ecore_file_shutdown();
455 static void _on_hide(void *data, Evas *e __UNUSED__,
456 Evas_Object *obj __UNUSED__, void *event __UNUSED__)
458 History *history = data;
459 DBG("history became hidden");
460 _history_time_updater_stop(history);
463 static void _on_show(void *data, Evas *e __UNUSED__,
464 Evas_Object *obj __UNUSED__, void *event __UNUSED__)
466 History *history = data;
467 DBG("history became visible");
468 _history_time_updater_start(history);
471 static void _on_win_focus_out(void *data, Evas *e __UNUSED__,
472 void *event_info __UNUSED__)
474 History *history = data;
475 DBG("window is unfocused");
476 _history_time_updater_stop(history);
479 static void _on_win_focus_in(void *data, Evas *e __UNUSED__,
480 void *event_info __UNUSED__)
482 History *history = data;
483 DBG("window is focused");
484 _history_time_updater_start(history);
487 static void _history_call_info_descriptor_init(Eet_Data_Descriptor **edd,
488 Eet_Data_Descriptor **edd_list)
490 Eet_Data_Descriptor_Class eddc;
492 EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Call_Info);
493 *edd = eet_data_descriptor_stream_new(&eddc);
495 EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Call_Info_List);
496 *edd_list = eet_data_descriptor_stream_new(&eddc);
498 EET_DATA_DESCRIPTOR_ADD_BASIC(*edd, Call_Info,
499 "completed", completed, EET_T_UCHAR);
500 EET_DATA_DESCRIPTOR_ADD_BASIC(*edd, Call_Info,
501 "incoming", incoming, EET_T_UCHAR);
503 EET_DATA_DESCRIPTOR_ADD_BASIC(*edd, Call_Info,
504 "start_time", start_time, EET_T_LONG_LONG);
505 EET_DATA_DESCRIPTOR_ADD_BASIC(*edd, Call_Info,
506 "end_time", end_time, EET_T_LONG_LONG);
507 EET_DATA_DESCRIPTOR_ADD_BASIC(*edd, Call_Info,
508 "line_id", line_id, EET_T_STRING);
509 EET_DATA_DESCRIPTOR_ADD_BASIC(*edd, Call_Info,
510 "name", name, EET_T_STRING);
512 EET_DATA_DESCRIPTOR_ADD_LIST(*edd_list, Call_Info_List, "list", list,
516 static void _history_call_log_read(History *history)
518 Call_Info *call_info;
521 Call_Info_List *calls = NULL;
524 efile = eet_open(history->path, EET_FILE_MODE_READ);
527 calls = eet_data_read(efile, history->edd_list, HISTORY_ENTRY);
532 efile = eet_open(history->bkp, EET_FILE_MODE_READ);
534 calls = eet_data_read(efile, history->edd_list,
541 calls = calloc(1, sizeof(Call_Info_List));
543 history->calls = calls;
544 EINA_SAFETY_ON_NULL_RETURN(history->calls);
546 EINA_LIST_FOREACH(history->calls->list, l, call_info) {
547 it = elm_genlist_item_append(history->genlist_all,
550 ELM_GENLIST_ITEM_NONE,
553 call_info->it_all = it;
554 call_info->history = history;
556 if (call_info->completed)
559 it = elm_genlist_item_append(history->genlist_missed,
560 history->itc, call_info, NULL,
561 ELM_GENLIST_ITEM_NONE,
564 call_info->it_missed = it;
565 call_info->history = history;
568 it = elm_genlist_first_item_get(history->genlist_all);
570 elm_genlist_item_show(it, ELM_GENLIST_ITEM_SCROLLTO_TOP);
572 it = elm_genlist_first_item_get(history->genlist_missed);
574 elm_genlist_item_show(it, ELM_GENLIST_ITEM_SCROLLTO_TOP);
577 static void _history_call_info_del(Call_Info *call_info)
579 History *ctx = call_info->history;
581 EINA_SAFETY_ON_NULL_RETURN(ctx);
583 call_info->call = NULL;
584 if (call_info->it_all)
585 elm_object_item_del(call_info->it_all);
586 if (call_info->it_missed)
587 elm_object_item_del(call_info->it_missed);
589 ctx->calls->list = eina_list_remove(ctx->calls->list, call_info);
590 ctx->calls->dirty = EINA_TRUE;
591 _history_call_log_save(ctx);
593 if ((!ctx->calls->list) && (ctx->updater)) {
594 ecore_poller_del(ctx->updater);
598 _call_info_free(call_info);
601 static void _history_clear_do(void *data, Evas_Object *obj __UNUSED__,
602 void *event_info __UNUSED__)
605 Call_Info *call_info;
607 DBG("ctx=%p, deleting %u entries",
608 ctx, eina_list_count(ctx->calls->list));
610 evas_object_del(ctx->clear_popup);
611 ctx->clear_popup = NULL;
613 elm_genlist_clear(ctx->genlist_all);
614 elm_genlist_clear(ctx->genlist_missed);
616 EINA_LIST_FREE(ctx->calls->list, call_info)
617 _call_info_free(call_info);
619 ctx->calls->dirty = EINA_TRUE;
620 _history_call_log_save(ctx);
623 ecore_poller_del(ctx->updater);
627 elm_object_signal_emit(ctx->self, "toggle,off,edit", "gui");
630 static void _history_clear_cancel(void *data, Evas_Object *obj __UNUSED__,
631 void *event_info __UNUSED__)
637 evas_object_del(ctx->clear_popup);
638 ctx->clear_popup = NULL;
641 static void _history_clear(History *ctx)
645 EINA_SAFETY_ON_TRUE_RETURN(ctx->clear_popup != NULL);
647 ctx->clear_popup = p = elm_popup_add(ctx->self);
648 evas_object_size_hint_weight_set(p, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
649 elm_object_part_text_set(p, "title,text", "Clear History");
650 elm_object_text_set(p, "Do you want to clear all history entries?");
652 bt = elm_button_add(p);
653 elm_object_text_set(bt, "No");
654 elm_object_part_content_set(p, "button1", bt);
655 evas_object_smart_callback_add(bt, "clicked",
656 _history_clear_cancel, ctx);
658 bt = elm_button_add(p);
659 elm_object_text_set(bt, "Yes, Clear");
660 elm_object_part_content_set(p, "button2", bt);
661 evas_object_smart_callback_add(bt, "clicked", _history_clear_do, ctx);
666 static char *_item_label_get(void *data, Evas_Object *obj __UNUSED__,
669 Call_Info *call_info = data;
671 if (strncmp(part, "text.call", strlen("text.call")))
674 part += strlen("text.call.");
676 if (!call_info->contact) {
677 double now = ecore_loop_time_get();
678 double diff = now - call_info->contact_last;
679 if (diff > CONTACT_LAST_THRESHOLD) {
680 Contact_Info *contact = gui_contact_search(
681 call_info->line_id, &(call_info->contact_type));
683 call_info->contact_last = now;
684 call_info->contact = contact;
686 contact_info_on_del_callback_add(
687 contact, _on_contact_del, call_info);
688 contact_info_on_changed_callback_add(
689 contact, _on_contact_changed,
695 if (!strcmp(part, "name")) {
696 if (!call_info->contact)
697 return strdup(call_info->line_id);
698 return strdup(contact_info_full_name_get(call_info->contact));
701 if (!strcmp(part, "time")) {
702 if ((call_info->completed) && (call_info->end_time))
703 return date_format(call_info->end_time);
704 return date_format(call_info->start_time);
707 if (!strcmp(part, "type")) {
708 if (!call_info->contact_type)
709 return strdup("Unknown");
710 return strdup(call_info->contact_type);
713 ERR("Unexpected text part: %s", part);
718 static Eina_Bool _item_state_get(void *data, Evas_Object *obj __UNUSED__,
721 Call_Info *call_info = data;
723 if (!strcmp(part, "missed"))
724 return !call_info->completed;
725 else if (!strcmp(part, "completed"))
726 return call_info->completed;
727 else if (!strcmp(part, "outgoing"))
728 return !call_info->incoming;
729 else if (!strcmp(part, "incoming"))
730 return call_info->incoming;
732 ERR("Unexpected state part: %s", part);
736 static void _on_clicked(void *data, Evas_Object *obj __UNUSED__,
737 const char *emission, const char *source __UNUSED__)
741 EINA_SAFETY_ON_NULL_RETURN(emission);
742 emission += strlen("clicked,");
744 DBG("ctx=%p, signal: %s", ctx, emission);
746 if (!strcmp(emission, "all"))
747 elm_object_signal_emit(obj, "show,all", "gui");
748 else if (!strcmp(emission, "missed"))
749 elm_object_signal_emit(obj, "show,missed", "gui");
750 else if (!strcmp(emission, "clear"))
752 else if (!strcmp(emission, "edit")) {
753 elm_object_signal_emit(obj, "toggle,on,edit", "gui");
754 elm_genlist_decorate_mode_set(ctx->genlist_all, EINA_TRUE);
755 elm_genlist_decorate_mode_set(ctx->genlist_missed, EINA_TRUE);
756 } else if (!strcmp(emission, "edit,done")) {
757 elm_object_signal_emit(obj, "toggle,off,edit", "gui");
758 elm_genlist_decorate_mode_set(ctx->genlist_all, EINA_FALSE);
759 elm_genlist_decorate_mode_set(ctx->genlist_missed, EINA_FALSE);
763 static void _on_more_clicked(void *data __UNUSED__, Evas_Object *obj __UNUSED__,
764 const char *emission __UNUSED__,
765 const char *source __UNUSED__)
770 static void _on_del_clicked(void *data, Evas_Object *obj __UNUSED__,
771 void *event_info __UNUSED__)
773 Call_Info *call_info = data;
774 DBG("call_info=%p, items all=%p missed=%p",
775 call_info, call_info->it_all, call_info->it_missed);
776 _history_call_info_del(call_info);
779 static Evas_Object *_item_content_get(void *data, Evas_Object *obj,
782 Evas_Object *btn = NULL;
784 if (strcmp(part, "call.swallow.more") == 0) {
785 btn = gui_layout_add(obj, "history/img");
786 EINA_SAFETY_ON_NULL_RETURN_VAL(btn, NULL);
787 elm_object_signal_callback_add(btn, "clicked,more", "gui",
788 _on_more_clicked, NULL);
789 evas_object_propagate_events_set(btn, EINA_FALSE);
790 } else if (strcmp(part, "call.swallow.delete") == 0) {
791 btn = elm_button_add(obj);
792 EINA_SAFETY_ON_NULL_RETURN_VAL(btn, NULL);
793 elm_object_style_set(btn, "history-delete");
794 elm_object_text_set(btn, "delete");
795 evas_object_smart_callback_add(btn, "clicked", _on_del_clicked,
797 evas_object_propagate_events_set(btn, EINA_FALSE);
799 ERR("unknown content part '%s'", part);
804 static void _on_list_slide_enter(void *data __UNUSED__,
808 Elm_Object_Item *it = elm_genlist_decorated_item_get(obj);
809 DBG("cancel decorated item=%p", it);
811 elm_genlist_item_decorate_mode_set(it, "slide", EINA_FALSE);
814 EINA_SAFETY_ON_NULL_RETURN(it);
816 elm_genlist_item_decorate_mode_set(it, "slide", EINA_TRUE);
819 static void _on_list_slide_cancel(void *data __UNUSED__,
821 void *event_info __UNUSED__)
823 Elm_Object_Item *it = elm_genlist_decorated_item_get(obj);
826 elm_genlist_item_decorate_mode_set(it, "slide", EINA_FALSE);
829 Evas_Object *history_add(Evas_Object *parent)
834 const char *config_path;
835 char *path, base_dir[PATH_MAX];
836 Elm_Genlist_Item_Class *itc;
837 Evas_Object *obj, *genlist_all, *genlist_missed;
841 history = calloc(1, sizeof(History));
842 EINA_SAFETY_ON_NULL_RETURN_VAL(history, NULL);
844 history->self = obj = gui_layout_add(parent, "history_bg");
845 EINA_SAFETY_ON_NULL_GOTO(obj, err_layout);
847 genlist_all = elm_genlist_add(obj);
848 EINA_SAFETY_ON_NULL_GOTO(genlist_all, err_object_new);
849 elm_object_style_set(genlist_all, "history");
852 evas_object_smart_callback_add(genlist_all, "drag,start,right",
853 _on_list_slide_enter, history);
854 evas_object_smart_callback_add(genlist_all, "drag,start,left",
855 _on_list_slide_cancel, history);
856 evas_object_smart_callback_add(genlist_all, "drag,start,down",
857 _on_list_slide_cancel, history);
858 evas_object_smart_callback_add(genlist_all, "drag,start,up",
859 _on_list_slide_cancel, history);
861 genlist_missed = elm_genlist_add(obj);
862 EINA_SAFETY_ON_NULL_GOTO(genlist_missed, err_object_new);
863 elm_object_style_set(genlist_missed, "history");
865 evas_object_smart_callback_add(genlist_missed, "drag,start,right",
866 _on_list_slide_enter, history);
867 evas_object_smart_callback_add(genlist_missed, "drag,start,left",
868 _on_list_slide_cancel, history);
869 evas_object_smart_callback_add(genlist_missed, "drag,start,down",
870 _on_list_slide_cancel, history);
871 evas_object_smart_callback_add(genlist_missed, "drag,start,up",
872 _on_list_slide_cancel, history);
874 itc = elm_genlist_item_class_new();
875 EINA_SAFETY_ON_NULL_GOTO(itc, err_object_new);
876 itc->item_style = "history";
877 itc->func.text_get = _item_label_get;
878 itc->func.content_get = _item_content_get;
879 itc->func.state_get = _item_state_get;
880 itc->func.del = NULL;
881 itc->decorate_all_item_style = "history-delete";
882 itc->decorate_item_style = "history-delete";
883 history->genlist_all = genlist_all;
884 history->genlist_missed = genlist_missed;
887 elm_object_part_content_set(obj, "elm.swallow.all", genlist_all);
888 elm_object_part_content_set(obj, "elm.swallow.missed", genlist_missed);
889 elm_object_signal_emit(obj, "show,all", "gui");
890 elm_object_signal_callback_add(obj, "clicked,*", "gui",
891 _on_clicked, history);
893 config_path = efreet_config_home_get();
894 snprintf(base_dir, sizeof(base_dir), "%s/%s", config_path,
896 ecore_file_mkpath(base_dir);
897 r = asprintf(&path, "%s/%s/history.eet", config_path, PACKAGE_NAME);
902 history->path = path;
903 r = asprintf(&path, "%s/%s/history.eet.bkp", config_path,
911 _history_call_info_descriptor_init(&history->edd, &history->edd_list);
912 _history_call_log_read(history);
913 EINA_SAFETY_ON_NULL_GOTO(history->calls, err_log_read);
914 evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, _on_del,
916 evas_object_event_callback_add(obj, EVAS_CALLBACK_HIDE, _on_hide,
918 evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _on_show,
921 e = evas_object_evas_get(obj);
922 evas_event_callback_add(e, EVAS_CALLBACK_CANVAS_FOCUS_OUT,
923 _on_win_focus_out, history);
924 evas_event_callback_add(e, EVAS_CALLBACK_CANVAS_FOCUS_IN,
925 _on_win_focus_in, history);
927 callback_node_call_changed =
928 ofono_call_changed_cb_add(_history_call_changed, history);
929 callback_node_call_removed =
930 ofono_call_removed_cb_add(_history_call_removed, history);
936 eet_data_descriptor_free(history->edd);
937 eet_data_descriptor_free(history->edd_list);
941 elm_genlist_item_class_free(itc);
946 ecore_file_shutdown();