7d1cb687675fe2b3e9450b82bec6d030925209b2
[apps/core/preloaded/calendar.git] / src / day-event-data.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 #include "day-event-data.h"
19 #include "query.h"
20 #include "list-data.h"
21
22 typedef struct {
23         cal_base_data_item base_item;
24         int cid;
25         calendar_record_h record;
26 } cal_day_event_data_event;
27
28 typedef struct {
29         Eina_List *list;
30         int maxsize;
31         int real_sz;
32         int start_index;
33 } cal_day_event_data_event_slice;
34
35 typedef struct {
36         int start_idx;
37         int end_idx;
38         int size;
39 } cal_day_event_data_event_slice_region;
40
41 typedef struct {
42         cal_base_data_s base_data;
43         struct appdata *ad;
44         Eina_List *event_list;
45         cal_day_event_data_event_slice event_slice_array[EVENT_SLICE_COUNT];
46         Eina_List *event_slice_region_list;
47 } cal_day_event_data_s;
48
49 static cal_base_data_h __cal_day_event_data_new(void *data);
50 static void __cal_day_event_data_delete(cal_base_data_h base_data);
51 static void __cal_day_event_data_load(cal_base_data_h day_event_data);
52 static void __cal_day_event_data_create_data_list(cal_base_data_h day_event_data);
53 static void __cal_day_event_data_delete_data_list(cal_base_data_h base_data);
54
55 static cal_base_data_operations event_data_operations= {
56         __cal_day_event_data_new,
57         __cal_day_event_data_delete,
58         __cal_day_event_data_load,
59         __cal_day_event_data_create_data_list,
60         __cal_day_event_data_delete_data_list,
61 };
62
63 static cal_base_data_h __cal_day_event_data_new(void *data)
64 {
65         c_retv_if(!data, NULL);
66
67         cal_day_event_data_s* p = NULL;
68
69         CAL_CALLOC(p, 1, cal_day_event_data_s);
70
71         p->ad = (struct appdata *)data;
72
73         return p;
74 }
75
76 cal_day_event_data_h cal_day_event_data_create(struct appdata *ad)
77 {
78         return cal_base_data_create(&event_data_operations, ad);
79 }
80
81
82 static cal_day_event_data_event *__cal_day_event_data_create_more_event(cal_day_event_data_s* p, cal_day_event_data_event *last_event)
83 {
84         c_retv_if(!p, NULL);
85         c_retv_if(!last_event, NULL);
86
87         cal_day_event_data_event *event = NULL;
88         CAL_CALLOC(event, 1, cal_day_event_data_event);
89
90         ((cal_base_data_item *)event)->text = strdup(">");
91         ((cal_base_data_item *)event)->color = ((cal_base_data_item *)last_event)->color;
92         ((cal_base_data_item *)event)->line_index = ((cal_base_data_item *)last_event)->line_index;
93         ((cal_base_data_item *)event)->height = 1;
94         ((cal_base_data_item *)event)->width_devider = EVEN_SLICE_MAX_EVENT_COUNT;
95         ((cal_base_data_item *)event)->column_index = EVEN_SLICE_MAX_EVENT_COUNT-1;
96
97         return event;
98 }
99
100 static void __cal_day_event_data_clear_event_slice_data(cal_day_event_data_s* p)
101 {
102         c_ret_if(!p);
103
104         int i = 0;
105         cal_day_event_data_event_slice *event_slice = NULL;
106
107         for(i=0; i<EVENT_SLICE_COUNT; i++) {
108                 event_slice = &p->event_slice_array[i];
109                 event_slice->start_index = 0;
110                 event_slice->real_sz = 0;
111         }
112 }
113
114 static void __cal_day_event_data_init_event_slice_data(cal_day_event_data_s* p)
115 {
116         c_ret_if(!p);
117
118         int i = 0;
119         int j = 0;
120         int k = 0;
121         int e = 0;
122         int sz = 0;
123         cal_day_event_data_event_slice *event_slice = NULL;
124         cal_day_event_data_event_slice *event_slice_tmp = NULL;
125         Eina_List *l;
126         cal_day_event_data_event *event = NULL;
127
128         __cal_day_event_data_clear_event_slice_data(p);
129
130         for(i = 0; i<EVENT_SLICE_COUNT; i++) {
131                 event_slice = &p->event_slice_array[i];
132                 if(NULL != event_slice->list) {
133                         k = 0;
134                         EINA_LIST_FOREACH(event_slice->list, l, event)
135                         {
136                                 if(NULL != event)
137                                 {
138                                         e = ((cal_base_data_item *)event)->line_index + ((cal_base_data_item *)event)->height;
139                                         for(j = ((cal_base_data_item *)event)->line_index; (j<e && j<EVENT_SLICE_COUNT); j++)
140                                         {
141                                                 event_slice_tmp = &p->event_slice_array[j];
142                                                 if(j > ((cal_base_data_item *)event)->line_index)
143                                                 {
144                                                         if(0 == k) {
145                                                                 event_slice_tmp->start_index =  event_slice->start_index + 1;
146                                                         } else {
147                                                                 event_slice_tmp->start_index =  event_slice_tmp->start_index + 1;
148                                                         }
149                                                 }
150                                                 sz = eina_list_count(event_slice_tmp->list);
151                                                 event_slice_tmp->real_sz = event_slice_tmp->start_index + sz;
152                                         }
153                                         k = 1;
154                                 }
155
156                         }
157                 }
158         }
159 }
160
161 static void __cal_day_event_data_delete_event_slice_regions(cal_day_event_data_s* p)
162 {
163         c_ret_if(!p);
164
165         cal_day_event_data_event_slice_region *even_slice_region = NULL;
166         Eina_List *l = NULL;
167
168         EINA_LIST_FOREACH(p->event_slice_region_list, l, even_slice_region) {
169                 if(even_slice_region)
170                         free(even_slice_region);
171         }
172
173         p->event_slice_region_list = eina_list_free(p->event_slice_region_list);
174 }
175
176 static void __cal_day_event_data_delete_events(cal_day_event_data_s* p)
177 {
178         c_ret_if(!p);
179
180         int i;
181         cal_day_event_data_event_slice *event_slice = NULL;
182         cal_day_event_data_event *event = NULL;
183
184         for (i = 0; i < EVENT_SLICE_COUNT; i++) {
185                 Eina_List *l;
186                 event_slice = &p->event_slice_array[i];
187
188                 if (event_slice) {
189                         if (event_slice->list) {
190                                 EINA_LIST_FOREACH(event_slice->list, l, event) {
191                                         if (event) {
192                                                 if (((cal_base_data_item *)event)->text) {
193                                                         CAL_FREE(((cal_base_data_item *)event)->text);
194                                                 }
195                                                 CAL_FREE(event);
196                                         }
197                                 }
198                         }
199
200                         eina_list_free(event_slice->list);
201                         event_slice->list = NULL;
202                 }
203         }
204 }
205
206 static void __cal_day_event_data_delete_data_list(cal_base_data_h base_data)
207 {
208         c_ret_if(!base_data);
209         c_ret_if(!((cal_base_data_s *)base_data)->base_data_list);
210
211         cal_day_event_data_event *event = NULL;
212         Eina_List *l;
213
214         EINA_LIST_FOREACH(((cal_base_data_s *)base_data)->base_data_list, l, event) {
215                 if (event) {
216                         if (!event->record) {
217                                 ((cal_base_data_s *)base_data)->base_data_list = eina_list_remove(((cal_base_data_s *)base_data)->base_data_list, event);
218
219                                 if (((cal_base_data_item *)event)->text) {
220                                         CAL_FREE(((cal_base_data_item *)event)->text);
221                                 }
222
223                                 free(event);
224                         }
225                 }
226         }
227
228         eina_list_free(((cal_base_data_s *)base_data)->base_data_list);
229
230         ((cal_base_data_s *)base_data)->base_data_list = NULL;
231 }
232
233 static void __cal_day_event_data_create_event_dispaly_data_list(cal_day_event_data_s* p)
234 {
235         c_ret_if(!p);
236
237         cal_day_event_data_event_slice_region *event_slice_region = NULL;
238         cal_day_event_data_event_slice *event_slice = NULL;
239         cal_day_event_data_event *event = NULL;
240
241         Eina_List *l;
242         Eina_List *l2;
243         int i = 0;
244
245         int width_radix = -1;
246         int column_index = -1;
247
248         cal_base_data_destroy_data_list(p);
249
250         EINA_LIST_FOREACH(p->event_slice_region_list, l, event_slice_region) {
251                 if (event_slice_region) {
252                         if (0 < event_slice_region->size) {
253                                 for ( i = event_slice_region->start_idx; i <= event_slice_region->end_idx; i++) {
254
255                                         event_slice = &p->event_slice_array[i];
256                                         if (EVEN_SLICE_MAX_EVENT_COUNT < event_slice_region->size) {
257                                                 width_radix = EVEN_SLICE_MAX_EVENT_COUNT;
258                                         } else {
259                                                 width_radix = event_slice_region->size;
260                                         }
261
262                                         column_index = event_slice->start_index;
263
264                                         EINA_LIST_FOREACH(event_slice->list, l2, event) {
265                                                 if (event) {
266                                                         if(column_index < EVEN_SLICE_MAX_EVENT_COUNT-1) {
267                                                                 ((cal_base_data_item *)event)->width_devider = width_radix;
268                                                                 ((cal_base_data_item *)event)->column_index = column_index;
269
270                                                                 ((cal_base_data_s *)p)->base_data_list = eina_list_append(((cal_base_data_s *)p)->base_data_list, event);
271
272                                                         } else {
273                                                                 if (column_index == EVEN_SLICE_MAX_EVENT_COUNT-1) {
274                                                                         cal_day_event_data_event *event_more = __cal_day_event_data_create_more_event(p, event);
275                                                                         c_ret_if(!event_more);
276
277                                                                         ((cal_base_data_s *)p)->base_data_list = eina_list_append(((cal_base_data_s *)p)->base_data_list, event_more);
278
279                                                                         break;
280                                                                 }
281
282                                                                 break;
283                                                         }
284                                                         column_index ++;
285                                                 }
286                                         }
287                                 }
288                         }
289                 }
290         }
291
292 }
293
294 static void __cal_day_event_data_create_data_list(cal_base_data_h base_data)
295 {
296         c_ret_if(!base_data);
297
298         cal_day_event_data_s* p = (cal_day_event_data_s*)base_data;
299
300         int i = 0;
301         int j = 0;
302
303         cal_day_event_data_event_slice *event_slice = NULL;
304         cal_day_event_data_event_slice_region *event_slice_region = NULL;
305
306         __cal_day_event_data_init_event_slice_data(p);
307
308         __cal_day_event_data_delete_event_slice_regions(p);
309
310         while(i < EVENT_SLICE_COUNT) {
311
312                 event_slice = &p->event_slice_array[i];
313
314                 if(0 == event_slice->start_index) {
315                         if(0 == event_slice->real_sz){
316                                 i++;
317                                 continue;
318                         }
319
320                         CAL_CALLOC(event_slice_region, 1, cal_day_event_data_event_slice_region);
321
322                         event_slice_region->start_idx = i;
323                         event_slice_region->end_idx = i;
324                         event_slice_region->size = event_slice->real_sz;
325
326                         if(EVENT_SLICE_COUNT == i+1) {
327                                 p->event_slice_region_list = eina_list_append(p->event_slice_region_list, event_slice_region);
328                         }
329
330                         for(j = i+1; j < EVENT_SLICE_COUNT; j++) {
331                                 event_slice = &p->event_slice_array[j];
332
333                                 if((j == EVENT_SLICE_COUNT - 1) && (0 != event_slice->start_index)) {
334                                         if(event_slice->real_sz > event_slice_region->size) {
335                                                 event_slice_region->size = event_slice->real_sz;
336                                         }
337                                         event_slice_region->end_idx = j;
338                                         p->event_slice_region_list = eina_list_append(p->event_slice_region_list, event_slice_region);
339                                 } else if(0 == event_slice->start_index) {
340                                         event_slice_region->end_idx = j - 1;
341                                         p->event_slice_region_list = eina_list_append(p->event_slice_region_list, event_slice_region);
342                                         i = j;
343                                         break;
344                                 } else {
345                                         if(event_slice->real_sz > event_slice_region->size) {
346                                                 event_slice_region->size = event_slice->real_sz;
347                                         }
348                                 }
349                         }
350
351                         if(EVENT_SLICE_COUNT <= j) {
352                                 break;
353                         }
354                 }
355         }
356
357         __cal_day_event_data_create_event_dispaly_data_list(p);
358 }
359
360 static char* __cal_day_event_data_get_event_text(calendar_record_h record)
361 {
362         c_retv_if(!record, NULL);
363
364
365         char *title = _calendar_get_summary(record);
366
367         char *location = _calendar_get_location(record);
368
369         char *text = NULL;
370
371         if (CAL_STRLEN(location)) {
372                 text = g_strdup_printf("%s, %s", title, location);
373                 free(title);
374                 free(location);
375         } else {
376                 text = title;
377         }
378
379         return text;
380 }
381
382 static int __cal_day_event_data_sort_event(const void *d1, const void *d2)
383 {
384         const cal_base_data_item  *t1 = d1;
385         const cal_base_data_item  *t2 = d2;
386
387         if (!t1)
388                 return 1;
389         if (!t2)
390                 return -1;
391
392         return t1->height < t2->height ? 1 : -1;
393 }
394
395 static void  __cal_day_event_data_insert_event_to_event_slice(cal_day_event_data_s* p, cal_day_event_data_event *event)
396 {
397         c_ret_if(!p);
398         c_ret_if(!event);
399
400         cal_day_event_data_event_slice *event_slice;
401
402         event_slice = &p->event_slice_array[((cal_base_data_item *)event)->line_index];
403         c_ret_if(!event_slice);
404
405         event_slice->list = eina_list_sorted_insert(event_slice->list, __cal_day_event_data_sort_event, event);
406 }
407
408 static cal_base_data_item_h __cal_day_event_data_create_item(cal_base_data_h base_data, void  *data)
409 {
410         c_retv_if(!data, NULL);
411         c_retv_if(!base_data, NULL);
412
413         cal_day_event_data_s *p = (cal_day_event_data_s *)base_data;
414         c_retv_if(!p, NULL);
415         c_retv_if(!p->ad, NULL);
416
417         calendar_record_h record = data;
418
419         cal_day_event_data_event *event;
420         calendar_time_s start_time = {0};
421         calendar_time_s end_time = {0};
422
423         time_t st, et;
424         cal_util_get_day_time_t(&p->ad->base_tm, &st, &et);
425
426         int cid = _calendar_get_record_index(record);
427
428         _calendar_get_start_time(record, &start_time);
429         _calendar_get_end_time(record, &end_time);
430
431         int hh = (start_time.time.utime - st)/CAL_SECONDS_FOR_THIRTY_MINUTES;
432         if (hh < 0)
433                 hh = 0;
434
435         end_time.time.utime = ((end_time.time.utime - 1 - st)/CAL_SECONDS_FOR_THIRTY_MINUTES) + 1;
436         if (end_time.time.utime > CAL_HALF_HOURS_FOR_DAY)
437                 end_time.time.utime = CAL_HALF_HOURS_FOR_DAY;
438
439         int sz = end_time.time.utime - hh;
440         if (sz <= 0)
441                 sz = 1;
442
443         CAL_CALLOC(event, 1, cal_day_event_data_event);
444
445         _calendar_get_calendar_color(record, &((cal_base_data_item *)event)->color);
446         ((cal_base_data_item *)event)->text = __cal_day_event_data_get_event_text(record);
447         ((cal_base_data_item *)event)->line_index = hh;
448         ((cal_base_data_item *)event)->height = sz;
449         ((cal_base_data_item *)event)->width_devider = -1;
450         ((cal_base_data_item *)event)->column_index = -1;
451         event->record = record;
452         event->cid = cid;
453
454         return event;
455 }
456
457 static cal_day_event_data_event *__cal_day_event_data_find_event(cal_day_event_data_s* p, int cid)
458 {
459         c_retv_if(!p, NULL);
460
461         int i;
462         cal_day_event_data_event_slice *even_slice;
463         cal_day_event_data_event *event;
464
465         Eina_List *l;
466
467         for (i = 0; i < EVENT_SLICE_COUNT; i++) {
468                 even_slice = &p->event_slice_array[i];
469
470                 EINA_LIST_FOREACH(even_slice->list, l, event)
471                 {
472                         if (event && event->cid == cid)
473                                 return event;
474                 }
475         }
476
477         return NULL;
478 }
479
480 static void __cal_day_event_data_add_event(cal_day_event_data_s* p, calendar_record_h record)
481 {
482         c_ret_if(!p);
483         c_ret_if(!p->ad);
484         c_ret_if(!record);
485
486         cal_day_event_data_event *event;
487
488         int cid = _calendar_get_record_index(record);
489
490         event = __cal_day_event_data_find_event(p, cid);
491
492         if (event) {
493                 event->record = record;
494                 return;
495         }
496
497         event = __cal_day_event_data_create_item(p, record);
498         c_ret_if(!event);
499
500         __cal_day_event_data_insert_event_to_event_slice(p, event);
501 }
502
503 static void __cal_day_event_data_add_events(cal_day_event_data_s* p)
504 {
505         c_ret_if(!p);
506         c_ret_if(!p->event_list);
507         c_ret_if(!p->ad);
508
509         Eina_List *l;
510         calendar_record_h record = NULL;
511
512         EINA_LIST_FOREACH(p->event_list, l, record) {
513                 if (!_calendar_is_allday_record(record))
514                         __cal_day_event_data_add_event(p, record);
515         }
516 }
517
518 static void __cal_day_event_data_load(cal_base_data_h day_event_data)
519 {
520         c_ret_if(!day_event_data);
521         cal_day_event_data_s* p = (cal_day_event_data_s*)day_event_data;
522
523         c_ret_if(!p->ad);
524
525         __cal_day_event_data_delete_event_slice_regions(p);
526
527         __cal_day_event_data_delete_events(p);
528
529         if(p->event_list)
530                 _calendar_free_record_list(&p->event_list);
531
532         struct tm tm_start = p->ad->base_tm;
533         tm_start.tm_hour = 0;
534         tm_start.tm_min = 0;
535         tm_start.tm_sec = 0;
536
537         struct tm tm_end = tm_start;
538         tm_end.tm_hour = 23;
539         tm_end.tm_min = 59;
540         tm_end.tm_sec = 59;
541
542         p->event_list = _calendar_get_all_instance_list(&tm_start, &tm_end);
543         c_ret_if(!p->event_list);
544
545         __cal_day_event_data_add_events(p);
546
547 }
548
549 static void __cal_day_event_data_delete(cal_base_data_h base_data)
550 {
551         c_ret_if(!base_data);
552
553         cal_day_event_data_s* p = (cal_day_event_data_s*)base_data;
554
555         cal_base_data_destroy_data_list(p);
556
557         __cal_day_event_data_delete_event_slice_regions(p);
558
559         __cal_day_event_data_delete_events(p);
560
561         if(p->event_list)
562                 _calendar_free_record_list(&p->event_list);
563
564         CAL_FREE(p);
565 }
566
567 calendar_record_h cal_day_event_data_get_event_record(cal_day_event_data_event_h event_data)
568 {
569         c_retv_if(!event_data, NULL);
570
571         cal_day_event_data_event* event_data_s = (cal_day_event_data_event*)event_data;
572
573         return event_data_s->record;
574 }
575
576 static void __cal_day_event_data_remove_event_form_event_slice(cal_day_event_data_s* p, cal_day_event_data_event* event)
577 {
578         c_ret_if(!p);
579         c_ret_if(!event);
580
581         cal_day_event_data_event_slice *event_slice;
582
583         event_slice = &p->event_slice_array[((cal_base_data_item *)event)->line_index];
584
585         event_slice->list = eina_list_remove(event_slice->list, event);
586 }
587
588 void cal_day_event_data_sort(cal_day_event_data_h day_event_data, cal_day_event_data_event_h event_data_h)
589 {
590         c_ret_if(!day_event_data);
591         c_ret_if(!event_data_h);
592
593         cal_day_event_data_s* p = (cal_day_event_data_s*)day_event_data;
594         cal_day_event_data_event* event_data = (cal_day_event_data_event*)event_data_h;
595
596         cal_day_event_data_event_slice *event_slice;
597
598         event_slice = &p->event_slice_array[((cal_base_data_item *)event_data)->line_index];
599         c_ret_if(!event_slice->list);
600
601         event_slice->list = eina_list_sort(event_slice->list, 0, __cal_day_event_data_sort_event);
602 }
603
604 void cal_day_event_data_update_event(cal_day_event_data_h day_event_data, cal_day_event_data_event_h event_data_h, int line_index, int height)
605 {
606         c_ret_if(!day_event_data);
607         c_ret_if(!event_data_h);
608
609         cal_day_event_data_s* p = (cal_day_event_data_s*)day_event_data;
610
611         cal_day_event_data_event *event_data = (cal_day_event_data_event*)event_data_h;
612         c_ret_if(!event_data->record);
613
614         time_t time_diff = (line_index - ((cal_base_data_item *)event_data)->line_index)*(30*60);
615
616         time_t time_diff_end = height*(30*60);
617         calendar_record_h record = NULL;
618
619         int cid = _calendar_get_record_index(event_data->record);
620
621         if (_calendar_get_record_type(event_data->record) == _CALENDAR_RECORD_TYPE_EVENT) {
622                 record = event_data->record;
623         } else {
624                 record = _calendar_get_record_with_index(cid);
625         }
626
627         calendar_time_s start_time = {0};
628         calendar_time_s end_time = {0};
629
630         _calendar_get_start_time(record, &start_time);
631         _calendar_get_end_time(record, &end_time);
632
633         start_time.time.utime += time_diff;
634         _calendar_set_start_time(record, &start_time);
635
636         start_time.time.utime += time_diff_end;
637         _calendar_set_end_time(record, &start_time);
638
639         cal_main_remove_db_changed_callback(p->ad);
640
641         calendar_error_e error = CALENDAR_ERROR_NONE;
642
643         error = calendar_db_update_record(record);
644         c_warn_if(error != CALENDAR_ERROR_NONE, "calendar_db_update_record() is faild(%x)", error);
645
646         if (event_data->record != record) {
647                 error = calendar_record_destroy(record, true);
648                 c_warn_if(error != CALENDAR_ERROR_NONE, "calendar_record_destroy() is faild(%x)", error);
649         }
650
651         cal_main_add_db_changed_callback(p->ad);
652
653         __cal_day_event_data_remove_event_form_event_slice(day_event_data, event_data_h);
654         cal_base_data_set_item_height(event_data_h, height);
655         cal_base_data_set_item_line_index(event_data_h, line_index);
656         __cal_day_event_data_insert_event_to_event_slice(p, event_data);
657 }