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;
33 Evas_Object *genlist_all, *genlist_missed;
36 typedef struct _Call_Info {
43 const OFono_Call *call; /* not in edd */
46 static OFono_Callback_List_Call_Node *callback_node_call_removed = NULL;
47 static OFono_Callback_List_Call_Node *callback_node_call_changed = NULL;
49 static Call_Info *_history_call_info_search(const History *history,
50 const OFono_Call *call)
55 EINA_LIST_FOREACH(history->calls->list, l, call_info)
56 if (call_info->call == call)
62 static Eina_Bool _history_call_info_update(Call_Info *call_info)
64 OFono_Call_State state;
66 EINA_SAFETY_ON_NULL_RETURN_VAL(call_info->call, EINA_FALSE);
67 state = ofono_call_state_get(call_info->call);
69 if (state == OFONO_CALL_STATE_INCOMING ||
70 state == OFONO_CALL_STATE_WAITING) {
71 if (!call_info->incoming) {
72 call_info->incoming = EINA_TRUE;
75 } else if (state == OFONO_CALL_STATE_DIALING ||
76 state == OFONO_CALL_STATE_ALERTING) {
77 if (!call_info->incoming) {
78 call_info->incoming = EINA_FALSE;
81 } else if (state == OFONO_CALL_STATE_ACTIVE ||
82 state == OFONO_CALL_STATE_HELD) {
83 if (!call_info->completed) {
84 call_info->completed = EINA_TRUE;
92 static void _on_item_clicked(void *data, Evas_Object *obj __UNUSED__,
93 void *event_inf __UNUSED__)
95 const char *number = data;
96 gui_number_set(number, EINA_TRUE);
99 static void _history_call_changed(void *data, OFono_Call *call)
101 History *history = data;
102 const char *line_id = ofono_call_line_id_get(call);
103 Call_Info *call_info;
104 OFono_Call_State state = ofono_call_state_get(call);
106 call_info = _history_call_info_search(history, call);
107 DBG("call=%p, id=%s, state=%d, completed=%d, incoming=%d, info=%p",
108 call, line_id, state,
109 call_info ? call_info->completed : EINA_FALSE,
110 call_info ? call_info->incoming : EINA_FALSE,
116 call_info = calloc(1, sizeof(Call_Info));
117 EINA_SAFETY_ON_NULL_RETURN(call_info);
119 call_info->call = call;
120 call_info->start_time = time(NULL);
121 call_info->line_id = eina_stringshare_add(line_id);
122 call_info->name = eina_stringshare_add(ofono_call_name_get(call));
123 history->calls->list =
124 eina_list_prepend(history->calls->list, call_info);
125 history->calls->dirty = EINA_TRUE;
128 if (_history_call_info_update(call_info))
129 history->calls->dirty = EINA_TRUE;
132 static void _history_call_log_save(History *history)
136 EINA_SAFETY_ON_NULL_RETURN(history->calls);
137 DBG("save history (%u calls, dirty: %d) to %s",
138 eina_list_count(history->calls->list), history->calls->dirty,
141 ecore_file_unlink(history->bkp);
142 ecore_file_mv(history->path, history->bkp);
143 efile = eet_open(history->path, EET_FILE_MODE_WRITE);
144 EINA_SAFETY_ON_NULL_RETURN(efile);
145 if (!(eet_data_write(efile,
146 history->edd_list, HISTORY_ENTRY,
147 history->calls, EET_COMPRESSION_DEFAULT)))
148 ERR("Could in the history log file");
153 static void _history_call_removed(void *data, OFono_Call *call)
155 History *history = data;
156 const char *line_id = ofono_call_line_id_get(call);
157 Call_Info *call_info;
161 call_info = _history_call_info_search(history, call);
162 DBG("call=%p, id=%s, info=%p", call, line_id, call_info);
163 EINA_SAFETY_ON_NULL_RETURN(call_info);
164 start = call_info->start_time;
167 if (call_info->completed)
168 INF("Call end: %s at %s", line_id, tm);
170 if (!call_info->incoming)
171 INF("Not answered: %s at %s", line_id, tm);
173 INF("Missed: %s at %s", line_id, tm);
174 elm_genlist_item_prepend(history->genlist_missed,
177 ELM_GENLIST_ITEM_NONE,
183 call_info->end_time = time(NULL);
184 call_info->call = NULL;
185 history->calls->dirty = EINA_TRUE;
186 _history_call_log_save(history);
188 elm_genlist_item_prepend(history->genlist_all, history->itc, call_info,
189 NULL, ELM_GENLIST_ITEM_NONE,
190 _on_item_clicked, call_info->line_id);
193 static void _call_info_free(Call_Info *call_info)
195 eina_stringshare_del(call_info->line_id);
196 eina_stringshare_del(call_info->name);
200 static void _on_del(void *data, Evas *e __UNUSED__,
201 Evas_Object *obj __UNUSED__, void *event __UNUSED__)
203 History *history = data;
204 Call_Info *call_info;
206 if (history->calls->dirty)
207 _history_call_log_save(history);
209 ofono_call_removed_cb_del(callback_node_call_removed);
210 ofono_call_changed_cb_del(callback_node_call_changed);
211 eet_data_descriptor_free(history->edd);
212 eet_data_descriptor_free(history->edd_list);
213 EINA_LIST_FREE(history->calls->list, call_info)
214 _call_info_free(call_info);
215 free(history->calls);
216 elm_genlist_item_class_free(history->itc);
220 ecore_file_shutdown();
224 static void _history_call_info_descriptor_init(Eet_Data_Descriptor **edd,
225 Eet_Data_Descriptor **edd_list)
227 Eet_Data_Descriptor_Class eddc;
229 EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Call_Info);
230 *edd = eet_data_descriptor_stream_new(&eddc);
232 EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Call_Info_List);
233 *edd_list = eet_data_descriptor_stream_new(&eddc);
235 EET_DATA_DESCRIPTOR_ADD_BASIC(*edd, Call_Info,
236 "completed", completed, EET_T_UCHAR);
237 EET_DATA_DESCRIPTOR_ADD_BASIC(*edd, Call_Info,
238 "incoming", incoming, EET_T_UCHAR);
240 EET_DATA_DESCRIPTOR_ADD_BASIC(*edd, Call_Info,
241 "start_time", start_time, EET_T_LONG_LONG);
242 EET_DATA_DESCRIPTOR_ADD_BASIC(*edd, Call_Info,
243 "end_time", end_time, EET_T_LONG_LONG);
244 EET_DATA_DESCRIPTOR_ADD_BASIC(*edd, Call_Info,
245 "line_id", line_id, EET_T_STRING);
246 EET_DATA_DESCRIPTOR_ADD_BASIC(*edd, Call_Info,
247 "name", name, EET_T_STRING);
249 EET_DATA_DESCRIPTOR_ADD_LIST(*edd_list, Call_Info_List, "list", list,
253 static void _history_call_log_read(History *history)
255 Call_Info *call_info;
258 Call_Info_List *calls = NULL;
260 efile = eet_open(history->path, EET_FILE_MODE_READ);
263 calls = eet_data_read(efile, history->edd_list, HISTORY_ENTRY);
268 efile = eet_open(history->bkp, EET_FILE_MODE_READ);
270 calls = eet_data_read(efile, history->edd_list,
277 calls = calloc(1, sizeof(Call_Info_List));
279 history->calls = calls;
280 EINA_SAFETY_ON_NULL_RETURN(history->calls);
282 EINA_LIST_FOREACH(history->calls->list, l, call_info) {
283 elm_genlist_item_append(history->genlist_all, history->itc,
284 call_info, NULL, ELM_GENLIST_ITEM_NONE,
285 _on_item_clicked, call_info->line_id);
286 if (!call_info->completed)
287 elm_genlist_item_append(history->genlist_missed,
288 history->itc, call_info, NULL,
289 ELM_GENLIST_ITEM_NONE,
295 static char *_item_label_get(void *data, Evas_Object *obj __UNUSED__,
298 Call_Info *call_info = data;
300 if (strncmp(part, "text.call", strlen("text.call")))
303 part += strlen("text.call.");
305 if (!strcmp(part, "name")) {
306 if (!call_info->name || call_info->name[0] == '\0')
307 return phone_format(call_info->line_id);
308 return strdup(call_info->name);
311 if (!strcmp(part, "time"))
312 return date_format(call_info->end_time);
314 /* TODO: Fetch phone type from contacts information*/
315 if (!strcmp(part, "type"))
316 return strdup("TODO:TELEPHONE TYPE");
318 ERR("Unexpected text part: %s", part);
323 static Eina_Bool _item_state_get(void *data, Evas_Object *obj __UNUSED__,
326 Call_Info *call_info = data;
328 if (!strcmp(part, "missed"))
329 return !call_info->completed;
330 else if (!strcmp(part, "completed"))
331 return call_info->completed;
332 else if (!strcmp(part, "outgoing"))
333 return !call_info->incoming;
334 else if (!strcmp(part, "incoming"))
335 return call_info->incoming;
337 ERR("Unexpected state part: %s", part);
341 static void _on_clicked(void *data __UNUSED__, Evas_Object *obj __UNUSED__,
342 const char *emission, const char *source __UNUSED__)
344 EINA_SAFETY_ON_NULL_RETURN(emission);
345 emission += strlen("clicked,");
347 if (!strcmp(emission, "all"))
348 elm_object_signal_emit(obj, "show,all", "gui");
350 elm_object_signal_emit(obj, "show,missed", "gui");
353 static void _on_more_clicked(void *data __UNUSED__, Evas_Object *obj __UNUSED__,
354 const char *emission __UNUSED__,
355 const char *source __UNUSED__)
360 static Evas_Object *_item_content_get(void *data __UNUSED__, Evas_Object *obj,
361 const char *part __UNUSED__)
365 btn = gui_layout_add(obj, "history/img");
366 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
367 elm_object_signal_callback_add(btn, "clicked,more", "gui",
368 _on_more_clicked, NULL);
369 evas_object_propagate_events_set(btn, EINA_FALSE);
374 Evas_Object *history_add(Evas_Object *parent)
378 const char *config_path;
379 char *path, base_dir[PATH_MAX];
380 Elm_Genlist_Item_Class *itc;
381 Evas_Object *obj, *genlist_all, *genlist_missed;
385 history = calloc(1, sizeof(History));
386 EINA_SAFETY_ON_NULL_RETURN_VAL(history, NULL);
388 obj = gui_layout_add(parent, "history_bg");
389 EINA_SAFETY_ON_NULL_GOTO(obj, err_layout);
391 genlist_all = elm_genlist_add(obj);
392 EINA_SAFETY_ON_NULL_GOTO(genlist_all, err_object_new);
393 elm_object_style_set(genlist_all, "history");
395 genlist_missed = elm_genlist_add(obj);
396 EINA_SAFETY_ON_NULL_GOTO(genlist_missed, err_object_new);
397 elm_object_style_set(genlist_missed, "history");
399 itc = elm_genlist_item_class_new();
400 EINA_SAFETY_ON_NULL_GOTO(itc, err_object_new);
401 itc->item_style = "history";
402 itc->func.text_get = _item_label_get;
403 itc->func.content_get = _item_content_get;
404 itc->func.state_get = _item_state_get;
405 itc->func.del = NULL;
406 history->genlist_all = genlist_all;
407 history->genlist_missed = genlist_missed;
410 elm_object_part_content_set(obj, "elm.swallow.all", genlist_all);
411 elm_object_part_content_set(obj, "elm.swallow.missed", genlist_missed);
412 elm_object_signal_emit(obj, "show,all", "gui");
413 elm_object_signal_callback_add(obj, "clicked,*", "gui",
416 config_path = efreet_config_home_get();
417 snprintf(base_dir, sizeof(base_dir), "%s/%s", config_path,
419 ecore_file_mkpath(base_dir);
420 r = asprintf(&path, "%s/%s/history.eet", config_path, PACKAGE_NAME);
425 history->path = path;
426 r = asprintf(&path, "%s/%s/history.eet.bkp", config_path,
434 _history_call_info_descriptor_init(&history->edd, &history->edd_list);
435 _history_call_log_read(history);
436 EINA_SAFETY_ON_NULL_GOTO(history->calls, err_log_read);
437 evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, _on_del,
439 callback_node_call_changed =
440 ofono_call_changed_cb_add(_history_call_changed, history);
441 callback_node_call_removed =
442 ofono_call_removed_cb_add(_history_call_removed, history);
447 eet_data_descriptor_free(history->edd);
448 eet_data_descriptor_free(history->edd_list);
452 elm_genlist_item_class_free(itc);
457 ecore_file_shutdown();