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 {
26 typedef struct _History {
28 Eet_Data_Descriptor *edd;
29 Eet_Data_Descriptor *edd_list;
30 Call_Info_List *calls;
31 Elm_Genlist_Item_Class *itc;
32 Evas_Object *genlist_all, *genlist_missed;
35 typedef struct _Call_Info {
43 static OFono_Callback_List_Call_Node *callback_node_call_removed = NULL;
44 static OFono_Callback_List_Call_Node *callback_node_call_changed = NULL;
46 static Call_Info *_history_call_info_list_search(Eina_List *list,
52 EINA_LIST_FOREACH(list, l, call_info)
53 if (!strcmp(call_info->line_id, line_id))
59 static void _history_call_changed(void *data, OFono_Call *call)
61 History *history = data;
62 const char *line_id = ofono_call_line_id_get(call);
64 OFono_Call_State state = ofono_call_state_get(call);
67 _history_call_info_list_search(history->calls->list, line_id);
70 /* Otherwise I missed the call or the person didn't
73 if ((call_info->state == OFONO_CALL_STATE_INCOMING ||
74 call_info->state == OFONO_CALL_STATE_DIALING) &&
75 state != OFONO_CALL_STATE_DISCONNECTED)
76 call_info->state = state;
79 call_info = calloc(1, sizeof(Call_Info));
80 EINA_SAFETY_ON_NULL_RETURN(call_info);
82 call_info->state = state;
83 call_info->start_time = time(NULL);
84 call_info->line_id = eina_stringshare_add(line_id);
85 call_info->name = eina_stringshare_add(ofono_call_name_get(call));
86 history->calls->list =
87 eina_list_prepend(history->calls->list, call_info);
90 static void _history_call_log_save(History *history)
94 ecore_file_unlink(history->bkp);
95 ecore_file_mv(history->path, history->bkp);
96 efile = eet_open(history->path, EET_FILE_MODE_WRITE);
97 EINA_SAFETY_ON_NULL_RETURN(efile);
98 if (!(eet_data_write(efile,
99 history->edd_list, HISTORY_ENTRY,
100 history->calls, EET_COMPRESSION_DEFAULT)))
101 ERR("Could in the history log file");
106 static void _history_call_removed(void *data, OFono_Call *call)
108 History *history = data;
109 const char *line_id = ofono_call_line_id_get(call);
110 Call_Info *call_info;
115 _history_call_info_list_search(history->calls->list, line_id);
116 EINA_SAFETY_ON_NULL_RETURN(call_info);
117 start = call_info->start_time;
120 if (call_info->state == OFONO_CALL_STATE_INCOMING) {
121 INF("Missed call - Id: %s - time: %s", line_id, tm);
122 elm_genlist_item_append(history->genlist_missed, history->itc,
123 call_info, NULL, ELM_GENLIST_ITEM_NONE,
125 } else if (call_info->state == OFONO_CALL_STATE_DIALING)
126 INF("Call not answered - Id: %s - time: %s", line_id, tm);
128 INF("A call has ended - Id: %s - time: %s", line_id, tm);
130 call_info->end_time = time(NULL);
131 _history_call_log_save(history);
132 elm_genlist_item_append(history->genlist_all, history->itc, call_info,
133 NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL);
136 static void _call_info_free(Call_Info *call_info)
138 eina_stringshare_del(call_info->line_id);
139 eina_stringshare_del(call_info->name);
143 static void _on_del(void *data, Evas *e __UNUSED__,
144 Evas_Object *obj __UNUSED__, void *event __UNUSED__)
146 History *history = data;
147 Call_Info *call_info;
148 ofono_call_removed_cb_del(callback_node_call_removed);
149 ofono_call_changed_cb_del(callback_node_call_changed);
150 eet_data_descriptor_free(history->edd);
151 eet_data_descriptor_free(history->edd_list);
152 EINA_LIST_FREE(history->calls->list, call_info)
153 _call_info_free(call_info);
154 free(history->calls);
155 elm_genlist_item_class_free(history->itc);
159 ecore_file_shutdown();
163 static void _history_call_info_descriptor_init(Eet_Data_Descriptor **edd,
164 Eet_Data_Descriptor **edd_list)
166 Eet_Data_Descriptor_Class eddc;
168 EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Call_Info);
169 *edd = eet_data_descriptor_stream_new(&eddc);
171 EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Call_Info_List);
172 *edd_list = eet_data_descriptor_stream_new(&eddc);
174 EET_DATA_DESCRIPTOR_ADD_BASIC(*edd, Call_Info,
175 "state", state, EET_T_INT);
176 EET_DATA_DESCRIPTOR_ADD_BASIC(*edd, Call_Info,
177 "start_time", start_time, EET_T_LONG_LONG);
178 EET_DATA_DESCRIPTOR_ADD_BASIC(*edd, Call_Info,
179 "end_time", end_time, EET_T_LONG_LONG);
180 EET_DATA_DESCRIPTOR_ADD_BASIC(*edd, Call_Info,
181 "line_id", line_id, EET_T_STRING);
182 EET_DATA_DESCRIPTOR_ADD_BASIC(*edd, Call_Info,
183 "name", name, EET_T_STRING);
185 EET_DATA_DESCRIPTOR_ADD_LIST(*edd_list, Call_Info_List, "list", list,
189 static void _history_call_log_read(History *history)
191 Call_Info *call_info;
194 Call_Info_List *calls = NULL;
196 efile = eet_open(history->path, EET_FILE_MODE_READ);
199 calls = eet_data_read(efile, history->edd_list, HISTORY_ENTRY);
204 efile = eet_open(history->bkp, EET_FILE_MODE_READ);
206 calls = eet_data_read(efile, history->edd_list,
213 history->calls = calloc(1, sizeof(Call_Info_List));
215 history->calls = calls;
216 EINA_SAFETY_ON_NULL_RETURN(history->calls);
218 EINA_LIST_FOREACH(history->calls->list, l, call_info) {
221 elm_genlist_item_append(history->genlist_all, history->itc,
222 call_info, NULL, ELM_GENLIST_ITEM_NONE,
224 if (call_info->state == OFONO_CALL_STATE_INCOMING)
225 elm_genlist_item_append(history->genlist_missed,
226 history->itc, call_info, NULL,
227 ELM_GENLIST_ITEM_NONE,
232 static char *_item_label_get(void *data, Evas_Object *obj __UNUSED__,
235 Call_Info *call_info = data;
237 if (strncmp(part, "text.call", strlen("text.call")))
240 part += strlen("text.call.");
242 if (!strcmp(part, "name")) {
243 if (!call_info->name || call_info->name[0] == '\0')
244 return phone_format(call_info->line_id);
245 return strdup(call_info->name);
248 if (!strcmp(part, "time"))
249 return date_format(call_info->end_time);
251 /* TODO: Fetch phone type from contacts information*/
252 if (!strcmp(part, "type"))
253 return strdup("TODO:TELEPHONE TYPE");
255 ERR("Unexpected text part: %s", part);
260 static Eina_Bool _item_state_get(void *data, Evas_Object *obj __UNUSED__,
263 Call_Info *call_info = data;
265 if (!strcmp(part, "missed")) {
266 if (call_info->state == OFONO_CALL_STATE_INCOMING ||
267 call_info->state == OFONO_CALL_STATE_DIALING)
271 } else if (!strcmp(part, "completed")) {
272 if (call_info->state == OFONO_CALL_STATE_INCOMING ||
273 call_info->state == OFONO_CALL_STATE_DIALING)
277 } else if (!strcmp(part, "outgoing"))
279 else if (!strcmp(part, "incoming"))
282 ERR("Unexpected state part: %s", part);
286 static void _on_clicked(void *data __UNUSED__, Evas_Object *obj __UNUSED__,
287 const char *emission, const char *source __UNUSED__)
289 EINA_SAFETY_ON_NULL_RETURN(emission);
290 emission += strlen("clicked,");
292 if (!strcmp(emission, "all"))
293 elm_object_signal_emit(obj, "show,all", "gui");
295 elm_object_signal_emit(obj, "show,missed", "gui");
298 static void _on_more_clicked(void *data __UNUSED__, Evas_Object *obj __UNUSED__,
299 const char *emission __UNUSED__,
300 const char *source __UNUSED__)
305 static Evas_Object *_item_content_get(void *data __UNUSED__, Evas_Object *obj,
306 const char *part __UNUSED__)
310 btn = gui_layout_add(obj, "history/img");
311 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
312 elm_object_signal_callback_add(btn, "clicked,more", "gui",
313 _on_more_clicked, NULL);
318 Evas_Object *history_add(Evas_Object *parent)
322 const char *config_path;
323 char *path, base_dir[PATH_MAX];
324 Elm_Genlist_Item_Class *itc;
325 Evas_Object *obj, *genlist_all, *genlist_missed;
329 history = calloc(1, sizeof(History));
330 EINA_SAFETY_ON_NULL_RETURN_VAL(history, NULL);
332 obj = gui_layout_add(parent, "history_bg");
333 EINA_SAFETY_ON_NULL_GOTO(obj, err_layout);
335 genlist_all = elm_genlist_add(obj);
336 EINA_SAFETY_ON_NULL_GOTO(genlist_all, err_object_new);
337 elm_object_style_set(genlist_all, "history");
339 genlist_missed = elm_genlist_add(obj);
340 EINA_SAFETY_ON_NULL_GOTO(genlist_missed, err_object_new);
341 elm_object_style_set(genlist_missed, "history");
343 itc = elm_genlist_item_class_new();
344 EINA_SAFETY_ON_NULL_GOTO(itc, err_object_new);
345 itc->item_style = "history";
346 itc->func.text_get = _item_label_get;
347 itc->func.content_get = _item_content_get;
348 itc->func.state_get = _item_state_get;
349 itc->func.del = NULL;
350 history->genlist_all = genlist_all;
351 history->genlist_missed = genlist_missed;
354 elm_object_part_content_set(obj, "elm.swallow.all", genlist_all);
355 elm_object_part_content_set(obj, "elm.swallow.missed", genlist_missed);
356 elm_object_signal_emit(obj, "show,all", "gui");
357 elm_object_signal_callback_add(obj, "clicked,*", "gui",
360 config_path = efreet_config_home_get();
361 snprintf(base_dir, sizeof(base_dir), "%s/%s", config_path,
363 ecore_file_mkpath(base_dir);
364 r = asprintf(&path, "%s/%s/history.eet", config_path, PACKAGE_NAME);
369 history->path = path;
370 r = asprintf(&path, "%s/%s/history.eet.bkp", config_path,
378 _history_call_info_descriptor_init(&history->edd, &history->edd_list);
379 _history_call_log_read(history);
380 EINA_SAFETY_ON_NULL_GOTO(history->calls, err_log_read);
381 evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, _on_del,
383 callback_node_call_changed =
384 ofono_call_changed_cb_add(_history_call_changed, history);
385 callback_node_call_removed =
386 ofono_call_removed_cb_add(_history_call_removed, history);
391 eet_data_descriptor_free(history->edd);
392 eet_data_descriptor_free(history->edd_list);
396 elm_genlist_item_class_free(itc);
401 ecore_file_shutdown();