[misc] Sync from master branch.
[apps/core/preloaded/calendar.git] / ug / list / ug-list.c
1 /*
2   *
3   *  Copyright 2012  Samsung Electronics Co., Ltd
4   *
5   *  Licensed under the Flora License, Version 1.0 (the "License");
6   *  you may not use this file except in compliance with the License.
7   *  You may obtain a copy of the License at
8   *
9   *       http://floralicense.org/license/
10   *
11   *  Unless required by applicable law or agreed to in writing, software
12   *  distributed under the License is distributed on an "AS IS" BASIS,
13   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   *  See the License for the specific language governing permissions and
15   *  limitations under the License.
16   */
17
18
19 #include <fcntl.h>
20 #include <vconf.h>
21 #include "cld.h"
22 #include "ug.h"
23
24 static const char *_name = "list/base";
25
26 ///TODO: get full path from caller
27 #define VFILE_PATH "/opt/usr/media/Others"
28
29 static Elm_Entry_Filter_Limit_Size _limit_20char = {
30        .max_char_count = 20,
31 };
32
33 #define MAX_FETCH_COUNT 10
34
35 #define ACCOUNT_LABLE_STRING_LENGTH 128
36
37 typedef struct {
38         const char *name;
39         struct ug_data *ugd;
40         Evas_Object *parent;
41         Evas_Object *ly;
42         Evas_Object *no_contents;
43         Evas_Object *bg;
44
45         Evas_Object *bt;
46
47         Evas_Object *genlist;
48
49         Eina_List *event_list;
50
51         Evas_Object *box;
52
53         Ecore_Idler* idler;
54
55         int checked_event_count;
56         int added_event_count;
57         Evas_Object* searchbar;
58         char * searchtext;
59         Elm_Object_Item *navi_item;
60 }cal_list_ug_data;
61
62 typedef struct {
63         Elm_Object_Item *it;  // Genlist Item pointer
64         Eina_Bool checked;     // Check status
65         char *label;
66         calendar_record_h record;
67         struct tm* tm;
68         Elm_Genlist_Item_Type it_flag;
69 }cal_list_ug_item_data;
70
71 static void __cal_list_ug_genlist_item_select_callback(void *data, Evas_Object *obj, void *event_info);
72 static void __cal_list_ug_update_callback(const char* view_uri, void *data);
73 static void __cal_list_ug_searchbar_entry_changed_callback(void *data, Evas_Object *obj, void *event_info);
74 static void __cal_list_ug_cancel_button_callback(void *data, Evas_Object *obj, void *event_info);
75 static void __cal_list_ug_searchbar_entry_unfocused_callback(void *data, Evas_Object *obj, void *event_info);
76 static void __cal_list_ug_searchbar_clicked_callback(void *data, Evas_Object *obj, void *event_info);
77 static void __cal_list_ug_create_searchbar(cal_list_ug_data *p);
78 static char* __cal_list_ug_get_genlist_item_label(void *data, Evas_Object *obj, const char *part);
79 static Evas_Object *__cal_list_ug_get_genlist_item_icon(void *data, Evas_Object *obj, const char *part);
80
81 static Elm_Genlist_Item_Class *itc = NULL;
82
83 static Elm_Genlist_Item_Class itc_multiple = {
84         .item_style = "3text.4icon.calendar.check",
85         .func.text_get = __cal_list_ug_get_genlist_item_label,
86         .func.content_get = __cal_list_ug_get_genlist_item_icon,
87 };
88
89 static Elm_Genlist_Item_Class itc_single = {
90         .item_style = "4text.1icon.3.calendar.search",
91         .func.text_get = __cal_list_ug_get_genlist_item_label,
92         .func.content_get = __cal_list_ug_get_genlist_item_icon,
93 };
94
95 static _calendar_book_color calendar_color;
96
97 //TODO
98 #define ELM_GENLIST_ITEM_GROUP (1<<1)
99
100 static void __cal_list_ug_update_selection_info(cal_list_ug_data *p)
101 {
102         CAL_FN_START;
103
104         c_ret_if(!p);
105
106         if (!p->checked_event_count) {
107                 cal_util_hide_small_information(p->ly);
108                 return;
109         }
110
111         char lable_str[128] = { '\0'};
112
113         snprintf(lable_str, sizeof(lable_str), "%s (%d)", S_("IDS_COM_POP_SELECTED"), p->checked_event_count);
114
115         cal_util_show_small_information(p->ly, lable_str, 0.0);
116 }
117
118 static inline void __cal_list_ug_update_button_state(cal_list_ug_data *p)
119 {
120         if (0 < p->checked_event_count)
121                 elm_object_disabled_set(p->bt, EINA_FALSE);
122         else
123                 elm_object_disabled_set(p->bt, EINA_TRUE);
124 }
125
126 static inline void __cal_list_ug_update_realized_genlist_item(cal_list_ug_data *p)
127 {
128         Eina_List *realized_list = elm_genlist_realized_items_get(p->genlist);
129         c_ret_if(!realized_list);
130
131         Eina_List *l = NULL;
132         Elm_Object_Item *it = NULL;
133
134         EINA_LIST_FOREACH(realized_list, l, it) {
135                 if (it)
136                         elm_genlist_item_update(it);
137         }
138 }
139
140 static void __cal_list_ug_genlist_item_check_changed_callback(void *data, Evas_Object *obj, void *event_info)
141 {
142         c_ret_if(!data);
143         c_ret_if(!obj);
144
145         cal_list_ug_item_data *item_data = data;
146
147         cal_list_ug_data* p = CAL_UTIL_GET_PRIV_DATA(obj);
148         c_ret_if(!p);
149
150         item_data->checked = elm_check_state_get(obj);
151
152         if (item_data->checked)
153                 p->checked_event_count++;
154         else
155                 p->checked_event_count--;
156
157         __cal_list_ug_update_button_state(p);
158
159         __cal_list_ug_update_realized_genlist_item(p);
160
161         __cal_list_ug_update_selection_info(p);
162 }
163
164 static Evas_Object *__cal_list_ug_get_genlist_item_icon(void *data, Evas_Object *obj, const char *part)
165 {
166         c_retv_if(!part, NULL);
167         c_retv_if(!obj, NULL);
168         c_retv_if(!data, NULL);
169
170         cal_list_ug_item_data *item_data = data;
171
172         if (!CAL_STRCMP(part, "elm.edit.icon")) {
173
174                 cal_list_ug_data* p = CAL_UTIL_GET_PRIV_DATA(obj);
175                 c_retv_if(!p, NULL);
176
177                 Evas_Object *checkbox = elm_check_add(obj);
178                 c_retv_if(!checkbox, NULL);
179
180                 elm_check_state_pointer_set(checkbox, &item_data->checked);
181                 evas_object_smart_callback_add(checkbox, "changed", __cal_list_ug_genlist_item_check_changed_callback, item_data);
182                 evas_object_propagate_events_set(checkbox, EINA_FALSE);
183                 evas_object_data_set(checkbox, "priv", p);
184
185                 return checkbox;
186
187         } else if (!CAL_STRCMP(part, "elm.swallow.colorbar")) {
188
189                 Evas_Object *rect = evas_object_rectangle_add(evas_object_evas_get(obj));
190                 c_retv_if(!rect, NULL);
191
192                 evas_object_size_hint_align_set(rect, EVAS_HINT_FILL, EVAS_HINT_FILL);
193
194                 _calendar_get_calendar_color(item_data->record, &calendar_color);
195
196                 evas_object_color_set(rect, calendar_color.red, calendar_color.green, calendar_color.blue, calendar_color.alpha);
197
198                 return rect;
199         }
200
201         return NULL;
202 }
203
204 static void __cal_list_ug_delete_idler(cal_list_ug_data *p)
205 {
206         CAL_FN_START;
207
208         c_ret_if(!p);
209
210         if (!p->idler)
211                 return;
212
213         ecore_idler_del(p->idler);
214         p->idler = NULL;
215 }
216
217 static void __cal_list_ug_delete_no_contents(cal_list_ug_data *p)
218 {
219         CAL_FN_START;
220
221         c_ret_if(!p);
222         c_ret_if(!p->ly);
223
224         if (!p->no_contents)
225                 return;
226
227         elm_object_part_content_unset(p->ly, "sw");
228
229         evas_object_del(p->no_contents);
230
231         p->no_contents = NULL;
232 }
233
234 static void __cal_list_ug_delete_layout(void *data, Evas *e, Evas_Object *obj, void *ei)
235 {
236         CAL_FN_START;
237
238         c_retm_if(!data, "data is null");
239
240         cal_list_ug_data *p = data;
241
242         calendar_error_e error = CALENDAR_ERROR_NONE;
243
244         error = calendar_db_remove_changed_cb(_calendar_event._uri, __cal_list_ug_update_callback, p);
245         c_warn_if(error != CALENDAR_ERROR_NONE, "calendar_db_remove_changed_cb() is failed(%x)", error);
246
247         __cal_list_ug_delete_idler(p);
248
249         _calendar_free_record_list(&p->event_list);
250
251         free(p);
252 }
253
254 static char* __cal_list_ug_get_genlist_item_label(void *data, Evas_Object *obj, const char *part)
255 {
256         c_retv_if(!part, NULL);
257         c_retv_if(!data, NULL);
258
259         cal_list_ug_item_data *item = data;
260         calendar_record_h record = item->record;
261         c_retv_if(!record, NULL);
262
263         if (!CAL_STRCMP(part, "elm.text.1")) {
264
265                 return _calendar_get_summary(record);
266         }
267
268         if (!CAL_STRCMP(part, "elm.text.3")) {
269
270                 return _calendar_get_location(record);
271         }
272
273         if (!CAL_STRCMP(part, "elm.text.2"))
274                 return _calendar_get_time_str_for_genlist(record);
275
276         return NULL;
277 }
278
279 static void __cal_list_ug_genlist_item_select_callback(void *data, Evas_Object *obj, void *event_info)
280 {
281         c_retm_if(!data, "data is null");
282         c_retm_if(!obj, "obj is null");
283
284         Elm_Object_Item* it;
285         cal_list_ug_item_data* item = data;
286         cal_list_ug_data *p = CAL_UTIL_GET_PRIV_DATA(obj);
287         c_retm_if(!p, "p is null");
288
289         if (p->ugd->selection_mode == SELECTION_MODE_SINGLE) {
290
291                 int cid = _calendar_get_record_index(item->record);
292                 c_retm_if(cid < 0, "CALENDAR_SVC_STRUCT_GET_INT return error!");
293
294                 service_h service;
295
296                 service_create(&service);
297
298                 char ** value = calloc(1, sizeof(char *));
299                 if(!value)      {
300                         ERR("value is NULL!");
301                         service_destroy(service);
302                         return;
303                 }
304
305
306                 char path[FILENAME_MAX] = {0};
307                 char *vcs_data = NULL;
308
309                 snprintf(path, sizeof(path), "%s/Calendar_%d.vcs", VFILE_PATH, cid);
310
311                 calendar_list_h list = NULL;
312
313                 calendar_error_e error = CALENDAR_ERROR_NONE;
314
315                 error = calendar_list_create(&list);
316                 c_warn_if(error != CALENDAR_ERROR_NONE, "calendar_list_create() is failed(%x)");
317
318                 error = calendar_list_add(list, item->record);
319                 c_warn_if(error != CALENDAR_ERROR_NONE, "calendar_list_add() is failed(%x)");
320
321                 error = calendar_vcalendar_make_from_records(list, &vcs_data);
322                 c_warn_if(error != CALENDAR_ERROR_NONE, "calendar_vcalendar_make_from_records() is failed(%x)");
323
324
325                 int fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0644);
326                 if(fd < 0)
327                 {
328                         ERR("Failed to open file %s.", path);
329
330                         free(value);
331                         service_destroy(service);
332                         error = calendar_list_destroy(list, false);
333                         c_warn_if(error != CALENDAR_ERROR_NONE, "calendar_list_destroy() is failed(%x)");
334
335                         return;
336                 }
337
338                 if (vcs_data) {
339                         int ret = write(fd, vcs_data, strlen(vcs_data));
340                         if (ret == -1)
341                                 ERR("write() is failed.");
342                         else
343                                 cal_util_update_media_db(path);
344
345                         free(vcs_data);
346                 }
347
348                 fsync(fd);
349                 close(fd);
350
351                 error = calendar_list_destroy(list, false);
352                 c_warn_if(error != CALENDAR_ERROR_NONE, "calendar_list_destroy() is failed(%x)");
353
354                 value[0] = strdup(path);
355
356                 service_add_extra_data_array(service, CAL_APPCONTROL_PATH, value, 1);
357                 service_add_extra_data_array(service, "path", (const char **)value, 1);
358
359                 free(value[0]);
360                 free(value);
361
362                 service_add_extra_data(service, "result", "success");
363
364                 if (p->ugd->item_type == ITEM_TYPE_EVENT)
365                         service_add_extra_data(service, "itemType", "event");
366                 else
367                         service_add_extra_data(service, "itemType", "todo");
368
369                 ug_send_result(p->ugd->ug, service);
370                 service_destroy(service);
371
372                 ug_destroy_me(p->ugd->ug);
373
374                 return;
375         }
376
377         if (p->added_event_count <= 0) {
378                 return;
379         }
380
381         item->checked = !(item->checked);
382         if (item->checked) {
383                 p->checked_event_count++;
384         } else {
385                 p->checked_event_count--;
386         }
387
388         if (item->checked || 0 < p->checked_event_count) {
389                 elm_object_disabled_set(p->bt, EINA_FALSE);
390         } else if (p->checked_event_count <= 0) {
391                 elm_object_disabled_set(p->bt, EINA_TRUE);
392         }
393
394         it = elm_genlist_selected_item_get(obj);
395         if (it) {
396                 elm_genlist_item_selected_set(it, EINA_FALSE);
397         }
398
399         __cal_list_ug_update_realized_genlist_item(p);
400
401         __cal_list_ug_update_selection_info(p);
402 }
403
404 static void __cal_list_ug_get_event_list(cal_list_ug_data *p)
405 {
406         CAL_FN_START;
407
408         c_ret_if(!p);
409
410         struct tm tm_start = {0};
411         struct tm tm_end = {0};
412
413         tm_start.tm_year = 70;
414         tm_end.tm_year = 137;
415
416         if (p->ugd->item_type == ITEM_TYPE_EVENT)
417                 p->event_list = _calendar_get_all_instance_list(&tm_start,&tm_end);
418         else
419                 p->event_list = _calendar_get_all_task_list2(&tm_start, &tm_end, EINA_TRUE, _CALENDAR_TASK_SORT_TYPE_DUEDATE_ASC);
420 }
421
422 static void __cal_list_ug_add_event_to_genlist(cal_list_ug_data *p)
423 {
424         CAL_FN_START;
425
426         c_ret_if(!p);
427         c_ret_if(!p->event_list);
428
429         Eina_List *l = NULL;
430         calendar_record_h record = NULL;
431
432         int added_event_count = 0;
433
434         Eina_List *event_list = eina_list_nth_list(p->event_list, p->added_event_count);
435         c_ret_if(!event_list);
436
437         EINA_LIST_FOREACH(event_list, l, record) {
438                 if (record) {
439                         cal_list_ug_item_data *item_data = calloc(1, sizeof(cal_list_ug_item_data));
440                         c_ret_if(!item_data);
441
442                         item_data->record = record;
443
444                         item_data->it = elm_genlist_item_append(p->genlist, itc, item_data, NULL, ELM_GENLIST_ITEM_NONE, __cal_list_ug_genlist_item_select_callback, item_data);
445
446                         added_event_count++;
447
448                         if (10 < added_event_count)
449                                 break;
450                 }
451         }
452
453         p->added_event_count += added_event_count;
454 }
455
456 static Eina_Bool __cal_list_ug_check_idler_condition(cal_list_ug_data *p)
457 {
458         c_retv_if(!p, ECORE_CALLBACK_CANCEL);
459
460         if (p->added_event_count < eina_list_count(p->event_list)) {
461
462                 return ECORE_CALLBACK_RENEW;
463         }
464
465         if (p->idler) {
466                 ecore_idler_del(p->idler);
467                 p->idler = NULL;
468         }
469
470         return ECORE_CALLBACK_CANCEL;
471 }
472
473 Eina_Bool __cal_list_ug_idler_callback(void* data)
474 {
475         CAL_FN_START;
476
477         c_retvm_if(!data, ECORE_CALLBACK_CANCEL, "data is null.");
478
479         cal_list_ug_data *p = data;
480
481         c_retv_if(!p->idler, ECORE_CALLBACK_CANCEL);
482
483         __cal_list_ug_add_event_to_genlist(p);
484
485         CAL_FN_END;
486
487         return __cal_list_ug_check_idler_condition(p);
488 }
489
490 static void __cal_list_ug_add_idler(cal_list_ug_data *p)
491 {
492         c_ret_if(!p);
493
494         if (p->added_event_count < eina_list_count(p->event_list)) {
495
496                 if (p->idler)
497                         ecore_idler_del(p->idler);
498
499                 p->idler = ecore_idler_add(__cal_list_ug_idler_callback, p);
500                 c_ret_if(!p->idler);
501         }
502 }
503
504 static void __cal_list_ug_create_searchbar(cal_list_ug_data *p)
505 {
506         c_ret_if(!p);
507         c_ret_if(!p->ly);
508
509         if (p->searchbar)
510                 return;
511
512         Evas_Object *searchbar = cal_util_add_searchbar(p->ly, NULL, NULL, EINA_TRUE, NULL, NULL);
513         c_ret_if(!searchbar);
514
515         Evas_Object *entry = elm_object_part_content_get(searchbar, "elm.swallow.content");
516         c_ret_if(!entry);
517
518         elm_entry_input_panel_layout_set(entry, ELM_INPUT_PANEL_LAYOUT_NORMAL);
519         elm_entry_markup_filter_append(entry, elm_entry_filter_limit_size, &_limit_20char);
520
521         evas_object_size_hint_weight_set(searchbar, EVAS_HINT_EXPAND, 0.1);
522         evas_object_size_hint_align_set(searchbar, EVAS_HINT_FILL, 0.6);
523
524         evas_object_smart_callback_add(entry, "changed", __cal_list_ug_searchbar_entry_changed_callback, p);
525         evas_object_smart_callback_add(entry, "unfocused", __cal_list_ug_searchbar_entry_unfocused_callback, p);
526         evas_object_smart_callback_add(searchbar, "clicked", __cal_list_ug_searchbar_clicked_callback, p);
527         evas_object_smart_callback_add(searchbar, "cancel,clicked", __cal_list_ug_cancel_button_callback, p);
528
529         evas_object_show(searchbar);
530
531         edje_object_signal_emit(CAL_UTIL_GET_EDJ_DATA(p->ly), "searchbar,show", "prog");
532
533         elm_object_part_content_set(p->ly, "searchbar", searchbar);
534
535         p->searchbar = searchbar;
536 }
537
538 static void __cal_list_ug_create_box(cal_list_ug_data *p)
539 {
540         CAL_FN_START;
541
542         c_ret_if(!p);
543         c_ret_if(!p->ly);
544
545         if (p->box)
546                 return;
547
548         Evas_Object *box = elm_box_add(p->ly);
549         c_ret_if(!box);
550
551         evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
552         elm_object_part_content_set(p->ly, "sw", box);
553         p->box = box;
554 }
555
556 static void __cal_list_ug_append_list_with_iter(Eina_List **event_list, calendar_list_h list)
557 {
558         c_ret_if(!event_list);
559         c_ret_if(!list);
560
561         calendar_record_h record = NULL;
562
563         int i = 0;
564
565         int count = 0;
566
567         calendar_error_e error = CALENDAR_ERROR_NONE;
568
569         error = calendar_list_get_count(list, &count);
570         c_warn_if(error != CALENDAR_ERROR_NONE, "calendar_list_get_count() is failed(%x)", error);
571
572         error = calendar_list_first(list);
573         c_warn_if(error != CALENDAR_ERROR_NONE, "calendar_list_first() is failed(%x)", error);
574
575         for (i = 0; i < count; i++) {
576                 error = calendar_list_get_current_record_p(list, &record);
577                 c_warn_if(error != CALENDAR_ERROR_NONE, "calendar_list_get_current_record_p() is failed(%x)", error);
578
579                 *event_list = eina_list_append(*event_list, record);
580
581                 calendar_list_next(list);
582         }
583 }
584
585
586 static void __cal_list_ug_update_event_list_with_keyword(cal_list_ug_data *p)
587 {
588         c_ret_if(!p);
589
590         calendar_list_h list = NULL;
591         if (p->ugd->item_type == ITEM_TYPE_EVENT) {
592                 list = _calendar_search_event(p->searchtext);
593                 c_ret_if(!list);
594         }
595         else {
596                 list = _calendar_search_task(p->searchtext);
597                 c_ret_if(!list);
598         }
599
600         __cal_list_ug_append_list_with_iter(&p->event_list, list);
601
602         calendar_error_e error = CALENDAR_ERROR_NONE;
603
604         error = calendar_list_destroy(list, false);
605         c_warn_if(error != CALENDAR_ERROR_NONE, "calendar_list_destroy() is failed(%x)", error);
606
607 }
608
609 static void __cal_list_ug_update_event_list(cal_list_ug_data *p)
610 {
611         c_ret_if(!p);
612
613         p->checked_event_count = 0;
614
615         p->added_event_count = 0;
616
617         _calendar_free_record_list(&p->event_list);
618
619         if (CAL_STRLEN(p->searchtext))
620                 __cal_list_ug_update_event_list_with_keyword(p);
621         else
622                 __cal_list_ug_get_event_list(p);
623 }
624
625 static void __cal_list_ug_create_genlist(cal_list_ug_data *p)
626 {
627         CAL_FN_START;
628
629         c_ret_if(!p);
630         c_ret_if(!p->box);
631
632         if (p->genlist) {
633
634                 elm_genlist_clear(p->genlist);
635
636                 return;
637         }
638
639         Evas_Object *genlist = elm_genlist_add(p->box);
640         c_ret_if(!genlist);
641
642         if (p->ugd->selection_mode == SELECTION_MODE_SINGLE)
643                 itc = &itc_single;
644         else
645                 itc = &itc_multiple;
646
647         evas_object_data_set(genlist, "priv", p);
648         elm_genlist_homogeneous_set(genlist, EINA_TRUE);
649         evas_object_size_hint_weight_set(genlist, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
650         evas_object_size_hint_align_set(genlist, EVAS_HINT_FILL, EVAS_HINT_FILL);
651         evas_object_show(genlist);
652         elm_box_pack_end(p->box, genlist);
653
654         p->genlist = genlist;
655 }
656
657 static void __cal_list_ug_create_no_contents(cal_list_ug_data *p)
658 {
659         CAL_FN_START;
660
661         c_ret_if(!p);
662         c_ret_if(!p->ly);
663
664         if (!p->no_contents) {
665
666                 p->no_contents = cal_util_add_nocontents(p->ly, C_("IDS_CLD_BODY_NO_EVENTS"));
667                 c_ret_if(!p->no_contents);
668
669         }
670
671         elm_object_part_content_set(p->ly, "sw", p->no_contents);
672
673         evas_object_show(p->no_contents);
674 }
675
676 static void __cal_list_ug_update_callback(const char* view_uri, void *data)
677 {
678         CAL_FN_START;
679
680         c_ret_if(!data);
681         cal_list_ug_data *p = data;
682
683         __cal_list_ug_delete_idler(p);
684
685         __cal_list_ug_update_event_list(p);
686
687         if (p->event_list && eina_list_count(p->event_list)) {
688
689                 __cal_list_ug_delete_no_contents(p);
690
691                 __cal_list_ug_create_searchbar(p);
692
693                 __cal_list_ug_create_box(p);
694
695                 __cal_list_ug_create_genlist(p);
696
697                 __cal_list_ug_add_event_to_genlist(p);
698
699                 __cal_list_ug_add_idler(p);
700
701         } else {
702
703                 //p->searchbar = NULL;
704
705                 elm_object_part_content_unset(p->ly, "sw");
706
707                 evas_object_del(p->box);
708
709                 p->box = NULL;
710
711                 p->genlist = NULL;
712
713                 __cal_list_ug_create_no_contents(p);
714
715                 elm_object_disabled_set(p->bt, EINA_TRUE);
716
717         }
718 }
719
720 static Evas_Object* __cal_list_ug_create_layout(Evas_Object *parent, struct ug_data *ugd)
721 {
722         CAL_FN_START;
723
724         c_retvm_if(!parent, NULL, "parent is null");
725         c_retvm_if(!ugd, NULL, "ugd is null");
726
727         cal_list_ug_data *p = calloc(1, sizeof(cal_list_ug_data));
728         c_retvm_if(!p, NULL, "p is null");
729
730         p->name = _name;
731         p->ugd = ugd;
732         p->parent = parent;
733
734         Evas_Object *ly = cal_util_add_layout(parent, p->name);
735         if (!ly)
736         {
737                 ERR("cal_util_add_layout returned null");
738                 free(p);
739                 return NULL;
740         }
741         p->ly = ly;
742         evas_object_data_set(ly, "priv", p);
743
744         p->bg = cal_util_add_bg(ly,EINA_FALSE);
745         if (!p->bg) {
746                 ERR("cal_util_add_bg returned null");
747                 evas_object_del(ly);
748                 free(p);
749                 ERR("bg is null");
750                 return NULL;
751         }
752         elm_object_part_content_set(ly, "base", p->bg);
753
754         __cal_list_ug_update_callback(_calendar_event._uri, p);
755
756         evas_object_show(ly);
757         evas_object_event_callback_add(ly, EVAS_CALLBACK_DEL, __cal_list_ug_delete_layout, p);
758
759         calendar_error_e error = CALENDAR_ERROR_NONE;
760         error = calendar_db_add_changed_cb(_calendar_event._uri, __cal_list_ug_update_callback, p);
761         c_warn_if(error != CALENDAR_ERROR_NONE, "calendar_db_add_changed_cb() is failed(%x)", error);
762
763         return ly;
764 }
765
766 static void __cal_list_ug_get_message_content(calendar_record_h record, char *body , int nsize)
767 {
768         c_ret_if(!record);
769         c_ret_if(!body);
770
771         char *title = _calendar_get_summary(record);
772
773         strncat(body, title, nsize - CAL_STRLEN(body));
774         strncat(body, "\n", nsize - CAL_STRLEN(body));
775
776         char *location = _calendar_get_location(record);
777
778         if (CAL_STRLEN(location)) {
779                 strncat(body, location, nsize - CAL_STRLEN(body));
780                 strncat(body, "\n", nsize - CAL_STRLEN(body));
781         }
782
783         char text[64] = {0};
784
785         const char *time_format = NULL;
786         if (is_hour24)
787                 time_format = CAL_UTIL_TIME_FORMAT_6;
788         else
789                 time_format = CAL_UTIL_TIME_FORMAT_1;
790
791         struct tm tm_start, tm_end;
792         calendar_time_s start_time = {0};
793         calendar_time_s end_time = {0};
794         _calendar_get_start_time(record, &start_time);
795         _calendar_get_end_time(record, &end_time);
796
797         if (_calendar_is_allday_record(record)) {
798                 long long int lli_time = time(NULL);
799
800                 cal_util_convert_lli_to_tm(NULL, lli_time, &tm_start);
801
802                 tm_end = tm_start;
803
804                 tm_start.tm_year = start_time.time.date.year - 1900;
805                 tm_start.tm_mon = start_time.time.date.month - 1;
806                 tm_start.tm_mday = start_time.time.date.mday;
807
808                 tm_end.tm_year = end_time.time.date.year - 1900;
809                 tm_end.tm_mon = end_time.time.date.month - 1;
810                 tm_end.tm_mday = end_time.time.date.mday;
811
812                 if (tm_start.tm_year == tm_end.tm_year
813                         && tm_start.tm_mon == tm_end.tm_mon
814                         && tm_start.tm_mday == tm_end.tm_mday) {
815                         cal_util_get_time_text(text, sizeof(text), CAL_UTIL_DATE_FORMAT_1, NULL, &tm_start);
816                         strncat(body, text, nsize - CAL_STRLEN(body));
817                 } else {
818                         cal_util_get_time_text(text, sizeof(text), CAL_UTIL_DATE_FORMAT_1, NULL, &tm_start);
819                         strncat(body, text, nsize - CAL_STRLEN(body));
820
821                         strncat(body, " ~ ", nsize - CAL_STRLEN(body));
822
823                         cal_util_get_time_text(text, sizeof(text), CAL_UTIL_DATE_FORMAT_1, NULL, &tm_end);
824                         strncat(body, text, nsize - CAL_STRLEN(body));
825                 }
826
827         } else {
828
829                 cal_util_convert_lli_to_tm(NULL, start_time.time.utime, &tm_start);
830                 cal_util_convert_lli_to_tm(NULL, end_time.time.utime, &tm_end);
831
832                 cal_util_get_time_text(text, sizeof(text), CAL_UTIL_DATE_FORMAT_1, time_format, &tm_start);
833                 strncat(body, text, nsize - CAL_STRLEN(body));
834
835                 strncat(body, " ~ " , nsize - CAL_STRLEN(body));
836
837                 cal_util_get_time_text(text, sizeof(text), CAL_UTIL_DATE_FORMAT_1, time_format, &tm_end);
838                 strncat(body, text, nsize - CAL_STRLEN(body));
839         }
840
841         free(title);
842         CAL_FREE(location);
843 }
844
845
846 static char * __cal_list_ug_add_event_content_to_service(service_h service, int record_index, int result_index)
847 {
848         c_retv_if(!service, NULL);
849         c_retv_if(record_index <= 0, NULL);
850
851         char key[16] = {0};
852         char value[1024] = {0};
853
854         calendar_record_h record = NULL;
855
856         record = _calendar_get_record_with_index(record_index);
857         c_retv_if(!record, NULL);
858
859         __cal_list_ug_get_message_content(record, value, sizeof(value));
860
861         snprintf(key, sizeof(key), "text%d", result_index);
862
863         calendar_error_e error = CALENDAR_ERROR_NONE;
864
865         error = calendar_record_destroy(record, true);
866         c_retvm_if(error != CALENDAR_ERROR_NONE, NULL, "calendar_record_destroy() is failed(%x)", error);
867
868         int r = service_add_extra_data(service, key, value);
869         c_retv_if(r != SERVICE_ERROR_NONE, NULL);
870
871         return CAL_STRDUP(value);
872 }
873
874 static char * __cal_list_ug_add_vcs_path_to_service(service_h service, int record_index, int result_index)
875 {
876         c_retv_if(!service, NULL);
877         c_retv_if(record_index <= 0, NULL);
878
879         calendar_record_h record = NULL;
880
881         record = _calendar_get_record_with_index(record_index);
882         c_retv_if(!record, NULL);
883
884         calendar_error_e error = CALENDAR_ERROR_NONE;
885
886         calendar_list_h list = NULL;
887
888         error = calendar_list_create(&list);
889         if (error != CALENDAR_ERROR_NONE) {
890                 ERR("calendar_list_create() is failed(%x)", error);
891
892                 calendar_record_destroy(record, true);
893
894                 return NULL;
895         }
896
897         error = calendar_list_add(list, record);
898         if (error != CALENDAR_ERROR_NONE) {
899                 ERR("calendar_list_add() is failed(%x)", error);
900
901                 calendar_list_destroy(list, false);
902
903                 calendar_record_destroy(record, true);
904
905                 return NULL;
906         }
907
908         char *vcs_data = NULL;
909
910         error = calendar_vcalendar_make_from_records(list, &vcs_data);
911         if (error != CALENDAR_ERROR_NONE) {
912                 ERR("calendar_vcalendar_make_from_records() is failed(%x)", error);
913
914                 calendar_list_destroy(list, true);
915
916                 return NULL;
917         }
918
919         if (!CAL_STRLEN(vcs_data)) {
920                 ERR("vcs_data is empty");
921
922                 calendar_list_destroy(list, true);
923
924                 return NULL;
925         }
926
927         char key[128] = {0};
928         char value[FILENAME_MAX] = {0};
929
930         snprintf(key, sizeof(key), "vfile%d", result_index);
931         snprintf(value, sizeof(value), "%s/Calendar_%d.vcs", VFILE_PATH, record_index);
932
933         int fd = open(value, O_WRONLY|O_CREAT|O_TRUNC, 0644);
934         if (fd < 0) {
935                 ERR("open() is failed.");
936
937                 calendar_list_destroy(list, true);
938
939                 CAL_FREE(vcs_data);
940
941                 return NULL;
942         }
943
944         int r = write(fd, vcs_data, strlen(vcs_data));
945         if (r == -1) {
946                 ERR("write() is failed.");
947         } else
948                 cal_util_update_media_db(value);
949
950         free(vcs_data);
951
952         fsync(fd);
953         close(fd);
954
955         error = calendar_list_destroy(list, true);
956         c_warn_if(error != CALENDAR_ERROR_NONE, "calendar_list_destroy() is failed(%x)");
957
958         r = service_add_extra_data(service, key, value);
959         c_retv_if(r != SERVICE_ERROR_NONE, NULL);
960
961         return CAL_STRDUP(value);
962 }
963
964 static void __cal_list_ug_add_extra_data_from_record_list(service_h service, GList *record_index_list, struct ug_data *ugd)
965 {
966         c_ret_if(!service);
967         c_ret_if(!record_index_list);
968         c_ret_if(!ugd);
969
970         record_index_list = g_list_first(record_index_list);
971
972         int result_index = 0;
973
974         char **result_array = NULL;
975
976         result_array = calloc(g_list_length(record_index_list), sizeof(char *));
977         c_ret_if(!result_array);
978
979         while (record_index_list && record_index_list->data) {
980
981                 int record_index = (int)record_index_list->data;
982
983                 switch (ugd->result_type) {
984                         case RESULT_TYPE_ITEM_CONTENT:
985                                 result_array[result_index] = __cal_list_ug_add_event_content_to_service(service, record_index, result_index + 1);
986                                 break;
987                         case RESULT_TYPE_VCS:
988                                 result_array[result_index] = __cal_list_ug_add_vcs_path_to_service(service, record_index, result_index + 1);
989                                 break;
990                         case RESULT_TYPE_ITEM_ID:
991                                 result_array[result_index] = g_strdup_printf("%d", record_index);
992                                 break;
993                         default:
994                                 break;
995                 }
996
997                 if (!result_array[result_index]) {
998
999                         ERR("Error, result_array[%d] is null.", result_index);
1000
1001                         free(result_array);
1002
1003                         return;
1004                 }
1005
1006                 record_index_list = g_list_next(record_index_list);
1007
1008                 result_index++;
1009         }
1010
1011         int r = 0;
1012
1013         switch (ugd->result_type) {
1014                 case RESULT_TYPE_ITEM_CONTENT:
1015                         r = service_add_extra_data_array(service, "text", result_array, result_index);
1016                         break;
1017                 case RESULT_TYPE_VCS:
1018                         r = service_add_extra_data_array(service, "path", result_array, result_index);
1019                         c_warn_if(r != SERVICE_ERROR_NONE, "service_add_extra_data_array() is failed(%x).", r);
1020
1021                         r = service_add_extra_data_array(service, CAL_APPCONTROL_PATH, result_array, result_index);
1022                         break;
1023                 case RESULT_TYPE_ITEM_ID:
1024                         r = service_add_extra_data_array(service, CAL_APPCONTROL_ITEM_ID, result_array, result_index);
1025                         break;
1026                 default:
1027                         break;
1028         }
1029
1030         c_warn_if(r != SERVICE_ERROR_NONE, "service_add_extra_data_array() is failed(%x).", r);
1031
1032         free(result_array);
1033 }
1034
1035 static service_h __cal_list_ug_create_return_results(cal_list_ug_data *p, struct ug_data *ugd)
1036 {
1037         c_retv_if(!p, NULL);
1038         c_retv_if(!ugd, NULL);
1039
1040         char buf[32] = {'\0'};
1041
1042         service_h service = NULL;
1043
1044         int r = service_create(&service);
1045         c_retv_if(r != SERVICE_ERROR_NONE, NULL);
1046
1047         Elm_Object_Item* item = elm_genlist_first_item_get(p->genlist);
1048         if (!item) {
1049                 ERR("item is null");
1050                 service_destroy(service);
1051                 return NULL;
1052         }
1053
1054         GList *record_index_list = NULL;
1055
1056         while (item) {
1057
1058                 cal_list_ug_item_data* item_data = elm_object_item_data_get(item);
1059                 if (!item_data) {
1060                         ERR("elm_object_item_data_get() is failed!");
1061                         service_destroy(service);
1062                         return NULL;
1063                 }
1064
1065                 if (item_data->checked)
1066                         record_index_list = g_list_append(record_index_list, (void *)_calendar_get_record_index(item_data->record));
1067
1068                 item = elm_genlist_item_next_get(item);
1069         }
1070
1071         int count = 0;
1072
1073         if (record_index_list) {
1074                 __cal_list_ug_add_extra_data_from_record_list(service, record_index_list, ugd);
1075
1076                 count = g_list_length(record_index_list);
1077
1078                 g_list_free(record_index_list);
1079         }
1080
1081         c_retv_if(!count, service);
1082
1083         snprintf(buf, sizeof(buf), "%d", count);
1084
1085         r = service_add_extra_data(service, "count", buf);
1086         if(r != SERVICE_ERROR_NONE)
1087         {
1088                 ERR("service_add_extra_data_array() is failed(%d)", r);
1089                 service_destroy(service);
1090                 return NULL;
1091         }
1092
1093         if (ugd->item_type == ITEM_TYPE_EVENT)
1094                 r = service_add_extra_data(service, "itemType", "event");
1095         else if (ugd->item_type == ITEM_TYPE_TODO)
1096                 r = service_add_extra_data(service, "itemType", "todo");
1097
1098         c_warn_if(r != SERVICE_ERROR_NONE, "service_add_extra_data() is failed(%d)", r);
1099
1100         r = service_add_extra_data(service, "result", "success");
1101         c_warn_if(r != SERVICE_ERROR_NONE, "service_add_extra_data() is failed(%d)", r);
1102
1103         return service;
1104 }
1105
1106 static void __cal_list_ug_attach(void *data, Evas_Object *obj, void *ei)
1107 {
1108         c_retm_if(!data, "data is null");
1109
1110         Evas_Object *ly = data;
1111         cal_list_ug_data *p;
1112         struct ug_data *ugd;
1113         service_h service = NULL;
1114
1115         p = CAL_UTIL_GET_PRIV_DATA(ly);
1116         c_retm_if(!p, "p is null");
1117
1118         ugd = p->ugd;
1119         c_retm_if(!ugd, "ugd is null");
1120
1121         cal_util_hide_small_information(p->ly);
1122
1123         service = __cal_list_ug_create_return_results(p, ugd);
1124         c_ret_if(!service);
1125
1126         ug_send_result(ugd->ug, service);
1127
1128         service_destroy(service);
1129
1130         ug_destroy_me(ugd->ug);
1131 }
1132
1133 static void __cal_list_ug_add_controlbar( struct ug_data *ugd, Evas_Object *ly, const char* title)
1134 {
1135         Elm_Object_Item* navi_item = NULL;
1136
1137         cal_list_ug_data* p = evas_object_data_get(ly,"priv");
1138         c_retm_if(!p, "p is null");
1139
1140         navi_item = elm_naviframe_item_push(ugd->naviframe, title, NULL, NULL, ly, NULL);
1141         if (!navi_item)
1142         {
1143                 ERR("elm_naviframe_item_push returned null");
1144                 return;
1145         }
1146
1147         if (ugd->selection_mode == SELECTION_MODE_MULTIPLE) {
1148                 Evas_Object * attach_button = cal_util_add_toolbar_button(ugd->naviframe, "toolbar_button1", S_("IDS_COM_POP_ATTACH"), __cal_list_ug_attach, ly);
1149                 c_retm_if(!attach_button, "elm_toolbar_item_append returned null");
1150
1151                 p->bt = attach_button;
1152
1153                 elm_object_disabled_set(p->bt, EINA_TRUE);
1154         }
1155 }
1156
1157 void cal_list_ug_create(const char *title, struct ug_data *ugd)
1158 {
1159         Evas_Object *ly = __cal_list_ug_create_layout(ugd->naviframe, ugd);
1160         if (!ly)
1161                 return;
1162
1163         ugd->cont = ly;
1164
1165         __cal_list_ug_add_controlbar(ugd, ly, title);
1166 }
1167
1168 static void __cal_list_ug_searchbar_entry_changed_callback(void *data, Evas_Object *obj, void *event_info)
1169 {
1170         CAL_FN_START;
1171
1172         cal_list_ug_data *p = data;
1173         c_ret_if(!p);
1174
1175         CAL_FREE(p->searchtext);
1176
1177         p->searchtext = CAL_STRDUP(elm_object_text_get(obj));
1178
1179 // TODO: Show search result
1180         __cal_list_ug_update_callback(_calendar_event._uri, p);
1181
1182         if (0 < p->checked_event_count)
1183                 elm_object_disabled_set(p->bt, EINA_FALSE);
1184         else
1185                 elm_object_disabled_set(p->bt, EINA_TRUE);
1186
1187         __cal_list_ug_update_selection_info(p);
1188 }
1189
1190 static void __cal_list_ug_cancel_button_callback(void *data, Evas_Object *obj, void *event_info)
1191 {
1192         CAL_FN_START;
1193
1194         c_retm_if(!data, "data is null");
1195         cal_list_ug_data *p = data;
1196         Eina_List *l = NULL;
1197         cal_list_ug_item_data *item =NULL;
1198
1199         Evas_Object *en = elm_object_part_content_get(p->searchbar, "elm.swallow.content");
1200         c_retm_if(!en, "elm_object_part_content_get returned null");
1201
1202         Ecore_IMF_Context *imf_context = elm_entry_imf_context_get(en);
1203         c_retm_if(!imf_context, "elm_entry_imf_context_get returned null");
1204
1205         if (imf_context)
1206                 ecore_imf_context_input_panel_hide(imf_context);
1207
1208         if (0 < p->checked_event_count)
1209                 elm_object_disabled_set(p->bt, EINA_FALSE);
1210         else
1211                 elm_object_disabled_set(p->bt, EINA_TRUE);
1212
1213         p->checked_event_count = 0;
1214
1215         EINA_LIST_FOREACH(p->event_list, l, item) {
1216                 if (item != NULL && item->checked) {
1217                         p->checked_event_count++;
1218                 }
1219         }
1220
1221         __cal_list_ug_update_selection_info(p);
1222 }
1223
1224 static void __cal_list_ug_searchbar_entry_unfocused_callback(void *data, Evas_Object *obj, void *event_info)
1225 {
1226         c_retm_if(!data, "data is null.");
1227         cal_list_ug_data *p = data;
1228
1229         if (p->checked_event_count <= 0) {
1230                 elm_object_disabled_set(p->bt, EINA_TRUE);
1231         } else {
1232                 elm_object_disabled_set(p->bt, EINA_FALSE);
1233         }
1234
1235         __cal_list_ug_update_selection_info(p);
1236 }
1237
1238 static void __cal_list_ug_searchbar_clicked_callback(void *data, Evas_Object *obj, void *event_info)
1239 {
1240         c_retm_if(!data, "data is null.");
1241         cal_list_ug_data *p = data;
1242
1243         elm_object_disabled_set(p->bt, EINA_TRUE);
1244 }