4 #include <Elementary.h>
16 #define HISTORY_ENTRY "history"
18 typedef struct _Call_Info_List {
22 typedef struct _History {
24 Eet_Data_Descriptor *edd;
25 Eet_Data_Descriptor *edd_list;
26 Call_Info_List *calls;
27 Elm_Genlist_Item_Class *itc;
28 Evas_Object *genlist_all, *genlist_missed;
31 typedef struct _Call_Info {
39 static OFono_Callback_List_Call_Node *callback_node_call_removed = NULL;
40 static OFono_Callback_List_Call_Node *callback_node_call_changed = NULL;
42 static Call_Info *_history_call_info_list_search(Eina_List *list,
48 EINA_LIST_FOREACH(list, l, call_info)
49 if (!strcmp(call_info->line_id, line_id))
55 static void _history_call_changed(void *data, OFono_Call *call)
57 History *history = data;
58 const char *line_id = ofono_call_line_id_get(call);
60 OFono_Call_State state = ofono_call_state_get(call);
63 _history_call_info_list_search(history->calls->list, line_id);
66 /* Otherwise I missed the call or the person didn't
69 if ((call_info->state == OFONO_CALL_STATE_INCOMING ||
70 call_info->state == OFONO_CALL_STATE_DIALING) &&
71 state != OFONO_CALL_STATE_DISCONNECTED)
72 call_info->state = state;
75 call_info = calloc(1, sizeof(Call_Info));
76 EINA_SAFETY_ON_NULL_RETURN(call_info);
78 call_info->state = state;
79 call_info->start_time = time(NULL);
80 call_info->line_id = eina_stringshare_add(line_id);
81 call_info->name = eina_stringshare_add(ofono_call_name_get(call));
82 history->calls->list =
83 eina_list_prepend(history->calls->list, call_info);
86 static void _history_call_log_save(History *history)
90 ecore_file_unlink(history->bkp);
91 ecore_file_mv(history->path, history->bkp);
92 efile = eet_open(history->path, EET_FILE_MODE_WRITE);
93 EINA_SAFETY_ON_NULL_RETURN(efile);
94 if (!(eet_data_write(efile,
95 history->edd_list, HISTORY_ENTRY,
96 history->calls, EET_COMPRESSION_DEFAULT)))
97 ERR("Could in the history log file");
102 static void _history_call_removed(void *data, OFono_Call *call)
104 History *history = data;
105 const char *line_id = ofono_call_line_id_get(call);
106 Call_Info *call_info;
111 _history_call_info_list_search(history->calls->list, line_id);
112 EINA_SAFETY_ON_NULL_RETURN(call_info);
113 start = call_info->start_time;
116 if (call_info->state == OFONO_CALL_STATE_INCOMING) {
117 INF("Missed call - Id: %s - time: %s", line_id, tm);
118 elm_genlist_item_append(history->genlist_missed, history->itc,
119 call_info, NULL, ELM_GENLIST_ITEM_NONE,
121 } else if (call_info->state == OFONO_CALL_STATE_DIALING)
122 INF("Call not answered - Id: %s - time: %s", line_id, tm);
124 INF("A call has ended - Id: %s - time: %s", line_id, tm);
126 call_info->end_time = time(NULL);
127 _history_call_log_save(history);
128 elm_genlist_item_append(history->genlist_all, history->itc, call_info,
129 NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL);
132 static void _call_info_free(Call_Info *call_info)
134 eina_stringshare_del(call_info->line_id);
135 eina_stringshare_del(call_info->name);
139 static void _on_del(void *data, Evas *e __UNUSED__,
140 Evas_Object *obj __UNUSED__, void *event __UNUSED__)
142 History *history = data;
143 Call_Info *call_info;
144 ofono_call_removed_cb_del(callback_node_call_removed);
145 ofono_call_changed_cb_del(callback_node_call_changed);
146 eet_data_descriptor_free(history->edd);
147 eet_data_descriptor_free(history->edd_list);
148 EINA_LIST_FREE(history->calls->list, call_info)
149 _call_info_free(call_info);
150 free(history->calls);
151 elm_genlist_item_class_free(history->itc);
155 ecore_file_shutdown();
159 static void _history_call_info_descriptor_init(Eet_Data_Descriptor **edd,
160 Eet_Data_Descriptor **edd_list)
162 Eet_Data_Descriptor_Class eddc;
164 EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Call_Info);
165 *edd = eet_data_descriptor_stream_new(&eddc);
167 EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Call_Info_List);
168 *edd_list = eet_data_descriptor_stream_new(&eddc);
170 EET_DATA_DESCRIPTOR_ADD_BASIC(*edd, Call_Info,
171 "state", state, EET_T_INT);
172 EET_DATA_DESCRIPTOR_ADD_BASIC(*edd, Call_Info,
173 "start_time", start_time, EET_T_LONG_LONG);
174 EET_DATA_DESCRIPTOR_ADD_BASIC(*edd, Call_Info,
175 "end_time", end_time, EET_T_LONG_LONG);
176 EET_DATA_DESCRIPTOR_ADD_BASIC(*edd, Call_Info,
177 "line_id", line_id, EET_T_STRING);
178 EET_DATA_DESCRIPTOR_ADD_BASIC(*edd, Call_Info,
179 "name", name, EET_T_STRING);
181 EET_DATA_DESCRIPTOR_ADD_LIST(*edd_list, Call_Info_List, "list", list,
185 static void _history_call_log_read(History *history)
187 Call_Info *call_info;
190 Call_Info_List *calls = NULL;
192 efile = eet_open(history->path, EET_FILE_MODE_READ);
195 calls = eet_data_read(efile, history->edd_list, HISTORY_ENTRY);
200 efile = eet_open(history->bkp, EET_FILE_MODE_READ);
202 calls = eet_data_read(efile, history->edd_list,
209 history->calls = calloc(1, sizeof(Call_Info_List));
211 history->calls = calls;
212 EINA_SAFETY_ON_NULL_RETURN(history->calls);
214 EINA_LIST_FOREACH(history->calls->list, l, call_info) {
217 elm_genlist_item_append(history->genlist_all, history->itc,
218 call_info, NULL, ELM_GENLIST_ITEM_NONE,
220 if (call_info->state == OFONO_CALL_STATE_INCOMING)
221 elm_genlist_item_append(history->genlist_missed,
222 history->itc, call_info, NULL,
223 ELM_GENLIST_ITEM_NONE,
228 static char *_item_label_get(void *data, Evas_Object *obj __UNUSED__,
231 Call_Info *call_info = data;
233 if (strncmp(part, "text.call", strlen("text.call")))
236 part += strlen("text.call.");
238 if (!strcmp(part, "name")) {
240 name = call_info->name;
241 if (!call_info->name || call_info->name[0] == '\0')
242 name = call_info->line_id;
246 if (!strcmp(part, "time"))
247 return date_format(call_info->end_time);
249 /* TODO: Fetch phone type from contacts information*/
250 if (!strcmp(part, "type"))
251 return strdup("TODO:TELEPHONE TYPE");
253 ERR("Unexpected text part: %s", part);
258 static Eina_Bool _item_state_get(void *data, Evas_Object *obj __UNUSED__,
261 Call_Info *call_info = data;
263 if (!strcmp(part, "missed")) {
264 if (call_info->state == OFONO_CALL_STATE_INCOMING ||
265 call_info->state == OFONO_CALL_STATE_DIALING)
269 } else if (!strcmp(part, "completed")) {
270 if (call_info->state == OFONO_CALL_STATE_INCOMING ||
271 call_info->state == OFONO_CALL_STATE_DIALING)
275 } else if (!strcmp(part, "outgoing"))
277 else if (!strcmp(part, "incoming"))
280 ERR("Unexpected state part: %s", part);
284 static void _on_clicked(void *data __UNUSED__, Evas_Object *obj __UNUSED__,
285 const char *emission, const char *source __UNUSED__)
287 EINA_SAFETY_ON_NULL_RETURN(emission);
288 emission += strlen("clicked,");
290 if (!strcmp(emission, "all"))
291 elm_object_signal_emit(obj, "show,all", "gui");
293 elm_object_signal_emit(obj, "show,missed", "gui");
296 static void _on_more_clicked(void *data __UNUSED__, Evas_Object *obj __UNUSED__,
297 const char *emission __UNUSED__,
298 const char *source __UNUSED__)
303 static Evas_Object *_item_content_get(void *data __UNUSED__, Evas_Object *obj,
304 const char *part __UNUSED__)
308 btn = gui_layout_add(obj, "history/img");
309 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
310 elm_object_signal_callback_add(btn, "clicked,more", "gui",
311 _on_more_clicked, NULL);
316 Evas_Object *history_add(Evas_Object *parent)
320 const char *config_path;
321 char *path, base_dir[PATH_MAX];
322 Elm_Genlist_Item_Class *itc;
323 Evas_Object *obj, *genlist_all, *genlist_missed;
327 history = calloc(1, sizeof(History));
328 EINA_SAFETY_ON_NULL_RETURN_VAL(history, NULL);
330 obj = gui_layout_add(parent, "history_bg");
331 EINA_SAFETY_ON_NULL_GOTO(obj, err_layout);
333 genlist_all = elm_genlist_add(obj);
334 EINA_SAFETY_ON_NULL_GOTO(genlist_all, err_object_new);
336 genlist_missed = elm_genlist_add(obj);
337 EINA_SAFETY_ON_NULL_GOTO(genlist_missed, err_object_new);
339 itc = elm_genlist_item_class_new();
340 EINA_SAFETY_ON_NULL_GOTO(itc, err_object_new);
341 itc->item_style = "history";
342 itc->func.text_get = _item_label_get;
343 itc->func.content_get = _item_content_get;
344 itc->func.state_get = _item_state_get;
345 itc->func.del = NULL;
346 history->genlist_all = genlist_all;
347 history->genlist_missed = genlist_missed;
350 elm_object_part_content_set(obj, "elm.swallow.all", genlist_all);
351 elm_object_part_content_set(obj, "elm.swallow.missed", genlist_missed);
352 elm_object_signal_emit(obj, "show,all", "gui");
353 elm_object_signal_callback_add(obj, "clicked,*", "gui",
356 config_path = efreet_config_home_get();
357 snprintf(base_dir, sizeof(base_dir), "%s/%s", config_path,
359 ecore_file_mkpath(base_dir);
360 r = asprintf(&path, "%s/%s/history.eet", config_path, PACKAGE_NAME);
365 history->path = path;
366 r = asprintf(&path, "%s/%s/history.eet.bkp", config_path,
374 _history_call_info_descriptor_init(&history->edd, &history->edd_list);
375 _history_call_log_read(history);
376 EINA_SAFETY_ON_NULL_GOTO(history->calls, err_log_read);
377 evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, _on_del,
379 callback_node_call_changed =
380 ofono_call_changed_cb_add(_history_call_changed, history);
381 callback_node_call_removed =
382 ofono_call_removed_cb_add(_history_call_removed, history);
387 eet_data_descriptor_free(history->edd);
388 eet_data_descriptor_free(history->edd_list);
392 elm_genlist_item_class_free(itc);
397 ecore_file_shutdown();